diff --git a/.ci/azure/linux.yml b/.ci/azure/linux.yml index 74cf6a91c2d4be..0e3da7f417d751 100644 --- a/.ci/azure/linux.yml +++ b/.ci/azure/linux.yml @@ -1,3 +1,12 @@ +trigger: + branches: + include: + - master + - releases/* + paths: + exclude: + - docs/* + resources: repositories: - repository: openvino_contrib @@ -12,6 +21,16 @@ resources: jobs: - job: Lin + strategy: + matrix: + Dynamic: + CMAKE_BUILD_SHARED_LIBS: 'ON' + PYTHON_STATIC_ARGS: + Static: + CMAKE_BUILD_SHARED_LIBS: 'OFF' + PYTHON_STATIC_ARGS: -m "not dynamic_library and not template_plugin" + maxParallel: 2 + # About 150% of total time timeoutInMinutes: 90 @@ -117,6 +136,9 @@ jobs: -DVERBOSE_BUILD=ON -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DENABLE_PYTHON=ON + -DBUILD_SHARED_LIBS=$(CMAKE_BUILD_SHARED_LIBS) + -DENABLE_GNA=$(CMAKE_BUILD_SHARED_LIBS) + -DENABLE_ONEDNN_FOR_GPU=$(CMAKE_BUILD_SHARED_LIBS) -DPYTHON_EXECUTABLE=/usr/bin/python3.8 -DENABLE_WHEEL=ON -DENABLE_TESTS=ON @@ -174,10 +196,12 @@ jobs: - script: $(INSTALL_DIR)/samples/cpp/build_samples.sh workingDirectory: $(BUILD_SAMPLES_DIR) displayName: 'Build cpp samples' + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') - script: $(INSTALL_DIR)/samples/c/build_samples.sh workingDirectory: $(BUILD_SAMPLES_DIR) displayName: 'Build c samples' + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') - script: rm -fr $(BUILD_DIR) displayName: 'Clean build dir' @@ -187,13 +211,13 @@ jobs: - script: | export DATA_PATH=$(MODELS_PATH) export MODELS_PATH=$(MODELS_PATH) - . $(SETUPVARS) -pyver 3.8 && python3 -m pytest -s $(INSTALL_TEST_DIR)/pyngraph --junitxml=TEST-Pyngraph.xml --ignore=$(INSTALL_TEST_DIR)/pyngraph/tests/test_onnx/test_zoo_models.py --ignore=$(INSTALL_TEST_DIR)/pyngraph/tests/test_onnx/test_backend.py + . $(SETUPVARS) -pyver 3.8 && python3 -m pytest -s $(INSTALL_TEST_DIR)/pyngraph $(PYTHON_STATIC_ARGS) --junitxml=TEST-Pyngraph.xml --ignore=$(INSTALL_TEST_DIR)/pyngraph/tests/test_onnx/test_zoo_models.py --ignore=$(INSTALL_TEST_DIR)/pyngraph/tests/test_onnx/test_backend.py displayName: 'nGraph Python Bindings Tests' continueOnError: false - script: | export MO_ROOT=$(INSTALL_DIR)/tools/model_optimizer - . $(SETUPVARS) -pyver 3.8 && python3 -m pytest -s $(INSTALL_DIR)/tools/model_optimizer/unit_tests --junitxml=TEST-ModelOptimizer.xml + . $(SETUPVARS) -pyver 3.8 && python3 -m pytest -s $(INSTALL_DIR)/tests/model_optimizer/unit_tests --junitxml=TEST-ModelOptimizer.xml displayName: 'Model Optimizer UT' continueOnError: false @@ -226,6 +250,7 @@ jobs: - script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/gnaUnitTests --gtest_output=xml:TEST-gnaUnitTests.xml displayName: 'GNA UT' continueOnError: false + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') - script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/vpuUnitTests --gtest_output=xml:TEST-vpuUnitTests.xml displayName: 'VPU UT' @@ -246,6 +271,7 @@ jobs: - script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/cpuFuncTests --gtest_filter=*smoke* --gtest_print_time=1 --gtest_output=xml:TEST-cpuFuncTests.xml displayName: 'CPU FuncTests' continueOnError: false + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'OFF') - script: | export DATA_PATH=$(MODELS_PATH) @@ -258,7 +284,7 @@ jobs: export DATA_PATH=$(MODELS_PATH) export MODELS_PATH=$(MODELS_PATH) cd $(REPO_DIR)/inference-engine/ie_bridges/python/tests - . $(SETUPVARS) -pyver 3.8 && python3 -m pytest --junitxml=TEST-PythonAPI.xml + . $(SETUPVARS) -pyver 3.8 && python3 -m pytest --junitxml=TEST-PythonAPI.xml $(PYTHON_STATIC_ARGS) displayName: 'Python API Tests' continueOnError: false diff --git a/.ci/azure/linux_conditional_compilation.yml b/.ci/azure/linux_conditional_compilation.yml index 1a69b7c3dcd9a2..d60bc412cc9900 100644 --- a/.ci/azure/linux_conditional_compilation.yml +++ b/.ci/azure/linux_conditional_compilation.yml @@ -1,3 +1,12 @@ +trigger: + branches: + include: + - master + - releases/* + paths: + exclude: + - docs/* + jobs: - job: LinCC # About 150% of total time diff --git a/.ci/azure/linux_ngraph_onnx.yml b/.ci/azure/linux_ngraph_onnx.yml index 8218a0874cdd30..6858024e877250 100644 --- a/.ci/azure/linux_ngraph_onnx.yml +++ b/.ci/azure/linux_ngraph_onnx.yml @@ -1,14 +1,21 @@ +trigger: + branches: + include: + - master + - releases/* + paths: + exclude: + - docs/* + jobs: - job: OpenVINO_ONNX_CI strategy: matrix: Release: BUILD_TYPE: 'Release' - PROTOBUF_LITE: 'ON' TOX_COMMAND: 'tox && tox -e zoo_models' Debug: BUILD_TYPE: 'Debug' - PROTOBUF_LITE: 'ON' TOX_COMMAND: 'tox' maxParallel: 2 @@ -77,10 +84,10 @@ jobs: condition: ne(variables['BUILD_TYPE'], 'Debug') - script: sudo docker build --tag=openvino-onnx-ci-image --file=.ci/openvino-onnx/Dockerfile --build-arg BUILD_TYPE=$(BUILD_TYPE) --build-arg PROTOBUF_LITE=$(PROTOBUF_LITE) . - displayName: 'Docker build $(BUILD_TYPE) protobuf-lite: $(PROTOBUF_LITE)' + displayName: 'Docker build $(BUILD_TYPE)' - script: sudo fallocate -l 64G /swapfile ; sudo mkswap /swapfile ; sudo swapon /swapfile ; df ; free -h displayName: 'Create swap' - script: sudo docker run --name openvino-onnx-ci-container --volume $(MODELS_DIR)/models_data/model_zoo/onnx_model_zoo_$(ONNX_MODEL_ZOO_SHA):/root/.onnx/model_zoo/onnx_model_zoo --volume $(MODELS_DIR)/msft:/root/.onnx/model_zoo/MSFT openvino-onnx-ci-image /bin/bash -c "$(TOX_COMMAND)" - displayName: 'Docker run $(BUILD_TYPE) protobuf-lite: $(PROTOBUF_LITE)' + displayName: 'Docker run $(BUILD_TYPE)' diff --git a/.ci/azure/linux_onnxruntime.yml b/.ci/azure/linux_onnxruntime.yml index 4fd14f2c1b1e39..7a7c4754610bf8 100644 --- a/.ci/azure/linux_onnxruntime.yml +++ b/.ci/azure/linux_onnxruntime.yml @@ -1,3 +1,11 @@ +trigger: + branches: + include: + - releases/* + paths: + exclude: + - docs/* + jobs: - job: onnxruntime timeoutInMinutes: 90 diff --git a/.ci/azure/mac.yml b/.ci/azure/mac.yml index 4534c08b0651d5..0df0c05a2e226a 100644 --- a/.ci/azure/mac.yml +++ b/.ci/azure/mac.yml @@ -1,3 +1,12 @@ +trigger: + branches: + include: + - master + - releases/* + paths: + exclude: + - docs/* + resources: repositories: - repository: openvino_contrib diff --git a/.ci/azure/windows.yml b/.ci/azure/windows.yml index e234836ce1bc80..72642660043fdc 100644 --- a/.ci/azure/windows.yml +++ b/.ci/azure/windows.yml @@ -1,3 +1,12 @@ +trigger: + branches: + include: + - master + - releases/* + paths: + exclude: + - docs/* + resources: repositories: - repository: openvino_contrib @@ -12,6 +21,14 @@ resources: jobs: - job: Win + strategy: + matrix: + Dynamic: + CMAKE_BUILD_SHARED_LIBS: 'ON' + Static: + CMAKE_BUILD_SHARED_LIBS: 'OFF' + maxParallel: 2 + # About 150% of total time timeoutInMinutes: 120 @@ -102,7 +119,7 @@ jobs: - script: | set PATH=$(WORK_DIR)\ninja-win;%PATH% - call "$(MSVS_VARS_PATH)" && cmake -GNinja -DENABLE_REQUIREMENTS_INSTALL=OFF -DENABLE_FASTER_BUILD=ON -DENABLE_TEMPLATE_PLUGIN=ON -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DENABLE_TESTS=ON -DENABLE_STRICT_DEPENDENCIES=OFF -DENABLE_PYTHON=ON -DPYTHON_EXECUTABLE="C:\hostedtoolcache\windows\Python\3.7.6\x64\python.exe" -DIE_EXTRA_MODULES=$(OPENVINO_CONTRIB_REPO_DIR)\modules -DCMAKE_C_COMPILER:PATH="$(MSVC_COMPILER_PATH)" -DCMAKE_CXX_COMPILER:PATH="$(MSVC_COMPILER_PATH)" $(REPO_DIR) + call "$(MSVS_VARS_PATH)" && cmake -GNinja -DENABLE_CLDNN=$(CMAKE_BUILD_SHARED_LIBS) -DBUILD_SHARED_LIBS=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_REQUIREMENTS_INSTALL=OFF -DENABLE_FASTER_BUILD=ON -DENABLE_TEMPLATE_PLUGIN=ON -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DENABLE_TESTS=ON -DENABLE_STRICT_DEPENDENCIES=OFF -DENABLE_PYTHON=ON -DPYTHON_EXECUTABLE="C:\hostedtoolcache\windows\Python\3.7.6\x64\python.exe" -DIE_EXTRA_MODULES=$(OPENVINO_CONTRIB_REPO_DIR)\modules -DCMAKE_C_COMPILER:PATH="$(MSVC_COMPILER_PATH)" -DCMAKE_CXX_COMPILER:PATH="$(MSVC_COMPILER_PATH)" $(REPO_DIR) workingDirectory: $(BUILD_DIR) displayName: 'CMake' @@ -135,10 +152,12 @@ jobs: - script: $(INSTALL_DIR)\samples\cpp\build_samples_msvc.bat workingDirectory: $(BUILD_SAMPLES_DIR) displayName: 'Build cpp samples' + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') - script: $(INSTALL_DIR)\samples\c\build_samples_msvc.bat workingDirectory: $(BUILD_SAMPLES_DIR) displayName: 'Build c samples' + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') - script: rd /Q /S $(BUILD_DIR) displayName: 'Clean build dir' @@ -152,10 +171,12 @@ jobs: - script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\paddlepaddle_tests --gtest_print_time=1 --gtest_filter=-backend_api.config_unsupported:*IE_GPU* --gtest_output=xml:TEST-PaddlePaddle.xml displayName: 'PaddlePaddle Frontend UT' continueOnError: false + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') - script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\tensorflow_tests --gtest_print_time=1 --gtest_output=xml:TEST-Tensorflow.xml displayName: 'Tensorflow Frontend UT' continueOnError: false + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') - script: | set PATH=$(IB_DIR);%PATH% @@ -197,6 +218,7 @@ jobs: call $(SETUPVARS) && "$(IB_TESTCONSOLE)" $(INSTALL_TEST_DIR)\cpuFuncTests.exe --gtest_filter=*smoke*:-*CompareWithRefs/base_size=16_pre_nms_topn=100_post_nms_topn=100_nms_thresh=0.7_feat_stride=1_min_size=1_ratio*:*smoke_GRUSequenceCommonZeroClip/GRUSequenceTest.CompareWithRefs/mode=CONVERT_TO_TI_MAX_SEQ_LEN_CONST_seq_lengths* --gtest_output=xml:TEST-cpuFuncTests-IB.xml /testlevel=24 displayName: 'CPU FuncTests - IB' continueOnError: false + condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'OFF') - script: | set DATA_PATH=$(MODELS_PATH) diff --git a/.ci/azure/windows_conditional_compilation.yml b/.ci/azure/windows_conditional_compilation.yml index 80c89e8d20f28e..2d0fdc63d7ceb7 100644 --- a/.ci/azure/windows_conditional_compilation.yml +++ b/.ci/azure/windows_conditional_compilation.yml @@ -1,3 +1,12 @@ +trigger: + branches: + include: + - master + - releases/* + paths: + exclude: + - docs/* + jobs: - job: WinCC # About 150% of total time diff --git a/.ci/openvino-onnx/Dockerfile b/.ci/openvino-onnx/Dockerfile index ada3c36adb126c..0992ea21220e04 100644 --- a/.ci/openvino-onnx/Dockerfile +++ b/.ci/openvino-onnx/Dockerfile @@ -4,7 +4,6 @@ LABEL version=2021.03.30.1 # Build configuration arguments ARG BUILD_TYPE=Release -ARG PROTOBUF_LITE=ON ARG http_proxy ARG https_proxy @@ -69,8 +68,7 @@ RUN cmake .. \ -DPYTHON_EXECUTABLE=/usr/bin/python3 \ -DNGRAPH_ONNX_FRONTEND_ENABLE=ON \ -DOPENVINO_DEBUG_ENABLE=OFF \ - -DCMAKE_INSTALL_PREFIX=/openvino/dist \ - -DNGRAPH_USE_PROTOBUF_LITE=${PROTOBUF_LITE} + -DCMAKE_INSTALL_PREFIX=/openvino/dist RUN make -j $(nproc) install # Run tests via tox diff --git a/.ci/openvino-onnx/Jenkinsfile b/.ci/openvino-onnx/Jenkinsfile index 5581c7c2ea8ad0..cfe866c23ebbfe 100644 --- a/.ci/openvino-onnx/Jenkinsfile +++ b/.ci/openvino-onnx/Jenkinsfile @@ -6,9 +6,8 @@ DOCKER_IMAGE_TAG = "openvino-onnx-ci-image" ONNX_MODEL_ZOO_SHA = "d58213534f2a4d1c4b19ba62b3bb5f544353256e" BACKEND_CONFIGURATIONS = [ - [ name: "Release", build_type: "Release", protobuf_lite : "OFF" ], - [ name: "Debug", build_type: "Debug", protobuf_lite : "OFF" ], - [ name: "Rel_Lite", build_type: "Release", protobuf_lite : "ON" ], + [ name: "Release", build_type: "Release" ], + [ name: "Debug", build_type: "Debug" ], ] // workaround for aborting previous builds on PR update @@ -111,7 +110,6 @@ def buildDockerImage(Map configuration, String workdir) { sh """ docker build --tag=${docker_image_tag} \ --build-arg BUILD_TYPE=${configuration.build_type} \ - --build-arg PROTOBUF_LITE=${configuration.protobuf_lite} \ --file=.ci/openvino-onnx/Dockerfile \ --build-arg http_proxy=${HTTP_PROXY} \ --build-arg https_proxy=${HTTPS_PROXY} . diff --git a/CMakeLists.txt b/CMakeLists.txt index b7b7f1fb86fa48..b0c6d805e6d504 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,13 +85,9 @@ include(cmake/test_model_zoo.cmake) add_subdirectory(thirdparty) add_subdirectory(openvino) add_subdirectory(ngraph) -add_subdirectory(runtime) add_subdirectory(inference-engine) - -# for Template plugin -openvino_developer_export_targets(COMPONENT ngraph TARGETS ngraph_backend interpreter_backend) +add_subdirectory(runtime) include(cmake/extra_modules.cmake) - if(ENABLE_SAMPLES) add_subdirectory(samples) endif() diff --git a/README.md b/README.md index 97f2ed60b37e8b..b4b3f49f81041e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # OpenVINO™ Toolkit -[![Stable release](https://img.shields.io/badge/version-2021.4.1-green.svg)](https://github.com/openvinotoolkit/openvino/releases/tag/2021.4.1) +[![Stable release](https://img.shields.io/badge/version-2021.4.2-green.svg)](https://github.com/openvinotoolkit/openvino/releases/tag/2021.4.2) [![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](LICENSE) ![GitHub branch checks state](https://img.shields.io/github/checks-status/openvinotoolkit/openvino/master?label=GitHub%20checks) ![Azure DevOps builds (branch)](https://img.shields.io/azure-devops/build/openvinoci/b2bab62f-ab2f-4871-a538-86ea1be7d20f/13?label=Public%20CI) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 711495b904527b..662b829478c059 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -103,17 +103,22 @@ if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") endif() if(WIN32 AND X86_64) - #TODO: add target_path to be platform specific as well, to avoid following if + # TODO: add target_path to be platform specific as well, to avoid following if RESOLVE_DEPENDENCY(TBB ARCHIVE_WIN "tbb2020_20200415_win.zip" TARGET_PATH "${TEMP}/tbb" ENVIRONMENT "TBBROOT" SHA256 "f1c9b9e2861efdaa01552bd25312ccbc5feeb45551e5f91ae61e29221c5c1479") - RESOLVE_DEPENDENCY(TBBBIND_2_5 - ARCHIVE_WIN "tbbbind_2_5_static_win_v1.zip" - TARGET_PATH "${TEMP}/tbbbind_2_5" - ENVIRONMENT "TBBBIND_2_5_ROOT" - SHA256 "a67afeea8cf194f97968c800dab5b5459972908295242e282045d6b8953573c1") + if(ENABLE_TBBBIND_2_5) + RESOLVE_DEPENDENCY(TBBBIND_2_5 + ARCHIVE_WIN "tbbbind_2_5_static_win_v1.zip" + TARGET_PATH "${TEMP}/tbbbind_2_5" + ENVIRONMENT "TBBBIND_2_5_ROOT" + SHA256 "a67afeea8cf194f97968c800dab5b5459972908295242e282045d6b8953573c1") + else() + message(WARNING "prebuilt TBBBIND_2_5 is not available. + Build oneTBB from sources and set TBBROOT environment var before OpenVINO cmake configure") + endif() elseif(ANDROID) # Should be before LINUX due LINUX is detected as well RESOLVE_DEPENDENCY(TBB ARCHIVE_ANDROID "tbb2020_20200404_android.tgz" @@ -126,11 +131,16 @@ if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") TARGET_PATH "${TEMP}/tbb" ENVIRONMENT "TBBROOT" SHA256 "95b2f3b0b70c7376a0c7de351a355c2c514b42c4966e77e3e34271a599501008") - RESOLVE_DEPENDENCY(TBBBIND_2_5 - ARCHIVE_LIN "tbbbind_2_5_static_lin_v2.tgz" - TARGET_PATH "${TEMP}/tbbbind_2_5" - ENVIRONMENT "TBBBIND_2_5_ROOT" - SHA256 "865e7894c58402233caf0d1b288056e0e6ab2bf7c9d00c9dc60561c484bc90f4") + if(ENABLE_TBBBIND_2_5) + RESOLVE_DEPENDENCY(TBBBIND_2_5 + ARCHIVE_LIN "tbbbind_2_5_static_lin_v2.tgz" + TARGET_PATH "${TEMP}/tbbbind_2_5" + ENVIRONMENT "TBBBIND_2_5_ROOT" + SHA256 "865e7894c58402233caf0d1b288056e0e6ab2bf7c9d00c9dc60561c484bc90f4") + else() + message(WARNING "prebuilt TBBBIND_2_5 is not available. + Build oneTBB from sources and set TBBROOT environment var before OpenVINO cmake configure") + endif() elseif(LINUX AND AARCH64) RESOLVE_DEPENDENCY(TBB ARCHIVE_LIN "keembay/tbb2020_38404_kmb_lic.tgz" diff --git a/cmake/developer_package/IEDevScriptsConfig.cmake b/cmake/developer_package/IEDevScriptsConfig.cmake index 2bdb7e6123656c..990628c24998d8 100644 --- a/cmake/developer_package/IEDevScriptsConfig.cmake +++ b/cmake/developer_package/IEDevScriptsConfig.cmake @@ -208,6 +208,13 @@ endif() # General flags +macro(ov_install_static_lib target comp) + if(NOT BUILD_SHARED_LIBS) + install(TARGETS ${target} EXPORT OpenVINOTargets + ARCHIVE DESTINATION ${IE_CPACK_ARCHIVE_PATH} COMPONENT ${comp}) + endif() +endmacro() + set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) @@ -235,7 +242,11 @@ endif() # macro to mark target as conditionally compiled function(ie_mark_target_as_cc TARGET_NAME) - target_link_libraries(${TARGET_NAME} PRIVATE openvino::conditional_compilation) + set(cc_library openvino::conditional_compilation) + if(TARGET IE::conditional_compilation) + set(cc_library IE::conditional_compilation) + endif() + target_link_libraries(${TARGET_NAME} PRIVATE ${cc_library}) if(NOT (SELECTIVE_BUILD STREQUAL "ON")) return() diff --git a/cmake/developer_package/plugins/create_plugins_hpp.cmake b/cmake/developer_package/plugins/create_plugins_hpp.cmake index c63f964660fb6b..4d73b0bca3bbc2 100644 --- a/cmake/developer_package/plugins/create_plugins_hpp.cmake +++ b/cmake/developer_package/plugins/create_plugins_hpp.cmake @@ -54,8 +54,4 @@ endforeach() set(IE_PLUGINS_MAP_DEFINITION "${IE_PLUGINS_MAP_DEFINITION} };\n") - -message("${IE_PLUGINS_DECLARATIONS}") -message("${IE_PLUGINS_MAP_DEFINITION}") - configure_file("${IE_PLUGINS_HPP_HEADER_IN}" "${IE_PLUGINS_HPP_HEADER}" @ONLY) diff --git a/cmake/developer_package/plugins/plugins.cmake b/cmake/developer_package/plugins/plugins.cmake index 1d9277fff2d572..f386a0db54caf0 100644 --- a/cmake/developer_package/plugins/plugins.cmake +++ b/cmake/developer_package/plugins/plugins.cmake @@ -75,6 +75,8 @@ function(ie_add_plugin) target_compile_definitions(${IE_PLUGIN_NAME} PRIVATE IE_CREATE_EXTENSION=CreateExtensionShared${IE_PLUGIN_DEVICE_NAME}) endif() + # install static plugins + ov_install_static_lib(${IE_PLUGIN_NAME} core) endif() ie_add_vs_version_file(NAME ${IE_PLUGIN_NAME} @@ -173,8 +175,9 @@ macro(ie_register_plugins_dynamic) message(FATAL_ERROR "Please, define MAIN_TARGET") endif() + # Unregister .xml files for plugins from current build tree + set(plugins_to_remove ${IE_REGISTER_POSSIBLE_PLUGINS}) - set(plugin_files_local) set(config_output_file "$/plugins.xml") foreach(plugin IN LISTS plugins_to_remove) @@ -190,6 +193,9 @@ macro(ie_register_plugins_dynamic) VERBATIM) endforeach() + # Generate .xml files + + set(plugin_files_local) foreach(name IN LISTS PLUGIN_FILES) string(REPLACE ":" ";" name "${name}") list(LENGTH name length) @@ -217,6 +223,8 @@ macro(ie_register_plugins_dynamic) list(APPEND plugin_files_local "${config_file_name}") endforeach() + # Combine all .xml files into plugins.xml + add_custom_command(TARGET ${IE_REGISTER_MAIN_TARGET} POST_BUILD COMMAND "${CMAKE_COMMAND}" @@ -229,15 +237,37 @@ macro(ie_register_plugins_dynamic) VERBATIM) endmacro() +macro(ie_register_plugins) + if(BUILD_SHARED_LIBS) + ie_register_plugins_dynamic(${ARGN}) + endif() +endmacro() + +function(ie_target_link_plugins TARGET_NAME) + if(BUILD_SHARED_LIBS) + return() + endif() + + foreach(name IN LISTS PLUGIN_FILES) + string(REPLACE ":" ";" name "${name}") + list(LENGTH name length) + if(NOT ${length} EQUAL 2) + message(FATAL_ERROR "Unexpected error, please, contact developer of this script") + endif() + + # link plugin to ${TARGET_NAME} static version + list(GET name 1 plugin_name) + target_link_libraries(${TARGET_NAME} PRIVATE ${plugin_name}) + endforeach() +endfunction() + # -# ie_register_plugins_static(MAIN_TARGET
-# POSSIBLE_PLUGINS ) +# ie_generate_plugins_hpp() # -macro(ie_register_plugins_static) - set(options) - set(oneValueArgs MAIN_TARGET) - set(multiValueArgs POSSIBLE_PLUGINS) - cmake_parse_arguments(IE_REGISTER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) +function(ie_generate_plugins_hpp) + if(BUILD_SHARED_LIBS) + return() + endif() set(device_mapping) set(device_configs) @@ -266,13 +296,15 @@ macro(ie_register_plugins_static) if(${device_name}_CONFIG) list(APPEND device_configs -D "${device_name}_CONFIG=${${device_name}_CONFIG}") endif() - - # link plugin to inference_engine static version - list(GET name 1 plugin_name) - target_link_libraries(${IE_REGISTER_MAIN_TARGET} PRIVATE ${plugin_name}) endforeach() - set(ie_plugins_hpp "${CMAKE_CURRENT_BINARY_DIR}/ie_plugins.hpp") + # add plugins to libraries including ie_plugins.hpp + ie_target_link_plugins(inference_engine) + if(TARGET inference_engine_s) + ie_target_link_plugins(inference_engine_s) + endif() + + set(ie_plugins_hpp "${CMAKE_BINARY_DIR}/inference-engine/src/inference_engine/ie_plugins.hpp") set(plugins_hpp_in "${IEDevScripts_DIR}/plugins/plugins.hpp.in") add_custom_command(OUTPUT "${ie_plugins_hpp}" @@ -291,30 +323,25 @@ macro(ie_register_plugins_static) "Generate ie_plugins.hpp for static build" VERBATIM) + # for some reason dependency on source files does not work + # so, we have to use explicit target and make it dependency for inference_engine + add_custom_target(ie_generate_hpp DEPENDS ${ie_plugins_hpp}) + add_dependencies(inference_engine ie_generate_hpp) + # add dependency for object files - get_target_property(sources ${IE_REGISTER_MAIN_TARGET} SOURCES) + get_target_property(sources inference_engine SOURCES) foreach(source IN LISTS sources) if("${source}" MATCHES "\\$\\") # object library set(obj_library ${CMAKE_MATCH_1}) get_target_property(obj_sources ${obj_library} SOURCES) - list(APPEND patched_sources ${obj_sources}) + list(APPEND all_sources ${obj_sources}) else() # usual source - list(APPEND patched_sources ${source}) + list(APPEND all_sources ${source}) endif() endforeach() - set_source_files_properties(${patched_sources} PROPERTIES OBJECT_DEPENDS ${ie_plugins_hpp}) -endmacro() -# -# ie_register_plugins(MAIN_TARGET
-# POSSIBLE_PLUGINS ) -# -macro(ie_register_plugins) - if(BUILD_SHARED_LIBS) - ie_register_plugins_dynamic(${ARGN}) - else() - ie_register_plugins_static(${ARGN}) - endif() -endmacro() + # add dependency on header file generation for all inference_engine source files + set_source_files_properties(${all_sources} PROPERTIES OBJECT_DEPENDS ${ie_plugins_hpp}) +endfunction() diff --git a/cmake/extra_modules.cmake b/cmake/extra_modules.cmake index e9027e21f06502..d72497749ac869 100644 --- a/cmake/extra_modules.cmake +++ b/cmake/extra_modules.cmake @@ -1,88 +1,112 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# function(ie_generate_dev_package_config) -# dummy check that OpenCV is here -find_package(OpenCV QUIET) - -set(all_dev_targets gflags ie_libraries) -foreach(component IN LISTS openvino_export_components) - export(TARGETS ${${component}} NAMESPACE IE:: - APPEND FILE "${CMAKE_BINARY_DIR}/${component}_dev_targets.cmake") - list(APPEND all_dev_targets ${${component}}) -endforeach() -add_custom_target(ie_dev_targets ALL DEPENDS ${all_dev_targets}) - -configure_package_config_file("${OpenVINO_SOURCE_DIR}/cmake/templates/InferenceEngineDeveloperPackageConfig.cmake.in" - "${CMAKE_BINARY_DIR}/InferenceEngineDeveloperPackageConfig.cmake" - INSTALL_DESTINATION share # not used - PATH_VARS "OpenVINO_SOURCE_DIR;gflags_BINARY_DIR" - NO_CHECK_REQUIRED_COMPONENTS_MACRO) - -configure_file("${OpenVINO_SOURCE_DIR}/cmake/templates/InferenceEngineConfig-version.cmake.in" - "${CMAKE_BINARY_DIR}/InferenceEngineDeveloperPackageConfig-version.cmake" - @ONLY) -endfunction() + # dummy check that OpenCV is here + find_package(OpenCV QUIET) + + set(all_dev_targets gflags ie_libraries) + foreach(component IN LISTS openvino_export_components) + # export all targets with prefix and use them during extra modules build + export(TARGETS ${${component}} NAMESPACE IE:: + APPEND FILE "${CMAKE_BINARY_DIR}/${component}_dev_targets.cmake") + list(APPEND all_dev_targets ${${component}}) + endforeach() + add_custom_target(ie_dev_targets ALL DEPENDS ${all_dev_targets}) -ie_generate_dev_package_config() + configure_package_config_file("${OpenVINO_SOURCE_DIR}/cmake/templates/InferenceEngineDeveloperPackageConfig.cmake.in" + "${CMAKE_BINARY_DIR}/InferenceEngineDeveloperPackageConfig.cmake" + INSTALL_DESTINATION share # not used + PATH_VARS "OpenVINO_SOURCE_DIR;gflags_BINARY_DIR" + NO_CHECK_REQUIRED_COMPONENTS_MACRO) + + configure_file("${OpenVINO_SOURCE_DIR}/cmake/templates/InferenceEngineConfig-version.cmake.in" + "${CMAKE_BINARY_DIR}/InferenceEngineDeveloperPackageConfig-version.cmake" + @ONLY) +endfunction() # # Add extra modules # function(register_extra_modules) -# post export -openvino_developer_export_targets(COMPONENT inference_engine TARGETS inference_engine) -openvino_developer_export_targets(COMPONENT ngraph TARGETS ngraph) + # post export + openvino_developer_export_targets(COMPONENT inference_engine TARGETS inference_engine) + openvino_developer_export_targets(COMPONENT ngraph TARGETS ngraph) -set(InferenceEngineDeveloperPackage_DIR "${CMAKE_CURRENT_BINARY_DIR}/runtime") + set(InferenceEngineDeveloperPackage_DIR "${CMAKE_CURRENT_BINARY_DIR}/runtime") -function(generate_fake_dev_package) - set(iedevconfig_file "${InferenceEngineDeveloperPackage_DIR}/InferenceEngineDeveloperPackageConfig.cmake") - file(REMOVE "${iedevconfig_file}") + function(generate_fake_dev_package) + set(iedevconfig_file "${InferenceEngineDeveloperPackage_DIR}/InferenceEngineDeveloperPackageConfig.cmake") + file(REMOVE "${iedevconfig_file}") - file(WRITE "${iedevconfig_file}" "\# !! AUTOGENERATED: DON'T EDIT !!\n\n") - file(APPEND "${iedevconfig_file}" "ie_deprecated_no_errors()\n") + file(WRITE "${iedevconfig_file}" "\# !! AUTOGENERATED: DON'T EDIT !!\n\n") + file(APPEND "${iedevconfig_file}" "ie_deprecated_no_errors()\n") - foreach(target IN LISTS ${openvino_export_components}) - if(target) - file(APPEND "${iedevconfig_file}" "add_library(IE::${target} ALIAS ${target})\n") - endif() - endforeach() -endfunction() + foreach(target IN LISTS ${openvino_export_components}) + if(target) + file(APPEND "${iedevconfig_file}" "add_library(IE::${target} ALIAS ${target})\n") + endif() + endforeach() + endfunction() -generate_fake_dev_package() + generate_fake_dev_package() -# automatically import plugins from the 'plugins' folder -file(GLOB local_extra_modules "runtime/plugins/*") -# add template plugin -list(APPEND local_extra_modules "${OpenVINO_SOURCE_DIR}/docs/template_plugin") - -# detect where IE_EXTRA_MODULES contains folders with CMakeLists.txt -# other folders are supposed to have sub-folders with CMakeLists.txt -foreach(module_path IN LISTS IE_EXTRA_MODULES) - if(EXISTS "${module_path}/CMakeLists.txt") - list(APPEND extra_modules "${module_path}") - elseif(module_path) - file(GLOB extra_modules ${extra_modules} "${module_path}/*") + # automatically import plugins from the 'runtime/plugins' folder + file(GLOB local_extra_modules "runtime/plugins/*") + # add template plugin + if(ENABLE_TEMPLATE) + list(APPEND local_extra_modules "${OpenVINO_SOURCE_DIR}/docs/template_plugin") endif() -endforeach() - -# add each extra module -foreach(module_path IN LISTS extra_modules local_extra_modules) - if(module_path) - get_filename_component(module_name "${module_path}" NAME) - set(build_module ON) - if(NOT EXISTS "${module_path}/CMakeLists.txt") # if module is built not using cmake - set(build_module OFF) - endif() - if(NOT DEFINED BUILD_${module_name}) - set(BUILD_${module_name} ${build_module} CACHE BOOL "Build ${module_name} extra module" FORCE) + + # detect where IE_EXTRA_MODULES contains folders with CMakeLists.txt + # other folders are supposed to have sub-folders with CMakeLists.txt + foreach(module_path IN LISTS IE_EXTRA_MODULES) + if(EXISTS "${module_path}/CMakeLists.txt") + list(APPEND extra_modules "${module_path}") + elseif(module_path) + file(GLOB extra_modules ${extra_modules} "${module_path}/*") endif() - if(BUILD_${module_name}) - message(STATUS "Register ${module_name} to be built in build-modules/${module_name}") - add_subdirectory("${module_path}" "build-modules/${module_name}") + endforeach() + + # add each extra module + foreach(module_path IN LISTS extra_modules local_extra_modules) + if(module_path) + get_filename_component(module_name "${module_path}" NAME) + set(build_module ON) + if(NOT EXISTS "${module_path}/CMakeLists.txt") # if module is built not using cmake + set(build_module OFF) + endif() + if(NOT DEFINED BUILD_${module_name}) + set(BUILD_${module_name} ${build_module} CACHE BOOL "Build ${module_name} extra module" FORCE) + endif() + if(BUILD_${module_name}) + message(STATUS "Register ${module_name} to be built in build-modules/${module_name}") + add_subdirectory("${module_path}" "build-modules/${module_name}") + endif() endif() - endif() -endforeach() + endforeach() endfunction() -register_extra_modules() \ No newline at end of file +# +# Extra modules support +# + +# for Template plugin +openvino_developer_export_targets(COMPONENT ngraph TARGETS ngraph_backend interpreter_backend) + +# this InferenceEngineDeveloperPackageConfig.cmake is not used +# during extra modules build since it's generated after modules +# are configured +ie_generate_dev_package_config() + +# extra modules must be registered after inference_engine library +# and all other IE common libraries (ie_libraries) are creared +# because 'register_extra_modules' creates fake InferenceEngineDeveloperPackageConfig.cmake +# with all imported developer targets +register_extra_modules() + +# for static libraries case we need to generate final ie_plugins.hpp +# with all the information about plugins +ie_generate_plugins_hpp() diff --git a/cmake/features.cmake b/cmake/features.cmake index c50f6f4da9a998..a62b6f2f9c40fe 100644 --- a/cmake/features.cmake +++ b/cmake/features.cmake @@ -14,6 +14,17 @@ ie_option (ENABLE_STRICT_DEPENDENCIES "Skip configuring \"convinient\" dependenc ie_dependent_option (ENABLE_CLDNN "clDnn based plugin for inference engine" ON "X86_64;NOT APPLE;NOT MINGW;NOT WINDOWS_STORE;NOT WINDOWS_PHONE" OFF) +if (NOT ENABLE_CLDNN OR ANDROID OR + (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)) + # oneDNN doesn't support old compilers and android builds for now, so we'll + # build GPU plugin without oneDNN + set(ENABLE_ONEDNN_FOR_GPU_DEFAULT OFF) +else() + set(ENABLE_ONEDNN_FOR_GPU_DEFAULT ON) +endif() + +ie_dependent_option (ENABLE_ONEDNN_FOR_GPU "Enable oneDNN with GPU support" ON "ENABLE_ONEDNN_FOR_GPU_DEFAULT" OFF) + ie_option (ENABLE_PROFILING_ITT "Build with ITT tracing. Optionally configure pre-built ittnotify library though INTEL_VTUNE_DIR variable." OFF) ie_option_enum(ENABLE_PROFILING_FILTER "Enable or disable ITT counter groups.\ @@ -62,6 +73,15 @@ if (NOT THREADING STREQUAL "TBB" AND message(FATAL_ERROR "THREADING should be set to TBB, TBB_AUTO, OMP or SEQ. Default option is ${THREADING_DEFAULT}") endif() +if((THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") AND + (BUILD_SHARED_LIBS OR (LINUX AND X86_64))) + set(ENABLE_TBBBIND_2_5_DEFAULT ON) +else() + set(ENABLE_TBBBIND_2_5_DEFAULT OFF) +endif() + +ie_dependent_option (ENABLE_TBBBIND_2_5 "Enable TBBBind_2_5 static usage in OpenVINO runtime" ON "ENABLE_TBBBIND_2_5_DEFAULT" OFF) + if (ENABLE_GNA) if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.4) set (DEFAULT_GNA_LIB GNA1) @@ -90,6 +110,8 @@ ie_option (ENABLE_MULTI "Enables Multi Device Plugin" ON) ie_option (ENABLE_HETERO "Enables Hetero Device Plugin" ON) +ie_option (ENABLE_TEMPLATE "Enable template plugin" ON) + ie_dependent_option (ENABLE_VPU "vpu targeted plugins for inference engine" ON "NOT WINDOWS_PHONE;NOT WINDOWS_STORE" OFF) ie_dependent_option (ENABLE_MYRIAD "myriad targeted plugin for inference engine" ON "ENABLE_VPU" OFF) @@ -118,7 +140,7 @@ set(IE_EXTRA_MODULES "" CACHE STRING "Extra paths for extra modules to include i ie_dependent_option(ENABLE_TBB_RELEASE_ONLY "Only Release TBB libraries are linked to the Inference Engine binaries" ON "THREADING MATCHES TBB;LINUX" OFF) -ie_option (ENABLE_SYSTEM_PUGIXML "use the system copy of pugixml" OFF) +ie_dependent_option (ENABLE_SYSTEM_PUGIXML "use the system copy of pugixml" OFF "BUILD_SHARED_LIBS" OFF) ie_option (ENABLE_DEBUG_CAPS "enable OpenVINO debug capabilities at runtime" OFF) @@ -136,8 +158,6 @@ ie_dependent_option(NGRAPH_ONNX_FRONTEND_ENABLE "Enable ONNX FrontEnd" ON "proto ie_dependent_option(NGRAPH_PDPD_FRONTEND_ENABLE "Enable PaddlePaddle FrontEnd" ON "protoc_available" OFF) ie_option(NGRAPH_IR_FRONTEND_ENABLE "Enable IR FrontEnd" ON) ie_dependent_option(NGRAPH_TF_FRONTEND_ENABLE "Enable TensorFlow FrontEnd" ON "protoc_available" OFF) -ie_dependent_option(NGRAPH_USE_PROTOBUF_LITE "Compiles and links with protobuf-lite" ON - "NGRAPH_ONNX_FRONTEND_ENABLE" OFF) ie_dependent_option(NGRAPH_USE_SYSTEM_PROTOBUF "Use system protobuf" OFF "NGRAPH_ONNX_FRONTEND_ENABLE OR NGRAPH_PDPD_FRONTEND_ENABLE OR NGRAPH_TF_FRONTEND_ENABLE" OFF) ie_dependent_option(NGRAPH_UNIT_TEST_ENABLE "Enables ngraph unit tests" ON "ENABLE_TESTS;NOT ANDROID" OFF) diff --git a/cmake/templates/OpenVINOConfig.cmake.in b/cmake/templates/OpenVINOConfig.cmake.in index 818080a0ac8581..bb21d19b400d48 100644 --- a/cmake/templates/OpenVINOConfig.cmake.in +++ b/cmake/templates/OpenVINOConfig.cmake.in @@ -160,8 +160,20 @@ if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO" AND NOT TBB_FOUND) ${_tbb_dir} NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH) + + set(install_tbbbind "@install_tbbbind@") + if(install_tbbbind) + set_and_check(_tbb_bind_dir "@PACKAGE_IE_TBBBIND_DIR@") + _ov_find_dependency(TBBBIND_2_5 + PATHS ${_tbb_bind_dir} + NO_CMAKE_FIND_ROOT_PATH + NO_DEFAULT_PATH) + set_target_properties(${TBBBIND_2_5_IMPORTED_TARGETS} PROPERTIES IMPORTED_GLOBAL ON) + endif() endif() +_ov_find_dependency(Threads) + if(NOT TARGET inference_engine) set(_ov_as_external_package ON) include("${CMAKE_CURRENT_LIST_DIR}/OpenVINOTargets.cmake") diff --git a/cmake/test_model_zoo.cmake b/cmake/test_model_zoo.cmake index 64ec7a6909d117..c8ec6691ca97cc 100644 --- a/cmake/test_model_zoo.cmake +++ b/cmake/test_model_zoo.cmake @@ -86,6 +86,11 @@ ov_model_convert("${OpenVINO_SOURCE_DIR}/${rel_path}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_model_zoo/onnx_import" ie_onnx_import_out_files) +set(rel_path "docs/onnx_custom_op") +ov_model_convert("${OpenVINO_SOURCE_DIR}/${rel_path}" + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_model_zoo/docs/models" + docs_onnx_out_files) + if(ENABLE_TESTS) if(NGRAPH_ONNX_FRONTEND_ENABLE AND ENABLE_REQUIREMENTS_INSTALL) find_package(PythonInterp 3 REQUIRED) @@ -124,13 +129,14 @@ if(ENABLE_TESTS) ${ft_out_files} ${ie_onnx_out_files} ${ie_serialize_out_files} - ${ie_onnx_import_out_files}) + ${ie_onnx_import_out_files} + ${docs_onnx_out_files}) if(TARGET test_pip_prerequsites) add_dependencies(test_model_zoo test_pip_prerequsites) endif() - if (NGRAPH_PDPD_FRONTEND_ENABLE) + if (NGRAPH_PDPD_FRONTEND_ENABLE AND NGRAPH_UNIT_TEST_ENABLE) add_dependencies(test_model_zoo paddlepaddle_test_models) endif() diff --git a/cmake/toolchains/ia32.linux.toolchain.cmake b/cmake/toolchains/ia32.linux.toolchain.cmake index 4526bc3ab9de81..f5c24fffb89fe2 100644 --- a/cmake/toolchains/ia32.linux.toolchain.cmake +++ b/cmake/toolchains/ia32.linux.toolchain.cmake @@ -17,5 +17,8 @@ macro(_set_if_not_defined var val) endif() endmacro() +# for ittapi +_set_if_not_defined(FORCE_32 ON) + # need libusb 32-bits version _set_if_not_defined(ENABLE_VPU OFF) diff --git a/cmake/toolchains/mt.runtime.win32.toolchain.cmake b/cmake/toolchains/mt.runtime.win32.toolchain.cmake index 899fecb679bce9..716d958fcd1f74 100644 --- a/cmake/toolchains/mt.runtime.win32.toolchain.cmake +++ b/cmake/toolchains/mt.runtime.win32.toolchain.cmake @@ -29,6 +29,8 @@ onecoreuap_set_runtime(STATIC_CRT) onecoreuap_set_runtime(protobuf_MSVC_STATIC_RUNTIME) # clDNN onecoreuap_set_runtime(CLDNN__COMPILE_LINK_USE_STATIC_RUNTIME) +# OpenCL +onecoreuap_set_runtime(USE_DYNAMIC_VCXX_RUNTIME) # google-test if(use_static_runtime) set(gtest_force_shared_crt OFF CACHE BOOL "" FORCE) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 93d1feed4050d1..b2ccee1dcdd1fc 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -23,8 +23,8 @@ if(NOT ENABLE_DOCKER) add_subdirectory(template_extension) set(all_docs_targets - ie_docs_snippets - template_extension templatePlugin templateFuncTests) + ie_docs_snippets templateFuncTests + template_extension template_ov_extension templatePlugin) foreach(target_name IN LISTS all_docs_targets) if(TARGET ${target_name}) set_target_properties(${target_name} PROPERTIES FOLDER docs) @@ -36,8 +36,14 @@ if(NOT ENABLE_DOCKER) # install - install(TARGETS templatePlugin template_extension template_ov_extension - LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT tests EXCLUDE_FROM_ALL) + foreach(target templatePlugin template_extension template_ov_extension) + if(TARGET ${target}) + install(TARGETS ${target} + LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH} + COMPONENT tests + EXCLUDE_FROM_ALL) + endif() + endforeach() endif() set(OMZ_DOCS_DIR "" CACHE PATH "Path to open_model_zoo documentation") diff --git a/docs/IE_DG/Extensibility_DG/Custom_ONNX_Ops.md b/docs/IE_DG/Extensibility_DG/Custom_ONNX_Ops.md index dd5543202418fe..5875995e21e462 100644 --- a/docs/IE_DG/Extensibility_DG/Custom_ONNX_Ops.md +++ b/docs/IE_DG/Extensibility_DG/Custom_ONNX_Ops.md @@ -26,7 +26,18 @@ New operator registration must happen before an ONNX model is read. For example, Reregistering ONNX operators within the same process is supported. If you register an existing operator, you get a warning. The example below demonstrates an exemplary model that requires a previously created `CustomRelu` operator: -@snippet onnx_custom_op/onnx_custom_op.cpp onnx_custom_op:model +@include onnx_custom_op/custom_relu_model.prototxt +This model is in text format, so before it can be passed to Inference Engine, it has to be converted to binary using: +```py +from google.protobuf import text_format +import onnx + +with open("custom_relu_model.prototxt") as in_file: + proto = onnx.ModelProto() + text_format.Parse(in_file.read(), proto, allow_field_number=True) + s = onnx._serialize(proto) + onnx._save_bytes(s, "custom_relu_model.onnx") +``` To create a graph with nGraph operations, visit [Custom nGraph Operations](AddingNGraphOps.md). diff --git a/docs/IE_DG/supported_plugins/GPU.md b/docs/IE_DG/supported_plugins/GPU.md index 8a30f5ce98ebe3..28bee7d5316039 100644 --- a/docs/IE_DG/supported_plugins/GPU.md +++ b/docs/IE_DG/supported_plugins/GPU.md @@ -105,7 +105,7 @@ When specifying key values as raw strings (that is, when using Python API), omit | `KEY_CACHE_DIR` | `""` | `""` | Specifies a directory where compiled OCL binaries can be cached. First model loading generates the cache, and all subsequent LoadNetwork calls use precompiled kernels which significantly improves load time. If empty - caching is disabled | | `KEY_PERF_COUNT` | `YES` / `NO` | `NO` | Collect performance counters during inference | | `KEY_CONFIG_FILE` | `" [ ...]"` | `""` | Load custom layer configuration files | -| `KEY_GPU_MODEL_`
`PRIORITY` | `GPU_MODEL_PRIORITY_`
`GPU_QUEUE_PRIORITY_`
`GPU_HOST_TASK_PRIORITY_` | `GPU_QUEUE_PRIORITY_DEFAULT`
`\|GPU_HOST_TASK_PRIORITY_ANY` | Specifies two types of priority: host task priority and OpenCL queue priority.

Host task priority is specified by `GPU_HOST_TASK_PRIORITY_[level]` and there are three types of task levels: `HIGH`, `LOW`, and `ANY`. Note that `HIGH` and `LOW` are effective only when tbb is used for multithreading the LoadNetwork workload and the host processor is hybrid type. For hybrid processors, if the task priority type is set as `HIGH` the task will have higher priority for core type selection, and vice versa. If the host processor is not hybrid core or the multi threading is not using tbb, it is set as `ANY`, which is the default type.

OpenCL queue priority is specified by `GPU_QUEUE_PRIORITY_[level]` and there are four types of levels: `HIGH`, `MED`, `LOW`, and `DEFAULT`, where the default value is `DEFAULT`. Before usage, make sure your OpenCL driver supports appropriate extension.

Basically `GPU_MODEL_PRIORITY` can be set as combination of the two priority types, such as
-`GPU_QUEUE_PRIORITY_HIGH\|GPU_HOST_TASK_PRIORITY_HIGH` or
-`GPU_QUEUE_PRIORITY_LOW\|GPU_HOST_TASK_PRIORITY_HIGH`.

Also it can be set as a more abstract level of priority PLUGIN_PRIORIY_[level], which represents combination of the two priorities as follows:
-`GPU_MODEL_PRIORITY_HIGH` : `GPU_QUEUE_PRIORITY_HIGH\|GPU_HOST_TASK_PRIORITY_HIGH`
-`GPU_MODEL_PRIORITY_LOW` : `GPU_QUEUE_PRIORITY_LOW\|GPU_HOST_TASK_PRIORITY_LOW`

The default of `KEY_GPU_MODEL_PRIORITY` is `GPU_QUEUE_PRIORITY_DEFAULT\|GPU_HOST_TASK_PRIORITY_ANY`.
| +| `KEY_GPU_MODEL_`
`PRIORITY` | `GPU_MODEL_PRIORITY_`
`GPU_QUEUE_PRIORITY_`
`GPU_HOST_TASK_PRIORITY_` | `GPU_QUEUE_PRIORITY_DEFAULT`
`\|GPU_HOST_TASK_PRIORITY_ANY` | Specifies two types of priority: host task priority and OpenCL queue priority.

Host task priority is specified by `GPU_HOST_TASK_PRIORITY_[level]` and there are three types of task levels: `HIGH`, `LOW`, and `ANY`. Note that `HIGH` and `LOW` are effective only when tbb is used for multithreading the LoadNetwork workload and the host processor is hybrid type. For hybrid processors, if the task priority type is set as `HIGH` the task will have higher priority for core type selection, and vice versa. If the host processor is not hybrid core or the multi threading is not using tbb, it is set as `ANY`, which is the default type.

OpenCL queue priority is specified by `GPU_QUEUE_PRIORITY_[level]` and there are four types of levels: `HIGH`, `MED`, `LOW`, and `DEFAULT`, where the default value is `DEFAULT`. Before usage, make sure your OpenCL driver supports appropriate extension.

Basically `GPU_MODEL_PRIORITY` can be set as combination of the two priority types, such as
-`GPU_QUEUE_PRIORITY_HIGH\|GPU_HOST_TASK_PRIORITY_HIGH` or
-`GPU_QUEUE_PRIORITY_LOW\|GPU_HOST_TASK_PRIORITY_HIGH`.

Also it can be set as a more abstract level of priority PLUGIN_PRIORIY_[level], which represents combination of the two priorities as follows:
-`GPU_MODEL_PRIORITY_HIGH` : `GPU_QUEUE_PRIORITY_HIGH\|GPU_HOST_TASK_PRIORITY_HIGH`
-`GPU_MODEL_PRIORITY_LOW` : `GPU_QUEUE_PRIORITY_LOW\|GPU_HOST_TASK_PRIORITY_LOW`

The default of `KEY_GPU_MODEL_PRIORITY` is `GPU_QUEUE_PRIORITY_DEFAULT\|GPU_HOST_TASK_PRIORITY_ANY`.
| | `KEY_GPU_PLUGIN_`
`PRIORITY` | `<0-3>` | `0` | OpenCL queue priority (before usage, make sure your OpenCL driver supports appropriate extension)
Higher value means higher priority for OpenCL queue. 0 disables the setting. **Deprecated**. Please use KEY_GPU_MODEL_PRIORITY | | `KEY_GPU_PLUGIN_`
`THROTTLE` | `<0-3>` | `0` | OpenCL queue throttling (before usage, make sure your OpenCL driver supports appropriate extension)
Lower value means lower driver thread priority and longer sleep time for it. 0 disables the setting. | | `KEY_CLDNN_ENABLE_`
`FP16_FOR_QUANTIZED_`
`MODELS` | `YES` / `NO` | `YES` | Allows using FP16+INT8 mixed precision mode, so non-quantized parts of a model will be executed in FP16 precision for FP16 IR. Does not affect quantized FP32 IRs | diff --git a/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md b/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md index 1a8070e4dc4d6e..8d132abe429163 100644 --- a/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md +++ b/docs/MO_DG/prepare_model/Supported_Frameworks_Layers.md @@ -525,7 +525,7 @@ Some TensorFlow\* operations do not match to any Inference Engine layer, but are | GRU | | | Gather | | | GatherElements | Doesn't work with negative indices | -| GatherND | | +| GatherND | Doesn't work with negative indices | | GatherTree | | | Gemm | | | GlobalAveragePool | | diff --git a/docs/migration_ov_2_0/docs/common_inference_pipeline.md b/docs/migration_ov_2_0/docs/common_inference_pipeline.md index af2dbf25304116..2b842e2e9e125a 100644 --- a/docs/migration_ov_2_0/docs/common_inference_pipeline.md +++ b/docs/migration_ov_2_0/docs/common_inference_pipeline.md @@ -32,6 +32,8 @@ OpenVINO™ 2.0 API: @snippet snippets/ov_common.cpp ov_api_2_0:read_model +Read model has the same structure as in the example from [OpenVINO™ Graph Construction](@ref ov_graph_construction) guide. + ### 2.1 Configure Input and Output of the Model Inference Engine API: @@ -52,4 +54,108 @@ OpenVINO™ 2.0 API: @snippet snippets/ov_common.cpp ov_api_2_0:compile_model -## 5. TBD +## 4. Create an Inference Request + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:create_infer_request + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:create_infer_request + +## 5. Prepare input + +### IR v10 + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_input_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_input_tensor_v10 + +### IR v11 + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_input_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_input_tensor_aligned + +### ONNX + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_input_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_input_tensor_aligned + +### From Function + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_input_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_input_tensor_aligned + +## 6. Start Inference + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:inference + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:inference + + +## 7. Process the Inference Results + +### IR v10 + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_output_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_output_tensor_v10 + +### IR v11 + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_output_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_output_tensor_aligned + +### ONNX + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_output_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_output_tensor_aligned + +### From Function + +Inference Engine API: + +@snippet snippets/ie_common.cpp ie:get_output_tensor + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_common.cpp ov_api_2_0:get_output_tensor_aligned + diff --git a/docs/migration_ov_2_0/docs/graph_construction.md b/docs/migration_ov_2_0/docs/graph_construction.md new file mode 100644 index 00000000000000..f3fe2c7a1dce34 --- /dev/null +++ b/docs/migration_ov_2_0/docs/graph_construction.md @@ -0,0 +1,12 @@ +# OpenVINO™ graph construction {#ov_graph_construction} + +OpenVINO™ 2.0 includes nGraph engine in a common part. The `ngraph` namespace was changed to `ov`. +Code snippets below show how application code should be changed for migration to OpenVINO™ 2.0. + +nGraph API: + +@snippet snippets/ngraph.cpp ngraph:graph + +OpenVINO™ 2.0 API: + +@snippet snippets/ov_graph.cpp ov:graph diff --git a/docs/migration_ov_2_0/docs/intro.md b/docs/migration_ov_2_0/docs/intro.md index 5d89b7aff3d809..5afc4a11304ffb 100644 --- a/docs/migration_ov_2_0/docs/intro.md +++ b/docs/migration_ov_2_0/docs/intro.md @@ -9,4 +9,5 @@ The list with differences between APIs below: - Namespaces were aligned between components. Please look at next transition guides to understand how transit own application to OpenVINO™ API 2.0. + - [OpenVINO™ Graph Construction](@ref ov_graph_construction) - [OpenVINO™ Common Inference pipeline](@ref ov_inference_pipeline) diff --git a/docs/onnx_custom_op/custom_relu_model.prototxt b/docs/onnx_custom_op/custom_relu_model.prototxt new file mode 100644 index 00000000000000..3845cc00ce2e8a --- /dev/null +++ b/docs/onnx_custom_op/custom_relu_model.prototxt @@ -0,0 +1,52 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "in" + output: "out" + name: "customrelu" + op_type: "CustomRelu" + domain: "com.example" + attribute { + name: "alpha" + type: FLOAT + f: 2 + } + attribute { + name: "beta" + type: FLOAT + f: 3 + } + } + name: "custom relu graph" + input { + name: "in" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 8 + } + } + } + } + } + output { + name: "out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 8 + } + } + } + } + } +} +opset_import { + domain: "com.example" + version: 1 +} diff --git a/docs/onnx_custom_op/onnx_custom_op.cpp b/docs/onnx_custom_op/onnx_custom_op.cpp index 2d8c6198e64f73..09ea58cc2b6b89 100644 --- a/docs/onnx_custom_op/onnx_custom_op.cpp +++ b/docs/onnx_custom_op/onnx_custom_op.cpp @@ -9,68 +9,6 @@ #include //! [onnx_custom_op:headers] - -std::string custom_relu_model() { - return -//! [onnx_custom_op:model] -R"ONNX( -ir_version: 3 -producer_name: "nGraph ONNX Importer" -graph { - node { - input: "in" - output: "out" - name: "customrelu" - op_type: "CustomRelu" - domain: "com.example" - attribute { - name: "alpha" - type: FLOAT - f: 2 - } - attribute { - name: "beta" - type: FLOAT - f: 3 - } - } - name: "custom relu graph" - input { - name: "in" - type { - tensor_type { - elem_type: 1 - shape { - dim { - dim_value: 8 - } - } - } - } - } - output { - name: "out" - type { - tensor_type { - elem_type: 1 - shape { - dim { - dim_value: 8 - } - } - } - } - } -} -opset_import { - domain: "com.example" - version: 1 -} -)ONNX"; -//! [onnx_custom_op:model] -} - - void register_custom_relu_operator() { // CustomRelu is defined as follows: // x >= 0 => f(x) = x * alpha diff --git a/docs/onnx_custom_op/onnx_custom_op.hpp b/docs/onnx_custom_op/onnx_custom_op.hpp index fae687097045a4..e1670a5f82bf5b 100644 --- a/docs/onnx_custom_op/onnx_custom_op.hpp +++ b/docs/onnx_custom_op/onnx_custom_op.hpp @@ -4,8 +4,5 @@ #pragma once -#include - -std::string custom_relu_model(); void register_custom_relu_operator(); void unregister_custom_relu_operator(); diff --git a/docs/ops/opset8.md b/docs/ops/opset8.md index c1a13c15b3fdaf..f9c55e8ce094c8 100644 --- a/docs/ops/opset8.md +++ b/docs/ops/opset8.md @@ -65,7 +65,7 @@ declared in `namespace opset8`. * [FloorMod](arithmetic/FloorMod_1.md) * [Gather](movement/Gather_8.md) * [GatherElements](movement/GatherElements_6.md) -* [GatherND_8](movement/GatherND_8.md) +* [GatherND](movement/GatherND_8.md) * [GatherTree](movement/GatherTree_1.md) * [Gelu](activation/GELU_7.md) * [Greater](comparison/Greater_1.md) @@ -94,12 +94,14 @@ declared in `namespace opset8`. * [LSTMCell](sequence/LSTMCell_1.md) * [LSTMSequence](sequence/LSTMSequence_1.md) * [MatMul](matrix/MatMul_1.md) -* [MaxPool](pooling/MaxPool_1.md) +* [MatrixNMS](sort/MatrixNMS_8.md) +* [MaxPool](pooling/MaxPool_8.md) * [Maximum](arithmetic/Maximum_1.md) * [Minimum](arithmetic/Minimum_1.md) * [Mish](activation/Mish_4.md) * [Mod](arithmetic/Mod_1.md) * [MVN](normalization/MVN_6.md) +* [MulticlassNMS](sort/MulticlassNMS_8.md) * [Multiply](arithmetic/Multiply_1.md) * [Negative](arithmetic/Negative_1.md) * [NonMaxSuppression](sort/NonMaxSuppression_5.md) @@ -152,6 +154,7 @@ declared in `namespace opset8`. * [Sign](arithmetic/Sign_1.md) * [Sin](arithmetic/Sin_1.md) * [Sinh](arithmetic/Sinh_1.md) +* [Slice](movement/Slice_8.md) * [SoftMax](activation/SoftMax_8.md) * [SoftPlus](activation/SoftPlus_4.md) * [SpaceToBatch](movement/SpaceToBatch_2.md) diff --git a/docs/ops/sequence/LSTMCell_1.md b/docs/ops/sequence/LSTMCell_1.md index eb979a94126b56..dd73b1b7dd9824 100644 --- a/docs/ops/sequence/LSTMCell_1.md +++ b/docs/ops/sequence/LSTMCell_1.md @@ -6,21 +6,20 @@ **Short description**: *LSTMCell* operation represents a single LSTM cell. It computes the output using the formula described in the original paper [Long Short-Term Memory](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.676.4320&rep=rep1&type=pdf). -**Detailed description** +**Detailed description**: *LSTMCell* computes the output *Ht* and *ot* for current time step based on the following formula: ``` Formula: - * - matrix mult - (.) - eltwise mult + * - matrix multiplication + (.) - Hadamard product (element-wise) [,] - concatenation -sigm - 1/(1 + e^{-x}) -tanh - (e^{2x} - 1)/(e^{2x} + 1) - f = sigm(Wf*[Hi, X] + Bf) - i = sigm(Wi*[Hi, X] + Bi) - c = tanh(Wc*[Hi, X] + Bc) - o = sigm(Wo*[Hi, X] + Bo) - Co = f (.) Ci + i (.) c - Ho = o (.) tanh(Co) + f, g, h - are activation functions. + it = f(Xt*(Wi^T) + Ht-1*(Ri^T) + Wbi + Rbi) + ft = f(Xt*(Wf^T) + Ht-1*(Rf^T) + Wbf + Rbf) + ct = g(Xt*(Wc^T) + Ht-1*(Rc^T) + Wbc + Rbc) + Ct = ft (.) Ct-1 + it (.) ct + ot = f(Xt*(Wo^T) + Ht-1*(Ro^T) + Wbo + Rbo) + Ht = ot (.) h(Ct) ``` **Attributes** @@ -37,7 +36,7 @@ tanh - (e^{2x} - 1)/(e^{2x} + 1) * **Description**: *activations* specifies activation functions for gates, there are three gates, so three activation functions should be specified as a value for this attributes * **Range of values**: any combination of *relu*, *sigmoid*, *tanh* * **Type**: a list of strings - * **Default value**: *sigmoid,tanh,tanh* + * **Default value**: *sigmoid* for f, *tanh* for g, *tanh* for h * **Required**: *no* * *activations_alpha, activations_beta* @@ -68,7 +67,7 @@ tanh - (e^{2x} - 1)/(e^{2x} + 1) * **5**: `R` - 2D tensor of type *T* `[4 * hidden_size, hidden_size]`, the recurrence weights for matrix multiplication, gate order: fico. **Required.** -* **6**: `B` 1D tensor of type *T* `[4 * hidden_size]`, the sum of biases (weights and recurrence weights). **Required.** +* **6**: `B` 1D tensor of type *T* `[4 * hidden_size]`, the sum of biases (weights and recurrence weights), if not specified - assumed to be 0. **optional.** **Outputs** diff --git a/docs/ops/sparse/EmbeddingBagOffsetsSum_3.md b/docs/ops/sparse/EmbeddingBagOffsetsSum_3.md index 7bd1540e91dbad..e74b9f78e4d8d0 100644 --- a/docs/ops/sparse/EmbeddingBagOffsetsSum_3.md +++ b/docs/ops/sparse/EmbeddingBagOffsetsSum_3.md @@ -8,6 +8,8 @@ **Detailed description**: This is the second case of the PyTorch [EmbeddingBag](https://pytorch.org/docs/stable/nn.html#embeddingbag), it has indices in two 1D tensors provided as 2nd and 3rd inputs. For each index in `indices` this operator gets values from `data` embedding table and sums all values belonging to each bag. Values in `offsets` define starting index in `indices` tensor of each "bag", e.g. `offsets` with value `[0,3,4,4,6]` define 5 "bags" containing `[3,1,0,2,n-6]` elements. +**Attributes**: EmbeddingBagOffsetsSum operation has no attributes. + **Inputs**: * **1**: `emb_table` tensor containing the embedding lookup table of the module of shape `[num_emb, emb_dim1, emb_dim2, ...]` and of type *T*. **Required.** @@ -42,7 +44,7 @@ 4 - + 3 diff --git a/docs/ops/sparse/EmbeddingBagPackedSum_3.md b/docs/ops/sparse/EmbeddingBagPackedSum_3.md index ceaebe3862326c..41b66668440628 100644 --- a/docs/ops/sparse/EmbeddingBagPackedSum_3.md +++ b/docs/ops/sparse/EmbeddingBagPackedSum_3.md @@ -8,6 +8,8 @@ **Detailed description**: This is the first case of the PyTorch [EmbeddingBag](https://pytorch.org/docs/stable/nn.html#embeddingbag), it has indices in the tensor of format `[batch, indices_per_bag]`. If 3rd input is not provided, this operation is equivalent to *Gather* followed by *ReduceSum(axis=0)*. However, *EmbeddingBagPackedSum* is much more time and memory efficient than using a chain of these operations. +**Attributes**: EmbeddingBagPackedSum operation has no attributes. + **Inputs**: * **1**: `emb_table` tensor containing the embedding lookup table of the module of shape `[num_emb, emb_dim1, emb_dim2, ...]` and of type *T*. **Required.** diff --git a/docs/ops/sparse/EmbeddingSegmentsSum_3.md b/docs/ops/sparse/EmbeddingSegmentsSum_3.md index 71dc4897251a1f..b1c8404aacad73 100644 --- a/docs/ops/sparse/EmbeddingSegmentsSum_3.md +++ b/docs/ops/sparse/EmbeddingSegmentsSum_3.md @@ -8,6 +8,8 @@ **Detailed description**: This is [sparse.segment_sum](https://www.tensorflow.org/api_docs/python/tf/sparse/segment_sum) operation from Tensorflow. For each index in `indices` this operator gets values from `data` embedding table and sums all values belonging to each segment. Values in `segment_ids` define which segment index in `indices` tensor belong to, e.g. `segments_ids` with value `[0,0,0,1,1,3,5,5]` define 4 non empty segments other segments are empty, the number of segments is defined by `num_segments` input. +**Attributes**: EmbeddingSegmentsSum operation has no attributes. + **Inputs**: * **1**: `emb_table` tensor containing the embedding lookup table of the module of shape `[num_emb, emb_dim1, emb_dim2, ...]` and of type *T*. **Required.** diff --git a/docs/snippets/ie_common.cpp b/docs/snippets/ie_common.cpp index 6a558129243082..25cf78a0c43582 100644 --- a/docs/snippets/ie_common.cpp +++ b/docs/snippets/ie_common.cpp @@ -27,8 +27,29 @@ int main() { //! [ie:create_infer_request] //! [ie:get_input_tensor] - InferenceEngine::Blob::Ptr input_blob = infer_request.GetBlob(inputs.begin()->first); - // fill input blob + InferenceEngine::Blob::Ptr input_blob1 = infer_request.GetBlob(inputs.begin()->first); + // fill first blob + InferenceEngine::SizeVector dims1 = input_blob1->getTensorDesc().getDims(); + InferenceEngine::MemoryBlob::Ptr minput1 = InferenceEngine::as(input_blob1); + if (minput1) { + // locked memory holder should be alive all time while access to its + // buffer happens + auto minputHolder = minput1->wmap(); + // Original I64 precision was converted to I32 + auto data = minputHolder.as::value_type*>(); + // Fill data ... + } + InferenceEngine::Blob::Ptr input_blob2 = infer_request.GetBlob("data2"); + // fill first blob + InferenceEngine::MemoryBlob::Ptr minput2 = InferenceEngine::as(input_blob2); + if (minput2) { + // locked memory holder should be alive all time while access to its + // buffer happens + auto minputHolder = minput2->wmap(); + // Original I64 precision was converted to I32 + auto data = minputHolder.as::value_type*>(); + // Fill data ... + } //! [ie:get_input_tensor] //! [ie:inference] @@ -37,7 +58,16 @@ int main() { //! [ie:get_output_tensor] InferenceEngine::Blob::Ptr output_blob = infer_request.GetBlob(outputs.begin()->first); - // process output data + InferenceEngine::MemoryBlob::Ptr moutput = InferenceEngine::as(output_blob); + if (moutput) { + // locked memory holder should be alive all time while access to its + // buffer happens + auto minputHolder = moutput->rmap(); + // Original I64 precision was converted to I32 + auto data = + minputHolder.as::value_type*>(); + // process output data + } //! [ie:get_output_tensor] return 0; } diff --git a/docs/snippets/ngraph.cpp b/docs/snippets/ngraph.cpp new file mode 100644 index 00000000000000..931140f99d9519 --- /dev/null +++ b/docs/snippets/ngraph.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#include +#include + +int main() { + //! [ngraph:graph] + // _____________ _____________ + // | Parameter | | Parameter | + // | data1 | | data2 | + // |___________| |___________| + // | | + // data1_t | | data2_t + // \ / + // \ / + // \ / + // ____\____/____ + // | Concat | + // | concat | + // |____________| + // | + // | concat_t + // | + // _______|_______ + // | Result | + // | result | + // |_____________| + auto data1 = std::make_shared(ngraph::element::i64, ngraph::Shape{1, 3, 2, 2}); + data1->set_friendly_name("data1"); // operation name + data1->output(0).set_names({"data1_t"}); // tensor names + auto data2 = std::make_shared(ngraph::element::i64, ngraph::Shape{1, 2, 2, 2}); + data2->set_friendly_name("data2"); // operation name + data2->output(0).set_names({"data2_t"}); // tensor names + + auto concat = std::make_shared(ngraph::OutputVector{data1, data2}, 1); + concat->set_friendly_name("concat"); // operation name + concat->output(0).set_names({"concat_t"}); // tensor name + + auto result = std::make_shared(concat); + result->set_friendly_name("result"); // operation name + + auto f = std::make_shared(ngraph::ResultVector{result}, + ngraph::ParameterVector{data1, data2}, + "function_name"); + //! [ngraph:graph] + return 0; +} diff --git a/docs/snippets/ov_common.cpp b/docs/snippets/ov_common.cpp index 7cb9e344f7cbaa..1392e3a509850f 100644 --- a/docs/snippets/ov_common.cpp +++ b/docs/snippets/ov_common.cpp @@ -1,9 +1,61 @@ // Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include +void inputs_v10(ov::runtime::InferRequest& infer_request) { + //! [ov_api_2_0:get_input_tensor_v10] + // Get input tensor by index + ov::runtime::Tensor input_tensor1 = infer_request.get_input_tensor(0); + // IR v10 works with converted precisions (i64 -> i32) + auto data1 = input_tensor1.data(); + // Fill first data ... + + // Get input tensor by tensor name + ov::runtime::Tensor input_tensor2 = infer_request.get_tensor("data2_t"); + // IR v10 works with converted precisions (i64 -> i32) + auto data2 = input_tensor1.data(); + // Fill first data ... + //! [ov_api_2_0:get_input_tensor_v10] +} + +void inputs_aligned(ov::runtime::InferRequest& infer_request) { + //! [ov_api_2_0:get_input_tensor_aligned] + // Get input tensor by index + ov::runtime::Tensor input_tensor1 = infer_request.get_input_tensor(0); + // Element types, names and layouts are aligned with framework + auto data1 = input_tensor1.data(); + // Fill first data ... + + // Get input tensor by tensor name + ov::runtime::Tensor input_tensor2 = infer_request.get_tensor("data2_t"); + // Element types, names and layouts are aligned with framework + auto data2 = input_tensor1.data(); + // Fill first data ... + //! [ov_api_2_0:get_input_tensor_aligned] +} + +void outputs_v10(ov::runtime::InferRequest& infer_request) { + //! [ov_api_2_0:get_output_tensor_v10] + // model has only one output + ov::runtime::Tensor output_tensor = infer_request.get_output_tensor(); + // IR v10 works with converted precisions (i64 -> i32) + auto out_data = output_tensor.data(); + // process output data + //! [ov_api_2_0:get_output_tensor_v10] +} + +void outputs_aligned(ov::runtime::InferRequest& infer_request) { + //! [ov_api_2_0:get_output_tensor_aligned] + // model has only one output + ov::runtime::Tensor output_tensor = infer_request.get_output_tensor(); + // Element types, names and layouts are aligned with framework + auto out_data = output_tensor.data(); + // process output data + //! [ov_api_2_0:get_output_tensor_aligned] +} + int main() { //! [ov_api_2_0:create_core] ov::runtime::Core core; @@ -14,21 +66,24 @@ int main() { //! [ov_api_2_0:read_model] //! [ov_api_2_0:get_inputs_outputs] - ov::ParameterVector inputs = network->get_parameters(); - ov::ResultVector outputs = network->get_results(); + std::vector> inputs = network->inputs(); + std::vector> outputs = network->outputs(); //! [ov_api_2_0:get_inputs_outputs] //! [ov_api_2_0:compile_model] ov::runtime::ExecutableNetwork exec_network = core.compile_model(network, "CPU"); //! [ov_api_2_0:compile_model] + //! [ov_api_2_0:create_infer_request] ov::runtime::InferRequest infer_request = exec_network.create_infer_request(); - // - // InferenceEngine::Blob::Ptr input_blob = infer_request.GetBlob(inputs.begin()->first); - // // fill input blob - // infer_request.Infer(); - // - // InferenceEngine::Blob::Ptr output_blob = infer_request.GetBlob(outputs.begin()->first); - // process output data + //! [ov_api_2_0:create_infer_request] + + inputs_aligned(infer_request); + //! [ov_api_2_0:inference] + infer_request.infer(); + //! [ov_api_2_0:inference] + + outputs_aligned(infer_request); + return 0; } diff --git a/docs/snippets/ov_graph.cpp b/docs/snippets/ov_graph.cpp new file mode 100644 index 00000000000000..b47abce44514cb --- /dev/null +++ b/docs/snippets/ov_graph.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +#include +#include + +int main() { + //! [ov:graph] + // _____________ _____________ + // | Parameter | | Parameter | + // | data1 | | data2 | + // |___________| |___________| + // | | + // data1_t | | data2_t + // \ / + // \ / + // \ / + // ____\____/____ + // | Concat | + // | concat | + // |____________| + // | + // | concat_t + // | + // _______|_______ + // | Result | + // | result | + // |_____________| + auto data1 = std::make_shared(ov::element::i64, ov::Shape{1, 3, 2, 2}); + data1->set_friendly_name("data1"); // operation name + data1->output(0).set_names({"data1_t"}); // tensor names + auto data2 = std::make_shared(ov::element::i64, ov::Shape{1, 2, 2, 2}); + data2->set_friendly_name("data2"); // operation name + data2->output(0).set_names({"data2_t"}); // tensor names + + auto concat = std::make_shared(ov::OutputVector{data1, data2}, 1); + concat->set_friendly_name("concat"); // operation name + concat->output(0).set_names({"concat_t"}); // tensor name + + auto result = std::make_shared(concat); + result->set_friendly_name("result"); // operation name + + auto f = + std::make_shared(ov::ResultVector{result}, ov::ParameterVector{data1, data2}, "function_name"); + //! [ov:graph] + return 0; +} diff --git a/docs/template_plugin/src/CMakeLists.txt b/docs/template_plugin/src/CMakeLists.txt index a6411523780629..e22bb0a6dedfa3 100644 --- a/docs/template_plugin/src/CMakeLists.txt +++ b/docs/template_plugin/src/CMakeLists.txt @@ -40,13 +40,5 @@ set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_REL # POSSIBLE_PLUGINS ${TARGET_NAME}) # [cmake:plugin] -# ATTENTION: uncomment to install component -# install - -# set(component_name template) -# ie_cpack_add_component(${component_name} REQUIRED) - -# install(TARGETS ${TARGET_NAME} -# RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} -# LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} -# COMPONENT ${component_name}) +ov_install_static_lib(ngraph_backend ngraph) +ov_install_static_lib(interpreter_backend ngraph) diff --git a/docs/template_plugin/src/template_executable_network.cpp b/docs/template_plugin/src/template_executable_network.cpp index 8479a027550b26..cff492f5c4acd7 100644 --- a/docs/template_plugin/src/template_executable_network.cpp +++ b/docs/template_plugin/src/template_executable_network.cpp @@ -218,7 +218,9 @@ void TemplatePlugin::ExecutableNetwork::Export(std::ostream& modelStream) { // Note: custom ngraph extensions are not supported std::map custom_opsets; std::stringstream xmlFile, binFile; + OPENVINO_SUPPRESS_DEPRECATED_START ov::pass::Serialize serializer(xmlFile, binFile, custom_opsets); + OPENVINO_SUPPRESS_DEPRECATED_END serializer.run_on_function(_function); auto m_constants = binFile.str(); diff --git a/docs/template_plugin/tests/functional/op_reference/batch_to_space.cpp b/docs/template_plugin/tests/functional/op_reference/batch_to_space.cpp new file mode 100644 index 00000000000000..600a5448d5804a --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/batch_to_space.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/opsets/opset1.hpp" +#include "openvino/opsets/opset2.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct BatchToSpaceParams { + BatchToSpaceParams(const Tensor& dataTensor, const Tensor& blockShapeTensor, + const Tensor& cropsBeginTensor, const Tensor& cropsEndTensor, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), blockShapeTensor(blockShapeTensor), + cropsBeginTensor(cropsBeginTensor), cropsEndTensor(cropsEndTensor), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor blockShapeTensor; + Tensor cropsBeginTensor; + Tensor cropsEndTensor; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceBatchToSpaceLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_bsType=" << param.blockShapeTensor.type; + result << "_bsShape=" << param.blockShapeTensor.shape; + result << "_cbType=" << param.cropsBeginTensor.type; + result << "_cbShape=" << param.cropsBeginTensor.shape; + result << "_ceType=" << param.cropsEndTensor.type; + result << "_ceShape=" << param.cropsEndTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const BatchToSpaceParams& params) { + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto blockShape = std::make_shared(element::i64, params.blockShapeTensor.shape, params.blockShapeTensor.data.data()); + const auto cropsBegin = std::make_shared(element::i64, params.cropsBeginTensor.shape, params.cropsBeginTensor.data.data()); + const auto cropsEnd = std::make_shared(element::i64, params.cropsEndTensor.shape, params.cropsEndTensor.data.data()); + const auto batchToSpace = std::make_shared(data, blockShape, cropsBegin, cropsEnd); + return std::make_shared(NodeVector {batchToSpace}, ParameterVector {data}); + } +}; + +TEST_P(ReferenceBatchToSpaceLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateBatchToSpaceParams() { + using T = typename element_type_traits::value_type; + std::vector batchToSpaceParams { + // input_with_shape_4x3 + BatchToSpaceParams( + Tensor({4, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}), + Tensor({2}, element::i64, std::vector{1, 2}), + Tensor({2}, element::i64, std::vector{0, 0}), + Tensor({2}, element::i64, std::vector{0, 0}), + Tensor({2, 6}, IN_ET, std::vector{1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12}), + "input_with_shape_4x3"), + + // input_with_shape_4x1x1x3 + BatchToSpaceParams( + Tensor({4, 1, 1, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}), + Tensor({4}, element::i64, std::vector{1, 1, 1, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({2, 1, 1, 6}, IN_ET, std::vector{1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12}), + "input_with_shape_4x1x1x3"), + // input_with_shape_4x1x1x3_1 + BatchToSpaceParams( + Tensor({4, 1, 1, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}), + Tensor({4}, element::i64, std::vector{1, 1, 2, 1}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({2, 1, 2, 3}, IN_ET, std::vector{1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12}), + "input_with_shape_4x1x1x3_1"), + // input_with_shape_4x1x1x3_2 + BatchToSpaceParams( + Tensor({4, 1, 1, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}), + Tensor({4}, element::i64, std::vector{1, 1, 2, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({2, 1, 1, 6}, IN_ET, std::vector{1, 4, 2, 5, 3, 6, 7, 10, 8, 11, 9, 12}), + "input_with_shape_4x1x1x3_2"), + + // input_with_shape_4x1x2x3 + BatchToSpaceParams( + Tensor({4, 1, 2, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24}), + Tensor({4}, element::i64, std::vector{1, 1, 1, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({2, 1, 2, 6}, IN_ET, std::vector{1, 13, 2, 14, 3, 15, + 4, 16, 5, 17, 6, 18, + 7, 19, 8, 20, 9, 21, + 10, 22, 11, 23, 12, 24}), + "input_with_shape_4x1x2x3"), + // input_with_shape_4x1x2x3_1 + BatchToSpaceParams( + Tensor({4, 1, 2, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24}), + Tensor({4}, element::i64, std::vector{1, 1, 2, 1}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({2, 1, 4, 3}, IN_ET, std::vector{1, 2, 3, 13, 14, 15, + 4, 5, 6, 16, 17, 18, + 7, 8, 9, 19, 20, 21, + 10, 11, 12, 22, 23, 24}), + "input_with_shape_4x1x2x3_1"), + // input_with_shape_4x1x2x3_2 + BatchToSpaceParams( + Tensor({4, 1, 2, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24}), + Tensor({4}, element::i64, std::vector{1, 1, 2, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({1, 1, 4, 6}, IN_ET, std::vector{1, 7, 2, 8, 3, 9, + 13, 19, 14, 20, 15, 21, + 4, 10, 5, 11, 6, 12, + 16, 22, 17, 23, 18, 24}), + "input_with_shape_4x1x2x3_2"), + + // input_with_shape_with_crop_4x1x2x3 + BatchToSpaceParams( + Tensor({4, 1, 2, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24}), + Tensor({4}, element::i64, std::vector{1, 1, 2, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 2}), + Tensor({1, 1, 4, 4}, IN_ET, std::vector{1, 7, 2, 8, 13, 19, 14, 20, + 4, 10, 5, 11, 16, 22, 17, 23}), + "input_with_shape_with_crop_4x1x2x3"), + // input_with_shape_with_crop_4x1x2x3_1 + BatchToSpaceParams( + Tensor({4, 1, 2, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24}), + Tensor({4}, element::i64, std::vector{1, 1, 2, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({1, 1, 4, 4}, IN_ET, std::vector{2, 8, 3, 9, 14, 20, 15, 21, + 5, 11, 6, 12, 17, 23, 18, 24}), + "input_with_shape_with_crop_4x1x2x3_1"), + // input_with_shape_with_crop_4x1x2x3_2 + BatchToSpaceParams( + Tensor({4, 1, 2, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24}), + Tensor({4}, element::i64, std::vector{1, 1, 2, 2}), + Tensor({4}, element::i64, std::vector{0, 0, 1, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 1, 0}), + Tensor({1, 1, 2, 6}, IN_ET, std::vector{13, 19, 14, 20, 15, 21, + 4, 10, 5, 11, 6, 12}), + "input_with_shape_with_crop_4x1x2x3_2"), + }; + return batchToSpaceParams; +} + +std::vector generateBatchToSpaceCombinedParams() { + const std::vector> batchToSpaceTypeParams { + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + generateBatchToSpaceParams(), + }; + std::vector combinedParams; + + for (const auto& params : batchToSpaceTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_BatchToSpace_With_Hardcoded_Refs, ReferenceBatchToSpaceLayerTest, + testing::ValuesIn(generateBatchToSpaceCombinedParams()), ReferenceBatchToSpaceLayerTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/ctc_greedy_decoder.cpp b/docs/template_plugin/tests/functional/op_reference/ctc_greedy_decoder.cpp new file mode 100644 index 00000000000000..c602d0d8ed9bb6 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/ctc_greedy_decoder.cpp @@ -0,0 +1,132 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/ctc_greedy_decoder.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct CTCGreedyDecoderParams { + CTCGreedyDecoderParams( + const Tensor& dataTensor, const Tensor& masksTensor, int64_t ctcMergedRepeat, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), masksTensor(masksTensor), ctcMergedRepeat(ctcMergedRepeat), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor masksTensor; + bool ctcMergedRepeat; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceCTCGreedyDecoderTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data, params.masksTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_aType=" << param.masksTensor.type; + result << "_aShape=" << param.masksTensor.shape; + result << "_bDims=" << param.ctcMergedRepeat; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const CTCGreedyDecoderParams& params) { + std::shared_ptr function; + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto indices = std::make_shared(params.masksTensor.type, params.masksTensor.shape); + const auto decoder = std::make_shared(data, indices, params.ctcMergedRepeat); + function = std::make_shared(NodeVector{decoder}, ParameterVector{data, indices}); + return function; + } +}; + +TEST_P(ReferenceCTCGreedyDecoderTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + CTCGreedyDecoderParams( + Tensor(IN_ET, {3, 1, 3}, std::vector{0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}), + Tensor(IN_ET, {3, 1}, std::vector{1.0f, 1.0f, 1.0f}), + false, + Tensor(IN_ET, {1, 3, 1, 1}, std::vector{1.0f, 0.0f, 1.0f}), + "ctc_greedy_decoder"), + CTCGreedyDecoderParams( + Tensor(IN_ET, {3, 2, 3}, std::vector{ + 0.1f, 0.2f, 0.f, 0.15f, 0.25f, 0.f, 0.4f, 0.3f, 0.f, 0.45f, 0.35f, 0.f, 0.5f, 0.6f, 0.f, 0.55f, 0.65f, 0.f}), + Tensor(IN_ET, {3, 2}, std::vector{1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}), + false, + Tensor(IN_ET, {2, 3, 1, 1}, std::vector{1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}), + "ctc_greedy_decoder_multiple_batches"), + CTCGreedyDecoderParams( + Tensor(IN_ET, {3, 1, 3}, std::vector{0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}), + Tensor(IN_ET, {3, 1}, std::vector{1.0f, 1.0f, 0.0f}), + false, + Tensor(IN_ET, {1, 3, 1, 1}, std::vector{1.0f, 0.0f, -1.0f}), + "ctc_greedy_decoder_single_batch_short_sequence"), + CTCGreedyDecoderParams( + Tensor(IN_ET, {3, 1, 3}, std::vector{0.1f, 0.2f, 0.f, 0.3f, 0.4f, 0.f, 0.6f, 0.5f, 0.f}), + Tensor(IN_ET, {3, 1}, std::vector{1.0f, 1.0f, 1.0f}), + true, + Tensor(IN_ET, {1, 3, 1, 1}, std::vector{1.0f, 0.0f, -1.0f}), + "ctc_greedy_decoder_merge"), + CTCGreedyDecoderParams( + Tensor(IN_ET, {3, 1, 3}, std::vector{0.1f, 0.2f, 0.f, 0.3f, 0.4f, 0.f, 0.6f, 0.5f, 0.f}), + Tensor(IN_ET, {3, 1}, std::vector{1.0f, 1.0f, 1.0f}), + false, + Tensor(IN_ET, {1, 3, 1, 1}, std::vector{1.0f, 1.0f, 0.0f}), + "ctc_greedy_decoder_single_no_merge"), + CTCGreedyDecoderParams( + Tensor(IN_ET, {2, 2, 3}, std::vector{0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f, 0.7f, 0.8f, 0.f}), + Tensor(IN_ET, {2, 2}, std::vector{1.0f, 1.0f, 1.0f, 0.0f}), + false, + Tensor(IN_ET, {2, 2, 1, 1}, std::vector{1.0f, 1.0f, 0.0f, -1.0f}), + "ctc_greedy_decoder_multiple_sequences"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_CTCGreedyDecoder_With_Hardcoded_Refs, ReferenceCTCGreedyDecoderTest, + testing::ValuesIn(generateCombinedParams()), ReferenceCTCGreedyDecoderTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/ctc_greedy_decoder_seq_len.cpp b/docs/template_plugin/tests/functional/op_reference/ctc_greedy_decoder_seq_len.cpp new file mode 100644 index 00000000000000..36b37523d3a2e8 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/ctc_greedy_decoder_seq_len.cpp @@ -0,0 +1,228 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/ctc_greedy_decoder_seq_len.hpp" +#include "openvino/op/constant.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct CTCGreedyDecoderSeqLenParams { + CTCGreedyDecoderSeqLenParams( + const Tensor& dataTensor, const Tensor& seqLenTensor, const Tensor& blankIndexTensor, int64_t mergeRepeated, + const Tensor& expectedTensor, const Tensor& expectedTensor2, const std::string& testcaseName = "") : + dataTensor(dataTensor), seqLenTensor(seqLenTensor), blankIndexTensor(blankIndexTensor), mergeRepeated(mergeRepeated), + expectedTensor(expectedTensor), expectedTensor2(expectedTensor2), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor seqLenTensor; + Tensor blankIndexTensor; + bool mergeRepeated; + Tensor expectedTensor; + Tensor expectedTensor2; + std::string testcaseName; +}; + +struct CTCGreedyDecoderSeqLenParamsNoOptionalInput { + CTCGreedyDecoderSeqLenParamsNoOptionalInput( + const Tensor& dataTensor, const Tensor& seqLenTensor, int64_t mergeRepeated, + const Tensor& expectedTensor, const Tensor& expectedTensor2, const std::string& testcaseName = "") : + dataTensor(dataTensor), seqLenTensor(seqLenTensor), mergeRepeated(mergeRepeated), + expectedTensor(expectedTensor), expectedTensor2(expectedTensor2), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor seqLenTensor; + bool mergeRepeated; + Tensor expectedTensor; + Tensor expectedTensor2; + std::string testcaseName; +}; + +class ReferenceCTCGreedyDecoderSeqLenTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data, params.seqLenTensor.data}; + refOutData = {params.expectedTensor.data, params.expectedTensor2.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_sType=" << param.seqLenTensor.type; + result << "_sShape=" << param.seqLenTensor.shape; + result << "_bType=" << param.blankIndexTensor.type; + result << "_bShape=" << param.blankIndexTensor.shape; + result << "_mRepeated=" << param.mergeRepeated; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const CTCGreedyDecoderSeqLenParams& params) { + std::shared_ptr function; + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto seq_len = std::make_shared(params.seqLenTensor.type, params.seqLenTensor.shape); + auto blank_index = std::make_shared(params.blankIndexTensor.type, params.blankIndexTensor.shape, + params.blankIndexTensor.data.data()); + const auto decoder = std::make_shared(data, seq_len, blank_index, params.mergeRepeated); + function = std::make_shared(decoder->outputs(), ParameterVector{data, seq_len}); + return function; + } +}; + +class ReferenceCTCGreedyDecoderSeqLenTestNoOptionalInput : + public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data, params.seqLenTensor.data}; + refOutData = {params.expectedTensor.data, params.expectedTensor2.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_sType=" << param.seqLenTensor.type; + result << "_sShape=" << param.seqLenTensor.shape; + result << "_mRepeated=" << param.mergeRepeated; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const CTCGreedyDecoderSeqLenParamsNoOptionalInput& params) { + std::shared_ptr function; + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto seq_len = std::make_shared(params.seqLenTensor.type, params.seqLenTensor.shape); + const auto decoder = std::make_shared(data, seq_len, params.mergeRepeated); + function = std::make_shared(decoder->outputs(), ParameterVector{data, seq_len}); + return function; + } +}; + +TEST_P(ReferenceCTCGreedyDecoderSeqLenTest, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceCTCGreedyDecoderSeqLenTestNoOptionalInput, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + CTCGreedyDecoderSeqLenParams( + Tensor(ET, {1, 3, 3}, std::vector{0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}), + Tensor(element::i32, {1}, std::vector{2}), + Tensor(element::i32, {}, std::vector{2}), + false, + Tensor(element::i32, {1, 3}, std::vector{1, 0, -1}), + Tensor(element::i32, {1}, std::vector{2}), + "evaluate_ctc_greedy_decoder_seq_len"), + CTCGreedyDecoderSeqLenParams( + Tensor(ET, {1, 3, 3}, std::vector{0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}), + Tensor(element::i32, {1}, std::vector{2}), + Tensor(element::i32, {}, std::vector{2}), + true, + Tensor(element::i32, {1, 3}, std::vector{1, 0, -1}), + Tensor(element::i32, {1}, std::vector{2}), + "evaluate_ctc_greedy_decoder_seq_len_merge"), + CTCGreedyDecoderSeqLenParams( + Tensor(ET, {2, 3, 3}, std::vector{0.1f, 0.2f, 0.f, 0.15f, 0.25f, 0.f, 0.4f, 0.3f, 0.f, + 0.45f, 0.35f, 0.f, 0.5f, 0.6f, 0.f, 0.55f, 0.65f, 0.f}), + Tensor(element::i32, {2}, std::vector{1, 1}), + Tensor(element::i32, {}, std::vector{2}), + false, + Tensor(element::i32, {2, 3}, std::vector{1, -1, -1, 0, -1, -1}), + Tensor(element::i32, {2}, std::vector{1, 1}), + "evaluate_ctc_greedy_decoder_seq_len_multiple_batches"), + CTCGreedyDecoderSeqLenParams( + Tensor(ET, {3, 3, 3}, std::vector{0.1f, 0.2f, 0.f, 0.15f, 0.25f, 0.f, 0.4f, 0.3f, 0.f, + 0.45f, 0.35f, 0.f, 0.5f, 0.6f, 0.f, 0.55f, 0.65f, 0.f, + 0.1f, 0.2f, 0.f, 0.15f, 0.25f, 0.f, 0.4f, 0.3f, 0.f}), + Tensor(element::i32, {3}, std::vector{2, 3, 1}), + Tensor(element::i32, {}, std::vector{2}), + false, + Tensor(element::i32, {3, 3}, std::vector{1, 1, -1, 0, 1, 1, 1, -1, -1}), + Tensor(element::i32, {3}, std::vector{2, 3, 1}), + "evaluate_ctc_greedy_decoder_seq_len_multiple_batches2"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParamsNoOptionalInput() { + using T = typename element_type_traits::value_type; + std::vector params { + CTCGreedyDecoderSeqLenParamsNoOptionalInput( + Tensor(ET, {1, 3, 3}, std::vector{0.1f, 0.2f, 0.f, 0.4f, 0.3f, 0.f, 0.5f, 0.6f, 0.f}), + Tensor(element::i32, {1}, std::vector{2}), + false, + Tensor(element::i32, {1, 3}, std::vector{1, 0, -1}), + Tensor(element::i32, {1}, std::vector{2}), + "evaluate_ctc_greedy_decoder_seq_len_no_optional_input"), + }; + return params; +} + +std::vector generateCombinedParamsNoOptionalInput() { + const std::vector> generatedParams { + generateParamsNoOptionalInput(), + generateParamsNoOptionalInput(), + generateParamsNoOptionalInput(), + generateParamsNoOptionalInput(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_CTCGreedyDecoderSeqLen_With_Hardcoded_Refs, ReferenceCTCGreedyDecoderSeqLenTest, + testing::ValuesIn(generateCombinedParams()), ReferenceCTCGreedyDecoderSeqLenTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_CTCGreedyDecoderSeqLen_With_Hardcoded_Refs, ReferenceCTCGreedyDecoderSeqLenTestNoOptionalInput, + testing::ValuesIn(generateCombinedParamsNoOptionalInput()), ReferenceCTCGreedyDecoderSeqLenTestNoOptionalInput::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/depth_to_space.cpp b/docs/template_plugin/tests/functional/op_reference/depth_to_space.cpp new file mode 100644 index 00000000000000..b317ece708ffdb --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/depth_to_space.cpp @@ -0,0 +1,157 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/opsets/opset1.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct DepthToSpaceParams { + DepthToSpaceParams(const Tensor& dataTensor, const std::string mode, const int32_t blockSize, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), mode(mode), blockSize(blockSize), expectedTensor(expectedTensor), + testcaseName(testcaseName) {} + + Tensor dataTensor; + std::string mode; + int32_t blockSize; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceDepthToSpaceLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const DepthToSpaceParams& params) { + opset1::DepthToSpace::DepthToSpaceMode mode = params.mode == "DEPTH_FIRST" ? + opset1::DepthToSpace::DepthToSpaceMode::DEPTH_FIRST : opset1::DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST; + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto depthToSpace = std::make_shared(data, mode, params.blockSize); + return std::make_shared(NodeVector {depthToSpace}, ParameterVector {data}); + } +}; + +TEST_P(ReferenceDepthToSpaceLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateDepthToSpaceParams() { + using T = typename element_type_traits::value_type; + std::vector depthToSpaceParams { + // depth_to_space_block_first_K1_BS2 + DepthToSpaceParams( + Tensor({1, 8, 2}, IN_ET, std::vector{0, 2, 8, 10, 16, 18, 24, 26, 1, 3, 9, 11, 17, 19, 25, 27}), + "BLOCKS_FIRST", + 2, + Tensor({1, 4, 4}, IN_ET, std::vector{0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27}), + "depth_to_space_block_first_K1_BS2"), + + // depth_to_space_block_first_K2_BS2 + DepthToSpaceParams( + Tensor({1, 8, 2, 2}, IN_ET, std::vector{0, 2, 8, 10, 16, 18, 24, 26, 1, 3, 9, + 11, 17, 19, 25, 27, 4, 6, 12, 14, 20, 22, + 28, 30, 5, 7, 13, 15, 21, 23, 29, 31}), + "BLOCKS_FIRST", + 2, + Tensor({1, 2, 4, 4}, IN_ET, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}), + "depth_to_space_block_first_K2_BS2"), + + // depth_to_space_block_first_K2_BS4 + DepthToSpaceParams( + Tensor({1, 16, 2, 1}, IN_ET, std::vector{0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, + 21, 6, 22, 7, 23, 8, 24, 9, 25, 10, 26, + 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}), + "BLOCKS_FIRST", + 4, + Tensor({1, 1, 8, 4}, IN_ET, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}), + "depth_to_space_block_first_K2_BS4"), + + // depth_to_space_depth_first_1K_BS2 + DepthToSpaceParams( + Tensor({1, 8, 2}, IN_ET, std::vector{0, 2, 1, 3, 4, 6, 5, 7, 8, 10, 9, 11, 12, 14, 13, 15}), + "DEPTH_FIRST", + 2, + Tensor({1, 4, 4}, IN_ET, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}), + "depth_to_space_depth_first_1K_BS2"), + + // depth_to_space_depth_first_2K_BS2 + DepthToSpaceParams( + Tensor({1, 8, 2, 2}, IN_ET, std::vector{0, 2, 8, 10, 16, 18, 24, 26, 1, 3, 9, + 11, 17, 19, 25, 27, 4, 6, 12, 14, 20, 22, + 28, 30, 5, 7, 13, 15, 21, 23, 29, 31}), + "DEPTH_FIRST", + 2, + Tensor({1, 2, 4, 4}, IN_ET, std::vector{0, 16, 2, 18, 1, 17, 3, 19, 8, 24, 10, 26, 9, 25, 11, 27, + 4, 20, 6, 22, 5, 21, 7, 23, 12, 28, 14, 30, 13, 29, 15, 31}), + "depth_to_space_depth_first_2K_BS2"), + + // depth_to_space_depth_first_2K_BS4 + DepthToSpaceParams( + Tensor({1, 16, 2, 1}, IN_ET, std::vector{0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, + 21, 6, 22, 7, 23, 8, 24, 9, 25, 10, 26, + 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}), + "DEPTH_FIRST", + 4, + Tensor({1, 1, 8, 4}, IN_ET, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}), + "depth_to_space_depth_first_2K_BS4"), + }; + return depthToSpaceParams; +} + +std::vector generateDepthToSpaceCombinedParams() { + const std::vector> depthToSpaceTypeParams { + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + generateDepthToSpaceParams(), + }; + std::vector combinedParams; + + for (const auto& params : depthToSpaceTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_DepthToSpace_With_Hardcoded_Refs, ReferenceDepthToSpaceLayerTest, + testing::ValuesIn(generateDepthToSpaceCombinedParams()), ReferenceDepthToSpaceLayerTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/embedding_segments_sum.cpp b/docs/template_plugin/tests/functional/op_reference/embedding_segments_sum.cpp new file mode 100644 index 00000000000000..5a0924b929ea48 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/embedding_segments_sum.cpp @@ -0,0 +1,214 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ngraph; +using namespace InferenceEngine; + +struct EmbeddingSegmentsSumParams { + template + EmbeddingSegmentsSumParams(const ov::PartialShape& iShape, + const ov::element::Type& iType, + const std::vector& iValues, + const ov::PartialShape& oShape, + const ov::element::Type& oType, + const std::vector& oValues, + const std::shared_ptr& indices, + const std::shared_ptr& segment_ids, + const std::shared_ptr& num_segments, + const std::shared_ptr& default_index = nullptr, + const std::shared_ptr& per_sample_weights = nullptr) + : _iShape(iShape), + _iType(iType), + _iData(CreateTensor(iType, iValues)), + _refShape(oShape), + _refType(oType), + _refData(CreateTensor(oType, oValues)) { + _segmentIds = segment_ids; + _indices = indices; + _numSegments = num_segments; + _defaultIndex = default_index; + _perSampleWeights = per_sample_weights; + } + + ov::PartialShape _iShape; + ov::element::Type _iType; + ov::runtime::Tensor _iData; + + ov::PartialShape _refShape; + ov::element::Type _refType; + ov::runtime::Tensor _refData; + + std::shared_ptr _indices; + std::shared_ptr _segmentIds; + std::shared_ptr _numSegments; + std::shared_ptr _defaultIndex; // Optional, default filled zero. + std::shared_ptr _perSampleWeights; // Optional, default is tensor of ones. +}; + +class ReferenceEmbeddingSegmentsSumLayerTest : public testing::TestWithParam, + public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params._iShape, + params._iType, + params._indices, + params._segmentIds, + params._numSegments, + params._defaultIndex, + params._perSampleWeights); + inputData = {params._iData}; + refOutData = {params._refData}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "_iShape=" << param._iShape << "_"; + result << "_iType=" << param._iType << "_"; + result << "_refShape=" << param._refShape << "_"; + result << "_refType=" << param._refType; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction( + const PartialShape& input_shape, + const element::Type& input_type, + const std::shared_ptr indices, + const std::shared_ptr segment_ids, + const std::shared_ptr num_segments, + const std::shared_ptr default_index, + const std::shared_ptr per_sample_weights) { + const auto in = std::make_shared(input_type, input_shape); + + if (default_index) { + if (per_sample_weights) { + const auto ess = std::make_shared(in, + indices, + segment_ids, + num_segments, + default_index, + per_sample_weights); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } else { + const auto ess = std::make_shared(in, + indices, + segment_ids, + num_segments, + default_index); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } + } else { + const auto ess = std::make_shared(in, indices, segment_ids, num_segments); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } + } +}; + +TEST_P(ReferenceEmbeddingSegmentsSumLayerTest, CompareWithRefs) { + Exec(); +} + +INSTANTIATE_TEST_SUITE_P( + smoke_EmbeddingSegmentsSum_With_Hardcoded_Refs, + ReferenceEmbeddingSegmentsSumLayerTest, + ::testing::Values( + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::f32, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f32, + {-1.05f, -1.2f, -0.2f, -0.6f, -0.1f, 0.4f}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{3}), + std::make_shared(element::i32, ov::Shape(), std::vector{0}), + std::make_shared(element::f32, + ov::Shape({4}), + std::vector{0.5, 0.5, 0.5, 0.5})), + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::f64, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f64, + std::vector{-2.1, -2.4, -0.2, -0.6, -0.2, 0.8}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{3}), + std::make_shared(element::i32, ov::Shape(), std::vector{0})), + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::i32, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i32, + std::vector{-6, -4, 0, 0, 2, 18}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{3})), + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::u32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::u32, + std::vector{6, 8, 3, 4, 16, 18}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{3}), + std::make_shared(element::i32, ov::Shape(), std::vector{1})), + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::f16, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f16, + std::vector{-2.1, -2.4, 0, 0, -0.2, 0.8}, + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i64, ov::Shape(), std::vector{3})), + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::i64, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i64, + std::vector{-6, -4, -1, 2, 2, 18}, + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i64, ov::Shape(), std::vector{3}), + std::make_shared(element::i64, ov::Shape(), std::vector{0})), + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::i8, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i8, + std::vector{-12, -8, -1, 2, 4, 36}, + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i64, ov::Shape(), std::vector{3}), + std::make_shared(element::i64, ov::Shape(), std::vector{0}), + std::make_shared(element::i8, ov::Shape({4}), std::vector{2, 2, 2, 2})), + EmbeddingSegmentsSumParams( + ov::PartialShape{5, 2}, + ov::element::u8, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::u8, + std::vector{6, 8, 1, 2, 16, 18}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{3}), + std::make_shared(element::i32, ov::Shape(), std::vector{0}))), + ReferenceEmbeddingSegmentsSumLayerTest::getTestCaseName); diff --git a/docs/template_plugin/tests/functional/op_reference/embeddingbag_offsetssum.cpp b/docs/template_plugin/tests/functional/op_reference/embeddingbag_offsetssum.cpp new file mode 100644 index 00000000000000..4c137d5bf643a2 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/embeddingbag_offsetssum.cpp @@ -0,0 +1,195 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ngraph; +using namespace InferenceEngine; + +struct EmbeddingBagOffsetsSumParams { + template + EmbeddingBagOffsetsSumParams(const ov::PartialShape& iShape, + const ov::element::Type& iType, + const std::vector& iValues, + const ov::PartialShape& oShape, + const ov::element::Type& oType, + const std::vector& oValues, + const std::shared_ptr& indices, + const std::shared_ptr& offsets, + const std::shared_ptr& default_index = nullptr, + const std::shared_ptr& per_sample_weights = nullptr) + : _iShape(iShape), + _iType(iType), + _iData(CreateTensor(iType, iValues)), + _refShape(oShape), + _refType(oType), + _refData(CreateTensor(oType, oValues)) { + _indices = indices; + _offsets = offsets; + _defaultIndex = default_index; + _perSampleWeights = per_sample_weights; + } + ov::PartialShape _iShape; + ov::element::Type _iType; + ov::runtime::Tensor _iData; + + ov::PartialShape _refShape; + ov::element::Type _refType; + ov::runtime::Tensor _refData; + + std::shared_ptr _indices; + std::shared_ptr _offsets; + std::shared_ptr _defaultIndex; // Optional, default filled zero. + std::shared_ptr _perSampleWeights; // Optional, default is tensor of ones. +}; + +class ReferenceEmbeddingBagOffsetsSumLayerTest : public testing::TestWithParam, + public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params._iShape, + params._iType, + params._indices, + params._offsets, + params._defaultIndex, + params._perSampleWeights); + inputData = {params._iData}; + refOutData = {params._refData}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "_iShape=" << param._iShape << "_"; + result << "_iType=" << param._iType << "_"; + result << "_refShape=" << param._refShape << "_"; + result << "_refType=" << param._refType; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction( + const PartialShape& input_shape, + const element::Type& input_type, + const std::shared_ptr indices, + const std::shared_ptr offsets, + const std::shared_ptr default_index, + const std::shared_ptr per_sample_weights) { + const auto in = std::make_shared(input_type, input_shape); + + if (default_index) { + if (per_sample_weights) { + const auto ess = std::make_shared(in, + indices, + offsets, + default_index, + per_sample_weights); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } else { + const auto ess = std::make_shared(in, indices, offsets, default_index); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } + } else { + const auto ess = std::make_shared(in, indices, offsets); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } + } +}; + +TEST_P(ReferenceEmbeddingBagOffsetsSumLayerTest, CompareWithRefs) { + Exec(); +} + +INSTANTIATE_TEST_SUITE_P( + smoke_EmbeddingBagOffsetsSum_With_Hardcoded_Refs, + ReferenceEmbeddingBagOffsetsSumLayerTest, + ::testing::Values( + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::f32, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f32, + {-1.05f, -1.2f, -0.2f, -0.6f, -0.1f, 0.4f}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({3}), std::vector{0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{0}), + std::make_shared(element::f32, + ov::Shape({4}), + std::vector{0.5, 0.5, 0.5, 0.5})), + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::f64, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f64, + std::vector{-2.1, -2.4, -0.2, -0.6, -0.2, 0.8}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({3}), std::vector{0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{0})), + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::i32, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i32, + std::vector{-6, -4, 0, 0, 2, 18}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({3}), std::vector{0, 2, 2})), + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::u32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::u32, + std::vector{6, 8, 3, 4, 16, 18}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({3}), std::vector{0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{1})), + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::f16, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f16, + std::vector{-2.1, -2.4, 0, 0, -0.2, 0.8}, + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i64, ov::Shape({3}), std::vector{0, 2, 2})), + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::i64, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i64, + std::vector{-6, -4, -1, 2, 2, 18}, + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i64, ov::Shape({3}), std::vector{0, 2, 2}), + std::make_shared(element::i64, ov::Shape(), std::vector{0})), + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::i8, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i8, + std::vector{-12, -8, -1, 2, 4, 36}, + std::make_shared(element::i64, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i64, ov::Shape({3}), std::vector{0, 2, 2}), + std::make_shared(element::i64, ov::Shape(), std::vector{0}), + std::make_shared(element::i8, ov::Shape({4}), std::vector{2, 2, 2, 2})), + EmbeddingBagOffsetsSumParams( + ov::PartialShape{5, 2}, + ov::element::u8, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::u8, + std::vector{6, 8, 1, 2, 16, 18}, + std::make_shared(element::i32, ov::Shape({4}), std::vector{0, 2, 3, 4}), + std::make_shared(element::i32, ov::Shape({3}), std::vector{0, 2, 2}), + std::make_shared(element::i32, ov::Shape(), std::vector{0}))), + ReferenceEmbeddingBagOffsetsSumLayerTest::getTestCaseName); diff --git a/docs/template_plugin/tests/functional/op_reference/embeddingbag_packedsum.cpp b/docs/template_plugin/tests/functional/op_reference/embeddingbag_packedsum.cpp new file mode 100644 index 00000000000000..0ae1bce6d9f9d3 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/embeddingbag_packedsum.cpp @@ -0,0 +1,170 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include + +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ngraph; +using namespace InferenceEngine; + +struct EmbeddingBagPackedSumParams { + template + EmbeddingBagPackedSumParams(const ov::PartialShape& iShape, + const ov::element::Type& iType, + const std::vector& iValues, + const ov::PartialShape& oShape, + const ov::element::Type& oType, + const std::vector& oValues, + const std::shared_ptr& indices, + const std::shared_ptr& per_sample_weights = nullptr) + : _iShape(iShape), + _iType(iType), + _iData(CreateTensor(iType, iValues)), + _refShape(oShape), + _refType(oType), + _refData(CreateTensor(oType, oValues)) { + _indices = indices; + _perSampleWeights = per_sample_weights; + } + ov::PartialShape _iShape; + ov::element::Type _iType; + ov::runtime::Tensor _iData; + + ov::PartialShape _refShape; + ov::element::Type _refType; + ov::runtime::Tensor _refData; + + std::shared_ptr _indices; + std::shared_ptr _perSampleWeights; // Optional, default is tensor of ones. +}; + +class ReferenceEmbeddingBagPackedSumLayerTest : public testing::TestWithParam, + public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params._iShape, params._iType, params._indices, params._perSampleWeights); + inputData = {params._iData}; + refOutData = {params._refData}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "_iShape=" << param._iShape << "_"; + result << "_iType=" << param._iType << "_"; + result << "_refShape=" << param._refShape << "_"; + result << "_refType=" << param._refType; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction( + const PartialShape& input_shape, + const element::Type& input_type, + const std::shared_ptr indices, + const std::shared_ptr per_sample_weights) { + const auto in = std::make_shared(input_type, input_shape); + + if (per_sample_weights) { + const auto ess = std::make_shared(in, indices, per_sample_weights); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } else { + const auto ess = std::make_shared(in, indices); + return std::make_shared(NodeVector{ess}, ParameterVector{in}); + } + } +}; + +TEST_P(ReferenceEmbeddingBagPackedSumLayerTest, CompareWithRefs) { + Exec(); +} + +template +inline std::shared_ptr CreateConstant(const std::vector>& val, + const ov::element::Type& element_type) { + if (val.size() > 0) { + ov::Shape i_shape({val.size(), val[0].size()}); + + size_t i_size = ov::shape_size(i_shape); + std::vector i_values(i_size); + + for (size_t i = 0; i < i_shape[0]; i++) { + for (size_t j = 0; j < i_shape[1]; j++) { + i_values[i * i_shape[1] + j] = val[i][j]; + } + } + + return std::make_shared(element_type, i_shape, i_values); + } else { + return std::make_shared(element_type, ov::Shape(), std::vector()); + } +} + +INSTANTIATE_TEST_SUITE_P( + smoke_EmbeddingBagPackedSum_With_Hardcoded_Refs, + ReferenceEmbeddingBagPackedSumLayerTest, + ::testing::Values( + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::f32, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f32, + std::vector{-1.05f, -1.2f, -1.f, -1.1f, -0.1f, 0.4f}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i32), + CreateConstant({{0.5, 0.5}, {0.5, 0.5}, {0.5, 0.5}}, element::f32)), + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::f64, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f64, + std::vector{-2.1, -2.4, -2.0, -2.2, -0.2, 0.8}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i32)), + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::i32, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i32, + std::vector{-6, -4, -2, -2, 2, 18}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i32)), + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::u32, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::u32, + std::vector{6, 8, 8, 10, 16, 18}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i32)), + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::f16, + std::vector{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7}, + ov::PartialShape{3, 2}, + ov::element::f16, + std::vector{-2.1, -2.4, -2.0, -2.2, -0.2, 0.8}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i64)), + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::i64, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i64, + std::vector{-6, -4, -2, -2, 2, 18}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i64)), + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::i8, + std::vector{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::i8, + std::vector{-12, -8, -4, -4, 4, 36}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i64), + CreateConstant({{2, 2}, {2, 2}, {2, 2}}, element::i8)), + EmbeddingBagPackedSumParams(ov::PartialShape{5, 2}, + ov::element::u8, + std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ov::PartialShape{3, 2}, + ov::element::u8, + std::vector{6, 8, 8, 10, 16, 18}, + CreateConstant({{0, 2}, {1, 2}, {3, 4}}, element::i64))), + ReferenceEmbeddingBagPackedSumLayerTest::getTestCaseName); diff --git a/docs/template_plugin/tests/functional/op_reference/experimental_detectron_topkrois.cpp b/docs/template_plugin/tests/functional/op_reference/experimental_detectron_topkrois.cpp new file mode 100644 index 00000000000000..3fe9dce3ebd209 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/experimental_detectron_topkrois.cpp @@ -0,0 +1,108 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/experimental_detectron_topkrois.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct ExperimentalDetectronTopKROIsParams { + ExperimentalDetectronTopKROIsParams( + const Tensor& dataTensor, const Tensor& probsTensor, const int32_t numRois, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), probsTensor(probsTensor), numRois(numRois), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor probsTensor; + int32_t numRois; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceExperimentalDetectronTopKROIsTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data, params.probsTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_pType=" << param.probsTensor.type; + result << "_pShape=" << param.probsTensor.shape; + result << "_numRois=" << param.numRois; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const ExperimentalDetectronTopKROIsParams& params) { + std::shared_ptr function; + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto probs = std::make_shared(params.probsTensor.type, params.probsTensor.shape); + const auto topkRois = std::make_shared(data, probs, params.numRois); + function = std::make_shared(topkRois, ParameterVector{data, probs}); + return function; + } +}; + +TEST_P(ReferenceExperimentalDetectronTopKROIsTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + ExperimentalDetectronTopKROIsParams( + Tensor(ET, {2, 4}, std::vector{1.0f, 1.0f, 3.0f, 4.0f, 2.0f, 1.0f, 5.0f, 7.0f}), + Tensor(ET, {2}, std::vector{0.5f, 0.3f}), + 1, + Tensor(ET, {1, 4}, std::vector{1.0, 1.0, 3.0, 4.0}), + "experimental_detectron_topk_rois_eval"), + ExperimentalDetectronTopKROIsParams( + Tensor(ET, {4, 4}, std::vector{1.0f, 1.0f, 4.0f, 5.0f, 3.0f, 2.0f, 7.0f, 9.0f, + 10.0f, 15.0f, 13.0f, 17.0f, 13.0f, 10.0f, 18.0f, 15.0f}), + Tensor(ET, {4}, std::vector{0.1f, 0.7f, 0.5f, 0.9f}), + 2, + Tensor(ET, {2, 4}, std::vector{13.0f, 10.0f, 18.0f, 15.0f, 3.0f, 2.0f, 7.0f, 9.0f}), + "experimental_detectron_topk_rois_eval"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_ExperimentalDetectronTopKROIs_With_Hardcoded_Refs, ReferenceExperimentalDetectronTopKROIsTest, + testing::ValuesIn(generateCombinedParams()), ReferenceExperimentalDetectronTopKROIsTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/gather.cpp b/docs/template_plugin/tests/functional/op_reference/gather.cpp new file mode 100644 index 00000000000000..a76021ab692964 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/gather.cpp @@ -0,0 +1,880 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/gather.hpp" +#include "openvino/op/constant.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct GatherParams { + GatherParams( + const Tensor& dataTensor, const Tensor& indicesTensor, const Tensor& axisTensor, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), indicesTensor(indicesTensor), axisTensor(axisTensor), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor indicesTensor; + Tensor axisTensor; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceGatherTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data, params.indicesTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_iType=" << param.indicesTensor.type; + result << "_iShape=" << param.indicesTensor.shape; + result << "_aType=" << param.axisTensor.type; + result << "_aShape=" << param.axisTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const GatherParams& params) { + const auto P = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto I = std::make_shared(params.indicesTensor.type, params.indicesTensor.shape); + const auto A = op::v0::Constant::create(params.axisTensor.type, params.axisTensor.shape, + params.axisTensor.data.data()); + const auto G = std::make_shared(P, I, A); + const auto f = std::make_shared(G, ParameterVector{P, I}); + return f; + } +}; + +TEST_P(ReferenceGatherTest, CompareWithRefs) { + Exec(); +} + +struct GatherParamsV7 { + GatherParamsV7( + const Tensor& dataTensor, const Tensor& indicesTensor, const Tensor& axisTensor, int64_t batchDims, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), indicesTensor(indicesTensor), axisTensor(axisTensor), batchDims(batchDims), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor indicesTensor; + Tensor axisTensor; + int64_t batchDims; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceGatherTestV7 : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data, params.indicesTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_iType=" << param.indicesTensor.type; + result << "_iShape=" << param.indicesTensor.shape; + result << "_aType=" << param.axisTensor.type; + result << "_aShape=" << param.axisTensor.shape; + result << "_batchDims=" << param.batchDims; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const GatherParamsV7& params) { + const auto P = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto I = std::make_shared(params.indicesTensor.type, params.indicesTensor.shape); + const auto A = op::v0::Constant::create(params.axisTensor.type, params.axisTensor.shape, + params.axisTensor.data.data()); + const auto G = std::make_shared(P, I, A, params.batchDims); + const auto f = std::make_shared(G, ParameterVector{P, I}); + return f; + } +}; + +TEST_P(ReferenceGatherTestV7, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + using T_I = typename element_type_traits::value_type; + using T_A = typename element_type_traits::value_type; + std::vector params { + GatherParams( + Tensor(ET, {3, 2}, std::vector{ + 10, 11, 20, 21, 30, 31}), + Tensor(ET_I, {2, 2, 3, 4}, std::vector{ + 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, + 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2, 2, 3, 4, 2}, std::vector{ + 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31, + 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31, + 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31, + 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31, 10, 11, 20, 21, 20, 21, 30, 31}), + "gather_4d_indices_axis_0"), + GatherParams( + Tensor(ET, {3, 2}, std::vector{ + 10, 11, 20, 21, 30, 31}), + Tensor(ET_I, {2, 2}, std::vector{ + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2, 2, 2}, std::vector{ + 10, 11, 20, 21, 20, 21, 30, 31}), + "gather_axis_0"), + }; + return params; +} + +template +std::vector generateParamsFloatValue() { + using T = typename element_type_traits::value_type; + using T_I = typename element_type_traits::value_type; + using T_A = typename element_type_traits::value_type; + std::vector params { + GatherParams( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 2, 3, 4}, std::vector{ + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2, 2, 3, 4, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_4d_indices_axis_0_2d_input"), + GatherParams( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 3, 4}, std::vector{ + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2, 3, 4, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_3d_indices_axis_0_2d_input"), + GatherParams( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 2}, std::vector{ + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2, 2, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_2d_indices_axis_0_2d_input"), + GatherParams( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 2}, std::vector{ + 0, -2, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2, 2, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_2d_negative_and_positive_indices_axis_0_2d_input"), + GatherParams( + Tensor(ET, {3}, std::vector{ + 1.0f, 2.0f, 3.0f}), + Tensor(ET_I, {2}, std::vector{ + 1, 0}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2}, std::vector{ + 2.0f, 1.0f}), + "gather_1d_indices_axis_0_1d_input"), + GatherParams( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, 2.0f, 2.1f, 3.0f, 3.1f}), + Tensor(ET_I, {}, std::vector{1}), + Tensor(ET_A, {}, std::vector{0}), + Tensor(ET, {2}, std::vector{ + 2.0f, 2.1f}), + "gather_scalar_indices_axis_0_2d_input"), + GatherParams( + Tensor(ET, {3, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, + 2.0f, 2.1f, 2.2f, + 3.0f, 3.1f, 3.2f}), + Tensor(ET_I, {1, 2}, std::vector{ + 0, 2}), + Tensor(ET_A, {}, std::vector{1}), + Tensor(ET, {3, 1, 2}, std::vector{ + 1.0f, 1.2f, + 2.0f, 2.2f, + 3.0f, 3.2f}), + "gather_2d_indices_axis_1_2d_input"), + GatherParams( + Tensor(ET, {2, 2, 3, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, + 2.0f, 2.1f, 2.2f, + 3.0f, 3.1f, 3.2f, + + 11.0f, 11.1f, 11.2f, + 12.0f, 12.1f, 12.2f, + 13.0f, 13.1f, 13.2f, + + + 101.0f, 101.1f, 101.2f, + 102.0f, 102.1f, 102.2f, + 103.0f, 103.1f, 103.2f, + + 111.0f, 111.1f, 111.2f, + 112.0f, 112.1f, 112.2f, + 113.0f, 113.1f, 113.2f}), + Tensor(ET_I, {2}, std::vector{ + 0, 2}), + Tensor(ET_A, {}, std::vector{2}), + Tensor(ET, {2, 2, 2, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, + 3.0f, 3.1f, 3.2f, + + 11.0f, 11.1f, 11.2f, + 13.0f, 13.1f, 13.2f, + + + 101.0f, 101.1f, 101.2f, + 103.0f, 103.1f, 103.2f, + + 111.0f, 111.1f, 111.2f, + 113.0f, 113.1f, 113.2f}), + "gather_1d_indices_axis_2_4d_input"), + GatherParams( + Tensor(ET, {3, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f, 3.0f, 3.1f, 3.2f}), + Tensor(ET_I, {}, std::vector{0}), + Tensor(ET_A, {}, std::vector{1}), + Tensor(ET, {3}, std::vector{ + 1.0f, 2.0f, 3.0f}), + "gather_scalar_indices_axis_1_2d_input"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParamsFloatValue(), + generateParamsFloatValue(), + generateParamsFloatValue(), + generateParamsFloatValue(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_Gather_With_Hardcoded_Refs, ReferenceGatherTest, + testing::ValuesIn(generateCombinedParams()), ReferenceGatherTest::getTestCaseName); + +template +std::vector generateParamsV7() { + using T = typename element_type_traits::value_type; + using T_I = typename element_type_traits::value_type; + using T_A = typename element_type_traits::value_type; + std::vector params { + GatherParamsV7( + Tensor(ET, {3}, std::vector{ + 1, 2, 3}), + Tensor(ET_I, {2}, std::vector{ + 2, 0}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2}, std::vector{ + 3, 1}), + "gather_v7_1d"), + GatherParamsV7( + Tensor(ET, {3, 2}, std::vector{ + 10, 11, 20, 21, 30, 31}), + Tensor(ET_I, {2, 2}, std::vector{ + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2, 2, 2}, std::vector{ + 10, 11, 20, 21, 20, 21, 30, 31}), + "gather_v7_axis_0"), + GatherParamsV7( + Tensor(ET, {2, 3}, std::vector{ + 1, 2, 3, + 4, 5, 6}), + Tensor(ET_I, {2, 2, 2}, std::vector{ + 0, 1, + 1, 2, + + 2, 0, + 1, 2}), + Tensor(ET_A, {}, std::vector{1}), + 1, + Tensor(ET, {2, 2, 2}, std::vector{ + 1, 2, + 2, 3, + + 6, 4, + 5, 6}), + "gather_v7_data_int32_3d_indices_axis_1_batch_dims_1"), + GatherParamsV7( + Tensor(ET, {2, 5}, std::vector{ + 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10}), + Tensor(ET_I, {2, 3}, std::vector{ + 0, 0, 4, + 4, 0, 0}), + Tensor(ET_A, {}, std::vector{1}), + 1, + Tensor(ET, {2, 3}, std::vector{ + 1, 1, 5, + 10, 6, 6}), + "gather_v7_data_int32_2d_indices_axis_1_batch_dims_1"), + GatherParamsV7( + Tensor(ET, {2, 5}, std::vector{ + 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10}), + Tensor(ET_I, {2, 3}, std::vector{ + 0, 0, 4, + 4, 0, 0}), + Tensor(ET_A, {}, std::vector{1}), + -1, + Tensor(ET, {2, 3}, std::vector{ + 1, 1, 5, + 10, 6, 6}), + "gather_v7_data_int32_2d_indices_axis_1_negative_batch_dims"), + GatherParamsV7( + Tensor(ET, {2, 1, 5, 4}, std::vector{ + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + 17, 18, 19, 20, + + 21, 22, 23, 24, + 25, 26, 27, 28, + 29, 30, 31, 32, + 33, 34, 35, 36, + 37, 38, 39, 40}), + Tensor(ET_I, {2, 3}, std::vector{ + 1, 2, 4, + 4, 3, 2}), + Tensor(ET_A, {}, std::vector{2}), + 1, + Tensor(ET, {2, 1, 3, 4}, std::vector{ + 5, 6, 7, 8, + 9, 10, 11, 12, + 17, 18, 19, 20, + + 37, 38, 39, 40, + 33, 34, 35, 36, + 29, 30, 31, 32}), + "gather_v7_4d_data_axis_2_batch_dims_1_int32"), + }; + return params; +} + +template <> +std::vector generateParamsV7() { + std::vector params { + GatherParamsV7( + Tensor(element::boolean, {3, 2}, std::vector{ + 1, 1, 1, 0, 0, 1}), + Tensor(element::i32, {2, 2}, std::vector{ + 0, 1, 1, 2}), + Tensor(element::i64, {}, std::vector{0}), + 0, + Tensor(element::boolean, {2, 2, 2}, std::vector{ + 1, 1, 1, 0, 1, 0, 0, 1}), + "gather_v7_axis_0_bool"), + }; + return params; +} + +template +std::vector generateParamsFloatValueV7() { + using T = typename element_type_traits::value_type; + using T_I = typename element_type_traits::value_type; + using T_A = typename element_type_traits::value_type; + std::vector params { + GatherParamsV7( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 2, 3, 4}, std::vector{ + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2, 2, 3, 4, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_v7_4d_indices_axis_0_2d_input"), + GatherParamsV7( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 3, 4}, std::vector{ + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2, + + 0, 1, 1, 2, + 0, 1, 1, 2, + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2, 3, 4, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f, + + 1.0f, 1.1f, + 2.0f, 2.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_v7_3d_indices_axis_0_2d_input"), + GatherParamsV7( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 2}, std::vector{ + 0, 1, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2, 2, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_v7_2d_indices_axis_0_2d_input"), + GatherParamsV7( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + 3.0f, 3.1f}), + Tensor(ET_I, {2, 2}, std::vector{ + 0, -2, 1, 2}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2, 2, 2}, std::vector{ + 1.0f, 1.1f, + 2.0f, 2.1f, + + 2.0f, 2.1f, + 3.0f, 3.1f}), + "gather_v7_2d_negative_and_positive_indices_axis_0_2d_input"), + GatherParamsV7( + Tensor(ET, {3}, std::vector{ + 1.0f, 2.0f, 3.0f}), + Tensor(ET_I, {2}, std::vector{ + 1, 0}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2}, std::vector{ + 2.0f, 1.0f}), + "gather_v7_1d_indices_axis_0_1d_input"), + GatherParamsV7( + Tensor(ET, {3, 2}, std::vector{ + 1.0f, 1.1f, 2.0f, 2.1f, 3.0f, 3.1f}), + Tensor(ET_I, {}, std::vector{1}), + Tensor(ET_A, {}, std::vector{0}), + 0, + Tensor(ET, {2}, std::vector{ + 2.0f, 2.1f}), + "gather_v7_scalar_indices_axis_0_2d_input"), + GatherParamsV7( + Tensor(ET, {3, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, + 2.0f, 2.1f, 2.2f, + 3.0f, 3.1f, 3.2f}), + Tensor(ET_I, {1, 2}, std::vector{ + 0, 2}), + Tensor(ET_A, {}, std::vector{1}), + 0, + Tensor(ET, {3, 1, 2}, std::vector{ + 1.0f, 1.2f, + 2.0f, 2.2f, + 3.0f, 3.2f}), + "gather_v7_2d_indices_axis_1_2d_input"), + GatherParamsV7( + Tensor(ET, {2, 2, 3, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, + 2.0f, 2.1f, 2.2f, + 3.0f, 3.1f, 3.2f, + + 11.0f, 11.1f, 11.2f, + 12.0f, 12.1f, 12.2f, + 13.0f, 13.1f, 13.2f, + + + 101.0f, 101.1f, 101.2f, + 102.0f, 102.1f, 102.2f, + 103.0f, 103.1f, 103.2f, + + 111.0f, 111.1f, 111.2f, + 112.0f, 112.1f, 112.2f, + 113.0f, 113.1f, 113.2f}), + Tensor(ET_I, {2}, std::vector{ + 0, 2}), + Tensor(ET_A, {}, std::vector{2}), + 0, + Tensor(ET, {2, 2, 2, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, + 3.0f, 3.1f, 3.2f, + + 11.0f, 11.1f, 11.2f, + 13.0f, 13.1f, 13.2f, + + + 101.0f, 101.1f, 101.2f, + 103.0f, 103.1f, 103.2f, + + 111.0f, 111.1f, 111.2f, + 113.0f, 113.1f, 113.2f}), + "gather_v7_1d_indices_axis_2_4d_input"), + GatherParamsV7( + Tensor(ET, {3, 3}, std::vector{ + 1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f, 3.0f, 3.1f, 3.2f}), + Tensor(ET_I, {}, std::vector{0}), + Tensor(ET_A, {}, std::vector{1}), + 0, + Tensor(ET, {3}, std::vector{ + 1.0f, 2.0f, 3.0f}), + "gather_v7_scalar_indices_axis_1_2d_input"), + GatherParamsV7( + Tensor(ET, {2, 5, 2}, std::vector{ + 1.0f, 2.0f, + 3.0f, 4.0f, + 5.0f, 6.0f, + 7.0f, 8.0f, + 9.0f, 10.0f, + + 11.0f, 12.0f, + 13.0f, 14.0f, + 15.0f, 16.0f, + 17.0f, 18.0f, + 19.0f, 20.0f}), + Tensor(ET_I, {2, 2, 3}, std::vector{ + 0, 0, 4, + 4, 0, 0, + + 1, 2, 4, + 4, 3, 2}), + Tensor(ET_A, {}, std::vector{1}), + 1, + Tensor(ET, {2, 2, 3, 2}, std::vector{ + 1.0f, 2.0f, + 1.0f, 2.0f, + 9.0f, 10.0f, + + 9.0f, 10.0f, + 1.0f, 2.0f, + 1.0f, 2.0f, + + + 13.0f, 14.0f, + 15.0f, 16.0f, + 19.0f, 20.0f, + + 19.0f, 20.0f, + 17.0f, 18.0f, + 15.0f, 16.0f}), + "gather_v7_3d_indices_axis_1_batch_dims_1"), + }; + return params; +} + +std::vector generateCombinedParamsV7() { + const std::vector> generatedParams { + generateParamsV7(), + generateParamsV7(), + generateParamsV7(), + generateParamsV7(), + generateParamsV7(), + generateParamsV7(), + generateParamsV7(), + generateParamsV7(), + generateParamsV7(), + generateParamsFloatValueV7(), + generateParamsFloatValueV7(), + generateParamsFloatValueV7(), + generateParamsFloatValueV7(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_Gather_With_Hardcoded_Refs, ReferenceGatherTestV7, + testing::ValuesIn(generateCombinedParamsV7()), ReferenceGatherTestV7::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/gather_nd.cpp b/docs/template_plugin/tests/functional/op_reference/gather_nd.cpp index 31b54247150354..d27d3bebf7f6a3 100644 --- a/docs/template_plugin/tests/functional/op_reference/gather_nd.cpp +++ b/docs/template_plugin/tests/functional/op_reference/gather_nd.cpp @@ -25,7 +25,7 @@ struct GatherNDParams { std::string testcaseName; }; -class ReferenceGatherNDTest : public testing::TestWithParam, public CommonReferenceTest { +class ReferenceGatherND5Test : public testing::TestWithParam, public CommonReferenceTest { public: void SetUp() override { auto params = GetParam(); @@ -59,18 +59,18 @@ class ReferenceGatherNDTest : public testing::TestWithParam, pub PartialShape{params.dataTensor.shape}); const auto indices = std::make_shared(params.indicesTensor.type, PartialShape{params.indicesTensor.shape}); - std::shared_ptr gatherElement; + std::shared_ptr gatherND; if (params.batchDims == 0) { - gatherElement = std::make_shared(data, indices); + gatherND = std::make_shared(data, indices); } else { - gatherElement = std::make_shared(data, indices, params.batchDims); + gatherND = std::make_shared(data, indices, params.batchDims); } - function = std::make_shared(NodeVector {gatherElement}, ParameterVector {data, indices}); + function = std::make_shared(NodeVector {gatherND}, ParameterVector {data, indices}); return function; } }; -TEST_P(ReferenceGatherNDTest, CompareWithRefs) { +TEST_P(ReferenceGatherND5Test, CompareWithRefs) { Exec(); } @@ -203,6 +203,207 @@ std::vector generateCombinedParams() { return combinedParams; } -INSTANTIATE_TEST_SUITE_P(smoke_GatherND_With_Hardcoded_Refs, ReferenceGatherNDTest, - testing::ValuesIn(generateCombinedParams()), ReferenceGatherNDTest::getTestCaseName); -} // namespace \ No newline at end of file +INSTANTIATE_TEST_SUITE_P(smoke_GatherND_With_Hardcoded_Refs, ReferenceGatherND5Test, + testing::ValuesIn(generateCombinedParams()), ReferenceGatherND5Test::getTestCaseName); + + +class ReferenceGatherND8Test : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data, params.indicesTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_aType=" << param.indicesTensor.type; + result << "_aShape=" << param.indicesTensor.shape; + result << "_bDims=" << param.batchDims; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const GatherNDParams& params) { + std::shared_ptr function; + const auto data = std::make_shared(params.dataTensor.type, + PartialShape{params.dataTensor.shape}); + const auto indices = std::make_shared(params.indicesTensor.type, + PartialShape{params.indicesTensor.shape}); + std::shared_ptr gatherND; + if (params.batchDims == 0) { + gatherND = std::make_shared(data, indices); + } else { + gatherND = std::make_shared(data, indices, params.batchDims); + } + function = std::make_shared(NodeVector {gatherND}, ParameterVector {data, indices}); + return function; + } +}; + +TEST_P(ReferenceGatherND8Test, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams_v8() { + using T = typename element_type_traits::value_type; + std::vector params { + GatherNDParams( + Tensor(IN_ET, {3, 3}, std::vector{10, 11, 12, 13, 14, 15, 16, 17, 18}), + Tensor(element::i32, {2}, std::vector{1, 2}), + 0, + Tensor(IN_ET, {}, std::vector{15}), + "gather_nd_8_single_indices"), + GatherNDParams( + Tensor(IN_ET, {2, 2}, std::vector{10, 11, 12, 13}), + Tensor(element::i32, {2, 2}, std::vector{0, 0, 1, 1}), + 0, + Tensor(IN_ET, {2}, std::vector{10, 13}), + "gather_nd_8_scalar_from_2d"), + GatherNDParams( + Tensor(IN_ET, {2, 2}, std::vector{10, 11, 12, 13}), + Tensor(element::i32, {2, 1}, std::vector{1, 0}), + 0, + Tensor(IN_ET, {2, 2}, std::vector{12, 13, 10, 11}), + "gather_nd_8_1d_from_2d"), + GatherNDParams( + Tensor(IN_ET, {2, 2, 2}, std::vector{10, 11, 12, 13, 20, 21, 22, 23}), + Tensor(element::i32, {2, 3}, std::vector{0, 0, 1, 1, 0, 1}), + 0, + Tensor(IN_ET, {2}, std::vector{11, 21}), + "gather_nd_8_scalar_from_3d"), + GatherNDParams( + Tensor(IN_ET, {2, 2, 2}, std::vector{10, 11, 12, 13, 20, 21, 22, 23}), + Tensor(element::i32, {2, 2}, std::vector{0, 1, 1, 0}), + 0, + Tensor(IN_ET, {2, 2}, std::vector{12, 13, 20, 21}), + "gather_nd_8_1d_from_3d"), + GatherNDParams( + Tensor(IN_ET, {2, 2, 2}, std::vector{10, 11, 12, 13, 20, 21, 22, 23}), + Tensor(element::i32, {1, 1}, std::vector{1}), + 0, + Tensor(IN_ET, {1, 2, 2}, std::vector{20, 21, 22, 23}), + "gather_nd_8_2d_from_3d"), + GatherNDParams( + Tensor(IN_ET, {2, 2}, std::vector{10, 11, 12, 13}), + Tensor(element::i32, {2, 1, 2}, std::vector{0, 0, 0, 1}), + 0, + Tensor(IN_ET, {2, 1}, std::vector{10, 11}), + "gather_nd_8_batch_scalar_from_2d"), + GatherNDParams( + Tensor(IN_ET, {2, 2}, std::vector{10, 11, 12, 13}), + Tensor(element::i32, {2, 1, 1}, std::vector{1, 0}), + 0, + Tensor(IN_ET, {2, 1, 2}, std::vector{12, 13, 10, 11}), + "gather_nd_8_batch_1d_from_2d"), + GatherNDParams( + Tensor(IN_ET, {2, 2, 2}, std::vector{10, 11, 12, 13, 20, 21, 22, 23}), + Tensor(element::i32, {2, 2, 3}, std::vector{0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0}), + 0, + Tensor(IN_ET, {2, 2}, std::vector{11, 21, 13, 22}), + "gather_nd_8_batch_scalar_from_3d"), + GatherNDParams( + Tensor(IN_ET, {2, 2, 2}, std::vector{10, 11, 12, 13, 20, 21, 22, 23}), + Tensor(element::i32, {2, 2, 2}, std::vector{0, 1, 1, 0, 0, 0, 1, 1}), + 0, + Tensor(IN_ET, {2, 2, 2}, std::vector{12, 13, 20, 21, 10, 11, 22, 23}), + "gather_nd_8_batch_1d_from_3d"), + GatherNDParams( + Tensor(IN_ET, {2, 2, 2}, std::vector{10, 11, 12, 13, 20, 21, 22, 23}), + Tensor(element::i32, {2, 2, 2}, std::vector{0, -1, -1, 0, 0, 0, 1, 1}), + 0, + Tensor(IN_ET, {2, 2, 2}, std::vector{12, 13, 20, 21, 10, 11, 22, 23}), + "gather_nd_8_batch_1d_from_3d_negative"), + GatherNDParams( + Tensor(IN_ET, {2, 2, 2}, std::vector{10, 11, 12, 13, 20, 21, 22, 23}), + Tensor(element::i32, {2, 1, 1}, std::vector{1, 0}), + 0, + Tensor(IN_ET, {2, 1, 2, 2}, std::vector{20, 21, 22, 23, 10, 11, 12, 13}), + "gather_nd_8_batch_2d_from_3d"), + GatherNDParams( + Tensor(IN_ET, {2, 3, 4}, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}), + Tensor(element::i32, {2, 1}, std::vector{1, 0}), + 1, + Tensor(IN_ET, {2, 4}, std::vector{5, 6, 7, 8, 13, 14, 15, 16}), + "gather_nd_8_batch_dims1"), + GatherNDParams( + Tensor(IN_ET, {2, 3, 4, 2}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48}), + Tensor(element::i32, {2, 3, 3, 2}, std::vector{ + 1, 0, 3, 1, 2, 1, 0, 1, 1, 1, 2, 0, 3, 0, 3, 1, 2, 1, + 2, 0, 1, 1, 3, 1, 1, 1, 2, 0, 2, 0, 0, 0, 3, 1, 3, 1}), + 2, + Tensor(IN_ET, {2, 3, 3}, std::vector{ + 3, 8, 6, 10, 12, 13, 23, 24, 22, 29, 28, 32, 36, 37, 37, 41, 48, 48}), + "gather_8_nd_batch_dims2"), + GatherNDParams( + Tensor(IN_ET, {2, 3, 4}, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}), + Tensor(element::i32, {2, 3, 1, 1}, std::vector{1, 0, 2, 0, 2, 2}), + 2, + Tensor(IN_ET, {2, 3, 1}, std::vector{2, 5, 11, 13, 19, 23}), + "gather_8_nd_batch_dims2_lead_dims"), + GatherNDParams( + Tensor(IN_ET, {2, 3, 4, 5}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120}), + Tensor(element::i32, {2, 3, 2, 1}, std::vector{ + 1, 0, 2, 0, 2, 0, 1, 0, 2, 0, 2, 0}), + 2, + Tensor(IN_ET, {2, 3, 2, 5}, std::vector{ + 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 31, 32, 33, 34, 35, 21, 22, 23, + 24, 25, 51, 52, 53, 54, 55, 41, 42, 43, 44, 45, 66, 67, 68, 69, + 70, 61, 62, 63, 64, 65, 91, 92, 93, 94, 95, 81, 82, 83, 84, 85, + 111, 112, 113, 114, 115, 101, 102, 103, 104, 105}), + "gather_8_nd_batch_dims2_non_scalar_slices"), + }; + return params; +} + +std::vector generateCombinedParams_v8() { + const std::vector> generatedParams { + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + generateParams_v8(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_GatherND_With_Hardcoded_Refs, ReferenceGatherND8Test, + testing::ValuesIn(generateCombinedParams_v8()), ReferenceGatherND8Test::getTestCaseName); +} // namespace diff --git a/docs/template_plugin/tests/functional/op_reference/gru_cell.cpp b/docs/template_plugin/tests/functional/op_reference/gru_cell.cpp new file mode 100644 index 00000000000000..f520ea0f77e7a2 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/gru_cell.cpp @@ -0,0 +1,294 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/gru_cell.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct GRUCellParams { + GRUCellParams( + const int32_t batchSize, const int32_t inputSize, const int32_t hiddenSize, const int32_t gatesCount, const bool linearBeforeReset, + const Tensor& X, const Tensor& H_t, const Tensor& W, const Tensor& R, const Tensor& B, + const Tensor& Ho, const std::string& testcaseName = "") : + batchSize(batchSize), inputSize(inputSize), hiddenSize(hiddenSize), gatesCount(gatesCount), linearBeforeReset(linearBeforeReset), + X(X), H_t(H_t), W(W), R(R), B(B), Ho(Ho), testcaseName(testcaseName) {} + + int32_t batchSize; + int32_t inputSize; + int32_t hiddenSize; + int32_t gatesCount; + bool linearBeforeReset; + Tensor X; + Tensor H_t; + Tensor W; + Tensor R; + Tensor B; + Tensor Ho; + std::string testcaseName; +}; + +class ReferenceGRUCellTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.X.data, params.H_t.data, params.W.data, params.R.data, params.B.data}; + refOutData = {params.Ho.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "bSize=" << param.batchSize; + result << "_iSize=" << param.inputSize; + result << "_hSize=" << param.hiddenSize; + result << "_gCount=" << param.gatesCount; + result << "_lbReset=" << param.linearBeforeReset; + result << "_xType=" << param.X.type; + result << "_xShape=" << param.X.shape; + result << "_htType=" << param.H_t.type; + result << "_htShape=" << param.H_t.shape; + result << "_wType=" << param.W.type; + result << "_wShape=" << param.W.shape; + result << "_rType=" << param.R.type; + result << "_rShape=" << param.R.shape; + result << "_hoType=" << param.Ho.type; + if (param.testcaseName != "") { + result << "_hoShape=" << param.Ho.shape; + result << "_=" << param.testcaseName; + } else { + result << "_hoShape=" << param.Ho.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const GRUCellParams& params) { + float clip = 2.88f; + + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto gru_cell = std::make_shared(X, + H_t, + W, + R, + B, + params.hiddenSize, + std::vector{"sigmoid", "tanh"}, + std::vector{}, + std::vector{}, + clip, + params.linearBeforeReset); + + auto function = std::make_shared(NodeVector{gru_cell}, ParameterVector{X, H_t, W, R, B}); + return function; + } +}; + +// Hard Sigmoid activation function is unsupprted with v3::GRUCell +class ReferenceGRUCellTestHardsigmoidActivationFunction : public ReferenceGRUCellTest { +public: + void SetUp() override { + threshold = 1e-1f; + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.X.data, params.H_t.data, params.W.data, params.R.data, params.B.data}; + refOutData = {params.Ho.data}; + } + +private: + static std::shared_ptr CreateFunction(const GRUCellParams& params) { + float clip = 2.88f; + + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto gru_cell = std::make_shared(X, + H_t, + W, + R, + B, + params.hiddenSize, + std::vector{"hardsigmoid", "hardsigmoid"}, + std::vector{1.8345f, 1.8345f}, + std::vector{3.05f, 3.05f}, + clip, + params.linearBeforeReset); + + auto function = std::make_shared(NodeVector{gru_cell}, ParameterVector{X, H_t, W, R, B}); + return function; + } +}; + +TEST_P(ReferenceGRUCellTest, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceGRUCellTestHardsigmoidActivationFunction, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + GRUCellParams( + 2, 3, 3, 3, false, + Tensor(ET, {2, 3}, std::vector{ + 0.52421564f, 0.78845507f, 0.9372873f, 0.59783894f, 0.18278378f, 0.2084126f}), + Tensor(ET, {2, 3}, std::vector{ + 0.45738035f, 0.996877f, 0.82882977f, 0.47492632f, 0.88471466f, 0.57833236f}), + Tensor(ET, {3 * 3, 3}, std::vector{ + 0.5815369f, 0.16559383f, 0.08464007f, 0.843122f, 0.73968244f, 0.11359601f, + 0.8295078f, 0.9240567f, 0.10007995f, 0.20573162f, 0.09002485f, 0.2839569f, + 0.3096991f, 0.5638341f, 0.5787327f, 0.84552664f, 0.16263747f, 0.7243242f, + 0.8049057f, 0.43966424f, 0.46294412f, 0.9833361f, 0.31369713f, 0.1719934f, + 0.4937093f, 0.6353004f, 0.77982515f}), + Tensor(ET, {3 * 3, 3}, std::vector{ + 0.16510165f, 0.52435565f, 0.2788478f, 0.99427545f, 0.1623331f, 0.01389796f, + 0.99669236f, 0.53901845f, 0.8737506f, 0.9254788f, 0.21172932f, 0.11634306f, + 0.40111724f, 0.37497616f, 0.2903471f, 0.6796794f, 0.65131867f, 0.78163475f, + 0.12058706f, 0.45591718f, 0.791677f, 0.76497287f, 0.9895242f, 0.7845312f, + 0.51267904f, 0.49030215f, 0.08498167f}), + Tensor(ET, {3 * 3}, std::vector{ + 0.8286678f + 0.9175602f, + 0.9153158f + 0.14958014f, + 0.9581612f + 0.49230585f, + 0.6639213f + 0.63162816f, + 0.84239805f + 0.4161903f, + 0.5282445f + 0.22148274f, + 0.14153397f + 0.50496656f, + 0.22404431f + 0.34798595f, + 0.6549655f + 0.6699164f}), + Tensor(ET, {2, 3}, std::vector{ + 0.48588726f, 0.99670005f, 0.83759373f, 0.5023099f, 0.89410484f, 0.60011315f}), + "gru_cell_bias_clip"), + GRUCellParams( + 2, 3, 3, 3, true, + Tensor(ET, {2, 3}, std::vector{ + 0.12249453f, 0.6127907f, 0.5001741f, 0.5124603f, 0.04329684f, 0.023834f}), + Tensor(ET, {2, 3}, std::vector{ + 0.8598948f, 0.41189128f, 0.72824323f, 0.53940123f, 0.31485787f, 0.04053852f}), + Tensor(ET, {3 * 3, 3}, std::vector{ + 0.72259396f, 0.11561195f, 0.9457856f, 0.19037509f, 0.6964006f, 0.33459795f, + 0.5468904f, 0.85646594f, 0.5101311f, 0.9712257f, 0.3687071f, 0.60280246f, + 0.56943774f, 0.7475505f, 0.2490578f, 0.86977345f, 0.85542053f, 0.29660386f, + 0.49717373f, 0.7473479f, 0.53454477f, 0.15974349f, 0.5804805f, 0.14303213f, + 0.07514781f, 0.5865731f, 0.76409274f}), + Tensor(ET, {3 * 3, 3}, std::vector{ + 0.91382647f, 0.41527033f, 0.28040004f, 0.23601337f, 0.04471736f, 0.03888785f, + 0.06308217f, 0.44844428f, 0.29384327f, 0.49037653f, 0.50421673f, 0.7366393f, + 0.63143945f, 0.00277612f, 0.37198433f, 0.06966069f, 0.4613444f, 0.10999731f, + 0.78273284f, 0.21453214f, 0.10751773f, 0.18332677f, 0.1326976f, 0.9998985f, + 0.19263928f, 0.10979804f, 0.52575564f}), + Tensor(ET, {(3 + 1) * 3}, std::vector{ + 0.61395123f, // 0.09875853f + 0.5151927f, + 1.08667738f, // 0.37801138f + 0.708666f, + 1.32600244f, // 0.7729636f + 0.55303884f, + 0.81917698f, // 0.78493553f + 0.03424145f, + 1.37736335f, // 0.5662702f + 0.81109315f, + 0.42931147f, // 0.12406381f + 0.30524766f, + 0.66729516f, + 0.7752771f, + 0.78819966f, + 0.6606634f, + 0.99040645f, + 0.21112025f}), + Tensor(ET, {2, 3}, std::vector{ + 0.8709214f, 0.48411977f, 0.74495184f, 0.6074972f, 0.44572943f, 0.1467715f}), + "gru_cell_linear_before_reset"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParamsHardsigmoidActivationFunction() { + using T = typename element_type_traits::value_type; + std::vector params { + GRUCellParams( + 2, 3, 3, 3, true, + Tensor(ET, {2, 3}, std::vector{ + 0.12249453f, 0.6127907f, 0.5001741f, 0.5124603f, 0.04329684f, 0.023834f}), + Tensor(ET, {2, 3}, std::vector{ + 0.8598948f, 0.41189128f, 0.72824323f, 0.53940123f, 0.31485787f, 0.04053852f}), + Tensor(ET, {3 * 3, 3}, std::vector{ + 0.72259396f, 0.11561195f, 0.9457856f, 0.19037509f, 0.6964006f, 0.33459795f, + 0.5468904f, 0.85646594f, 0.5101311f, 0.9712257f, 0.3687071f, 0.60280246f, + 0.56943774f, 0.7475505f, 0.2490578f, 0.86977345f, 0.85542053f, 0.29660386f, + 0.49717373f, 0.7473479f, 0.53454477f, 0.15974349f, 0.5804805f, 0.14303213f, + 0.07514781f, 0.5865731f, 0.76409274f}), + Tensor(ET, {3 * 3, 3}, std::vector{ + 0.91382647f, 0.41527033f, 0.28040004f, 0.23601337f, 0.04471736f, 0.03888785f, + 0.06308217f, 0.44844428f, 0.29384327f, 0.49037653f, 0.50421673f, 0.7366393f, + 0.63143945f, 0.00277612f, 0.37198433f, 0.06966069f, 0.4613444f, 0.10999731f, + 0.78273284f, 0.21453214f, 0.10751773f, 0.18332677f, 0.1326976f, 0.9998985f, + 0.19263928f, 0.10979804f, 0.52575564f}), + Tensor(ET, {(3 + 1) * 3}, std::vector{ + 0.09875853f + 0.5151927f, + 0.37801138f + 0.708666f, + 0.7729636f + 0.55303884f, + 0.78493553f + 0.03424145f, + 0.5662702f + 0.81109315f, + 0.12406381f + 0.30524766f, + 0.66729516f, + 0.7752771f, + 0.78819966f, + 0.6606634f, + 0.99040645f, + 0.21112025f}), + Tensor(ET, {2, 3}, std::vector{ + 0.8598948f, 0.41189128f, 0.72824323f, 0.53940123f, 0.31485787f, 0.04053852f}), + "gru_cell_hardsigmoid_activation_function"), + }; + return params; +} + +std::vector generateCombinedParamsHardsigmoidActivationFunction() { + const std::vector> generatedParams { + generateParamsHardsigmoidActivationFunction(), + generateParamsHardsigmoidActivationFunction(), + generateParamsHardsigmoidActivationFunction(), + generateParamsHardsigmoidActivationFunction(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_GRUCell_With_Hardcoded_Refs, ReferenceGRUCellTest, + testing::ValuesIn(generateCombinedParams()), ReferenceGRUCellTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_GRUCell_With_Hardcoded_Refs, ReferenceGRUCellTestHardsigmoidActivationFunction, + testing::ValuesIn(generateCombinedParamsHardsigmoidActivationFunction()), ReferenceGRUCellTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/lstm_cell.cpp b/docs/template_plugin/tests/functional/op_reference/lstm_cell.cpp new file mode 100644 index 00000000000000..7279cee6b66cae --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/lstm_cell.cpp @@ -0,0 +1,379 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/lstm_cell.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct LSTMCellParams { + LSTMCellParams( + int32_t batchSize, int32_t inputSize, int32_t hiddenSize, int32_t gatesCount, + const Tensor& X, const Tensor& W, const Tensor& R, const Tensor& H_t, const Tensor& C_t, const Tensor& B, + const Tensor& Ho, const Tensor& Co, const std::string& testcaseName = "") : + batchSize(batchSize), inputSize(inputSize), hiddenSize(hiddenSize), gatesCount(gatesCount), + X(X), W(W), R(R), H_t(H_t), C_t(C_t), B(B), Ho(Ho), Co(Co), testcaseName(testcaseName) {} + + int32_t batchSize; + int32_t inputSize; + int32_t hiddenSize; + int32_t gatesCount; + Tensor X; + Tensor W; + Tensor R; + Tensor H_t; + Tensor C_t; + Tensor B; + Tensor Ho; + Tensor Co; + std::string testcaseName; +}; + +class ReferenceLSTMCellTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.X.data, params.H_t.data, params.C_t.data, params.W.data, params.R.data, params.B.data}; + refOutData = {params.Ho.data, params.Co.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "bSize=" << param.batchSize; + result << "_iSize=" << param.inputSize; + result << "_hSize=" << param.hiddenSize; + result << "_gCount=" << param.gatesCount; + result << "_xType=" << param.X.type; + result << "_xShape=" << param.X.shape; + result << "_wType=" << param.W.type; + result << "_wShape=" << param.W.shape; + result << "_rType=" << param.R.type; + result << "_rShape=" << param.R.shape; + result << "_htType=" << param.H_t.type; + result << "_htShape=" << param.H_t.shape; + result << "_ctType=" << param.C_t.type; + result << "_ctShape=" << param.C_t.shape; + result << "_hoType=" << param.Ho.type; + result << "_hoShape=" << param.Ho.shape; + result << "_coType=" << param.Co.type; + if (param.testcaseName != "") { + result << "_coShape=" << param.Co.shape; + result << "_=" << param.testcaseName; + } else { + result << "_coShape=" << param.Co.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const LSTMCellParams& params) { + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto C_t = std::make_shared(params.C_t.type, params.C_t.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto lstm_cell = + std::make_shared(X, + H_t, + C_t, + op::util::convert_lstm_node_format(W, op::util::LSTMWeightsFormat::IOFC), + op::util::convert_lstm_node_format(R, op::util::LSTMWeightsFormat::IOFC), + op::util::convert_lstm_node_format(B, op::util::LSTMWeightsFormat::IOFC), + params.hiddenSize); + + auto function = std::make_shared(lstm_cell->outputs(), ParameterVector{X, H_t, C_t, W, R, B}); + return function; + } +}; + +class ReferenceLSTMCellTestBiasDefaultAttrs : public ReferenceLSTMCellTest { +public: + void SetUp() override { + threshold = 1e-1f; + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.X.data, params.H_t.data, params.C_t.data, params.W.data, params.R.data, params.B.data}; + refOutData = {params.Ho.data, params.Co.data}; + } + +private: + static std::shared_ptr CreateFunction(const LSTMCellParams& params) { + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto C_t = std::make_shared(params.C_t.type, params.C_t.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto lstm_cell = + std::make_shared(X, + H_t, + C_t, + op::util::convert_lstm_node_format(W, op::util::LSTMWeightsFormat::IOFC), + op::util::convert_lstm_node_format(R, op::util::LSTMWeightsFormat::IOFC), + op::util::convert_lstm_node_format(B, op::util::LSTMWeightsFormat::IOFC), + params.hiddenSize); + + auto function = std::make_shared(lstm_cell->outputs(), ParameterVector{X, H_t, C_t, W, R, B}); + return function; + } +}; + +class ReferenceLSTMCellTestBiasClip : public ReferenceLSTMCellTest { +public: + void SetUp() override { + threshold = 1e-1f; + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.X.data, params.H_t.data, params.C_t.data, params.W.data, params.R.data, params.B.data}; + refOutData = {params.Ho.data, params.Co.data}; + } + +private: + static std::shared_ptr CreateFunction(const LSTMCellParams& params) { + const float clip_threshold = 3.5f; + + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto C_t = std::make_shared(params.C_t.type, params.C_t.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto lstm_cell = + std::make_shared(X, + H_t, + C_t, + W, + R, + B, + params.hiddenSize, + std::vector{"sigmoid", "tanh", "tanh"}, + std::vector{}, + std::vector{}, + clip_threshold); + + auto function = std::make_shared(lstm_cell->outputs(), ParameterVector{X, H_t, C_t, W, R, B}); + return function; + } +}; + +TEST_P(ReferenceLSTMCellTest, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceLSTMCellTestBiasDefaultAttrs, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceLSTMCellTestBiasClip, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + LSTMCellParams( + 2, 3, 3, 4, + Tensor(ET, {2, 3}, std::vector{ + 0.81342685f, 0.84108883f, 0.8152282f, 0.46893653f, 0.0901856f, 0.37088776f}), + Tensor(ET, {4 * 3, 3}, std::vector{ + 3.3330739e-01f, 3.6229487e-04f, 4.6773660e-01f, 4.3046016e-01f, 7.3950343e-02f, 3.8063636e-01f, + 9.6921772e-01f, 9.6897459e-01f, 6.2964785e-01f, 3.1134409e-01f, 8.4709978e-01f, 9.4928098e-01f, + 6.1676943e-01f, 6.6020679e-01f, 1.9072217e-01f, 8.8032126e-02f, 4.0472135e-01f, 6.8342745e-01f, + 8.3432144e-01f, 4.4928190e-01f, 7.9524308e-01f, 5.3966165e-01f, 8.5936421e-01f, 8.3136767e-01f, + 5.5125546e-02f, 4.7791195e-01f, 3.5788772e-01f, 6.7507404e-01f, 2.1716513e-01f, 2.7473119e-01f, + 3.3999152e-02f, 9.6835363e-01f, 3.7581277e-01f, 2.4026000e-01f, 6.7418844e-01f, 3.4199652e-01f}), + Tensor(ET, {4 * 3, 3}, std::vector{ + 0.0987983f, 0.52032113f, 0.5848073f, 0.5356095f, 0.74497133f, 0.73260087f, + 0.1700787f, 0.45684233f, 0.1495722f, 0.42734373f, 0.4433832f, 0.25906256f, + 0.03854987f, 0.47480518f, 0.37215272f, 0.99890584f, 0.74019486f, 0.3518967f, + 0.6881257f, 0.8170279f, 0.54088944f, 0.81225616f, 0.14619833f, 0.42941234f, + 0.86843914f, 0.45967972f, 0.6237719f, 0.11074839f, 0.6029616f, 0.3149305f, + 0.46504205f, 0.5843412f, 0.8733427f, 0.7687243f, 0.07074859f, 0.39188156f}), + Tensor(ET, {2, 3}, std::vector{ + 0.77956f, 0.5331557f, 0.04297554f, 0.7962175f, 0.7635707f, 0.11989366f}), + Tensor(ET, {2, 3}, std::vector{ + 0.8488452f, 0.18851636f, 0.5020695f, 0.29716516f, 0.06740791f, 0.45384037f}), + Tensor(ET, {4 * 3}, std::vector(4 * 3, 0.f)), + Tensor(ET, {2, 3}, std::vector{0.81457126f, 0.61109227f, 0.769522f, 0.52239674f, 0.4324641f, 0.63183f}), + Tensor(ET, {2, 3}, std::vector{1.4444952f, 0.9635685f, 1.2875274f, 0.8053419f, 0.7184521f, 0.95803297f}), + "lstm_cell_zero_bias_default_attrs"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParamsBiasDefaultAttrs() { + using T = typename element_type_traits::value_type; + std::vector params { + LSTMCellParams( + 2, 3, 3, 4, + Tensor(ET, {2, 3}, std::vector{ + 0.81342685f, 0.84108883f, 0.8152282f, 0.46893653f, 0.0901856f, 0.37088776f}), + Tensor(ET, {4 * 3, 3}, std::vector{ + 3.3330739e-01f, 3.6229487e-04f, 4.6773660e-01f, 4.3046016e-01f, 7.3950343e-02f, 3.8063636e-01f, + 9.6921772e-01f, 9.6897459e-01f, 6.2964785e-01f, 3.1134409e-01f, 8.4709978e-01f, 9.4928098e-01f, + 6.1676943e-01f, 6.6020679e-01f, 1.9072217e-01f, 8.8032126e-02f, 4.0472135e-01f, 6.8342745e-01f, + 8.3432144e-01f, 4.4928190e-01f, 7.9524308e-01f, 5.3966165e-01f, 8.5936421e-01f, 8.3136767e-01f, + 5.5125546e-02f, 4.7791195e-01f, 3.5788772e-01f, 6.7507404e-01f, 2.1716513e-01f, 2.7473119e-01f, + 3.3999152e-02f, 9.6835363e-01f, 3.7581277e-01f, 2.4026000e-01f, 6.7418844e-01f, 3.4199652e-01f}), + Tensor(ET, {4 * 3, 3}, std::vector{ + 0.0987983f, 0.52032113f, 0.5848073f, 0.5356095f, 0.74497133f, 0.73260087f, + 0.1700787f, 0.45684233f, 0.1495722f, 0.42734373f, 0.4433832f, 0.25906256f, + 0.03854987f, 0.47480518f, 0.37215272f, 0.99890584f, 0.74019486f, 0.3518967f, + 0.6881257f, 0.8170279f, 0.54088944f, 0.81225616f, 0.14619833f, 0.42941234f, + 0.86843914f, 0.45967972f, 0.6237719f, 0.11074839f, 0.6029616f, 0.3149305f, + 0.46504205f, 0.5843412f, 0.8733427f, 0.7687243f, 0.07074859f, 0.39188156f}), + Tensor(ET, {2, 3}, std::vector{ + 0.77956f, 0.5331557f, 0.04297554f, 0.7962175f, 0.7635707f, 0.11989366f}), + Tensor(ET, {2, 3}, std::vector{ + 0.8488452f, 0.18851636f, 0.5020695f, 0.29716516f, 0.06740791f, 0.45384037f}), + Tensor(ET, {4 * 3}, std::vector{1.07393714f, + 1.15248052f, + 1.16671345f, + 0.21450312f, + 1.2380678f, + 1.51688835f, + 0.46718366f, + 0.91810346f, + 1.1274234f, + 0.51022074f, + 1.11389844f, + 0.74174305f}), + Tensor(ET, {2, 3}, std::vector{0.81014400720596313, + 0.76665538549423218, + 0.82509011030197144, + 0.6479143500328064, + 0.66586339473724365, + 0.74838578701019287}), + Tensor(ET, {2, 3}, std::vector{1.6800162792205811, + 1.1150213479995728, + 1.4578367471694946, + 1.0649888515472412, + 0.93761754035949707, + 1.3659683465957642}), + "lstm_cell_bias_default_attrs"), + }; + return params; +} + +std::vector generateCombinedParamsBiasDefaultAttrs() { + const std::vector> generatedParams { + generateParamsBiasDefaultAttrs(), + generateParamsBiasDefaultAttrs(), + generateParamsBiasDefaultAttrs(), + generateParamsBiasDefaultAttrs(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParamsBiasClip() { + using T = typename element_type_traits::value_type; + std::vector params { + LSTMCellParams( + 2, 3, 3, 4, + Tensor(ET, {2, 3}, std::vector{ + 0.81342685f, 0.84108883f, 0.8152282f, 0.46893653f, 0.0901856f, 0.37088776f}), + Tensor(ET, {4 * 3, 3}, std::vector{ + 3.3330739e-01f, 3.6229487e-04f, 4.6773660e-01f, 4.3046016e-01f, 7.3950343e-02f, 3.8063636e-01f, + 9.6921772e-01f, 9.6897459e-01f, 6.2964785e-01f, 3.1134409e-01f, 8.4709978e-01f, 9.4928098e-01f, + 6.1676943e-01f, 6.6020679e-01f, 1.9072217e-01f, 8.8032126e-02f, 4.0472135e-01f, 6.8342745e-01f, + 8.3432144e-01f, 4.4928190e-01f, 7.9524308e-01f, 5.3966165e-01f, 8.5936421e-01f, 8.3136767e-01f, + 5.5125546e-02f, 4.7791195e-01f, 3.5788772e-01f, 6.7507404e-01f, 2.1716513e-01f, 2.7473119e-01f, + 3.3999152e-02f, 9.6835363e-01f, 3.7581277e-01f, 2.4026000e-01f, 6.7418844e-01f, 3.4199652e-01f}), + Tensor(ET, {4 * 3, 3}, std::vector{ + 0.0987983f, 0.52032113f, 0.5848073f, 0.5356095f, 0.74497133f, 0.73260087f, + 0.1700787f, 0.45684233f, 0.1495722f, 0.42734373f, 0.4433832f, 0.25906256f, + 0.03854987f, 0.47480518f, 0.37215272f, 0.99890584f, 0.74019486f, 0.3518967f, + 0.6881257f, 0.8170279f, 0.54088944f, 0.81225616f, 0.14619833f, 0.42941234f, + 0.86843914f, 0.45967972f, 0.6237719f, 0.11074839f, 0.6029616f, 0.3149305f, + 0.46504205f, 0.5843412f, 0.8733427f, 0.7687243f, 0.07074859f, 0.39188156f}), + Tensor(ET, {2, 3}, std::vector{ + 0.77956f, 0.5331557f, 0.04297554f, 0.7962175f, 0.7635707f, 0.11989366f}), + Tensor(ET, {2, 3}, std::vector{ + 0.8488452f, 0.18851636f, 0.5020695f, 0.29716516f, 0.06740791f, 0.45384037f}), + Tensor(ET, {4 * 3}, std::vector{1.07393714f, + 1.15248052f, + 1.16671345f, + 0.21450312f, + 1.2380678f, + 1.51688835f, + 0.46718366f, + 0.91810346f, + 1.1274234f, + 0.51022074f, + 1.11389844f, + 0.74174305f}), + Tensor(ET, {2, 3}, std::vector{0.81014400720596313, + 0.76665538549423218, + 0.82387429475784302, + 0.6479143500328064, + 0.66586339473724365, + 0.74838578701019287}), + Tensor(ET, {2, 3}, std::vector{1.6800162792205811, + 1.1150213479995728, + 1.4510968923568726, + 1.0649888515472412, + 0.93761754035949707, + 1.3659683465957642}), + "lstm_cell_bias_clip"), + }; + return params; +} + +std::vector generateCombinedParamsBiasClip() { + const std::vector> generatedParams { + generateParamsBiasClip(), + generateParamsBiasClip(), + generateParamsBiasClip(), + generateParamsBiasClip(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_LSTMCell_With_Hardcoded_Refs, ReferenceLSTMCellTest, + testing::ValuesIn(generateCombinedParams()), ReferenceLSTMCellTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_LSTMCell_With_Hardcoded_Refs, ReferenceLSTMCellTestBiasDefaultAttrs, + testing::ValuesIn(generateCombinedParamsBiasDefaultAttrs()), ReferenceLSTMCellTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_LSTMCell_With_Hardcoded_Refs, ReferenceLSTMCellTestBiasClip, + testing::ValuesIn(generateCombinedParamsBiasClip()), ReferenceLSTMCellTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/one_hot.cpp b/docs/template_plugin/tests/functional/op_reference/one_hot.cpp new file mode 100644 index 00000000000000..7dbcd5788e55a6 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/one_hot.cpp @@ -0,0 +1,226 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/one_hot.hpp" +#include "openvino/op/constant.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct OneHotParams { + OneHotParams( + const Tensor& dataTensor, const int32_t axis, + const Tensor& depthTensor, const Tensor& onValueTensor, const Tensor& offValueTensor, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), axis(axis), + depthTensor(depthTensor), onValueTensor(onValueTensor), offValueTensor(offValueTensor), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + int32_t axis; + Tensor depthTensor; + Tensor onValueTensor; + Tensor offValueTensor; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceOneHotTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_axis=" << param.axis; + result << "_deType=" << param.depthTensor.type; + result << "_deShape=" << param.depthTensor.shape; + result << "_onType=" << param.onValueTensor.type; + result << "_onShape=" << param.onValueTensor.shape; + result << "_offType=" << param.offValueTensor.type; + result << "_offShape=" << param.offValueTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const OneHotParams& params) { + std::shared_ptr function; + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto depth = std::make_shared(params.depthTensor.type, params.depthTensor.shape, + params.depthTensor.data.data()); + const auto onValue = std::make_shared(params.onValueTensor.type, params.onValueTensor.shape, + params.onValueTensor.data.data()); + const auto offValue = std::make_shared(params.offValueTensor.type, params.offValueTensor.shape, + params.offValueTensor.data.data()); + const auto oneHot = std::make_shared(data, depth, onValue, offValue, params.axis); + function = std::make_shared(oneHot, ParameterVector{data}); + return function; + } +}; + +TEST_P(ReferenceOneHotTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateExpectedValues(const Shape& input_shape, std::vector input, uint32_t category_count) { +// std::vector input{0, 11, 101, 1001, 10001, static_cast(category_count - 1)}; + std::vector output(shape_size(input_shape), 0); + for (size_t i = 0; i < input.size(); ++i) { + output[i * category_count + input[i]] = 1; + } + return output; +} + +template +std::vector generateParams() { + using T1 = typename element_type_traits::value_type; + using T2 = typename element_type_traits::value_type; + std::vector params { + OneHotParams( + Tensor(ET1, {}, std::vector{2}), + 0, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {3}, std::vector{0, 0, 1}), + "one_hot_scalar_2_in_3"), + OneHotParams( + Tensor(ET1, {}, std::vector{1}), + 0, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {3}, std::vector{0, 1, 0}), + "one_hot_scalar_1_in_3"), + OneHotParams( + Tensor(ET1, {}, std::vector{0}), + 0, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {3}, std::vector{1, 0, 0}), + "one_hot_scalar_0_in_3"), + OneHotParams( + Tensor(ET1, {8}, std::vector{2, 1, 0, 0, 2, 2, 1, 0}), + 0, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {3, 8}, std::vector{0, 0, 1, 1, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 1, 0, 0}), + "one_hot_vector_0"), + OneHotParams( + Tensor(ET1, {8}, std::vector{2, 1, 0, 0, 2, 2, 1, 0}), + 1, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {8, 3}, std::vector{0, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 1, 0, 1, 0, 0}), + "one_hot_vector_1"), + OneHotParams( + Tensor(ET1, {8}, std::vector{2, 1, 0, 0, 3, 2, 1, 0}), + 1, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {8, 3}, std::vector{0, 0, 1, 0, 1, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 1, 0, 0}), + "one_hot_vector_1_barely_oob"), + OneHotParams( + Tensor(ET1, {3, 3}, std::vector{0, 1, 1, 2, 1, 0, 0, 2, 1}), + 0, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {3, 3, 3}, std::vector{1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}), + "one_hot_matrix_0"), + OneHotParams( + Tensor(ET1, {6}, std::vector{0, 11, 101, 1001, 10001, 19999}), + 1, + Tensor(ET1, {}, std::vector{20000}), + Tensor(ET2, {}, std::vector{1}), + Tensor(ET2, {}, std::vector{0}), + Tensor(ET2, {6, 20000}, generateExpectedValues({6, 20000}, + std::vector{0, 11, 101, 1001, 10001, 19999}, + 20000)), + "one_hot_vector_many_categories"), + }; + return params; +} + +template +std::vector generateParamsFloat() { + using T1 = typename element_type_traits::value_type; + using T2 = typename element_type_traits::value_type; + std::vector params { + OneHotParams( + Tensor(ET1, {3, 3}, std::vector{0, 1, 1, 2, 1, 0, 0, 2, 1}), + 0, + Tensor(ET1, {}, std::vector{3}), + Tensor(ET2, {}, std::vector{2.5}), + Tensor(ET2, {}, std::vector{0.5}), + Tensor(ET2, {3, 3, 3}, std::vector{ + 2.5, 0.5, 0.5, 0.5, 0.5, 2.5, 2.5, 0.5, 0.5, 0.5, 2.5, 2.5, 0.5, 2.5, + 0.5, 0.5, 0.5, 2.5, 0.5, 0.5, 0.5, 2.5, 0.5, 0.5, 0.5, 2.5, 0.5}), + "one_hot_on_off_float"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParamsFloat(), + generateParamsFloat(), + generateParamsFloat(), + generateParamsFloat(), + generateParamsFloat(), + generateParamsFloat(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_OneHot_With_Hardcoded_Refs, ReferenceOneHotTest, + testing::ValuesIn(generateCombinedParams()), ReferenceOneHotTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/pad.cpp b/docs/template_plugin/tests/functional/op_reference/pad.cpp new file mode 100644 index 00000000000000..dfe16f69ad6e93 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/pad.cpp @@ -0,0 +1,1101 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "openvino/op/pad.hpp" +#include "openvino/op/constant.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct PadParams { + PadParams( + const Tensor& inputData, const Tensor& padsBegin, const Tensor& padsEnd, + const Tensor& expectedOutput, op::PadMode padMode, const Tensor& constantValue, + const std::string& testcaseName = "") : + inputData(inputData), padsBegin(padsBegin), padsEnd(padsEnd), + expectedOutput(expectedOutput), padMode(padMode), + useConstValue{true}, constantValue(constantValue), + testcaseName(testcaseName) {} + + PadParams( + const Tensor& inputData, const Tensor& padsBegin, const Tensor& padsEnd, + const Tensor& expectedOutput, op::PadMode padMode, + const std::string& testcaseName = "") : + inputData(inputData), padsBegin(padsBegin), padsEnd(padsEnd), + expectedOutput(expectedOutput), padMode(padMode), + testcaseName(testcaseName) {} + + Tensor inputData; + Tensor padsBegin; + Tensor padsEnd; + Tensor expectedOutput; + op::PadMode padMode; + bool useConstValue{false}; + Tensor constantValue; + std::string testcaseName; +}; + +class ReferencePadTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + SKIP_IF_CURRENT_TEST_IS_DISABLED(); + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.inputData.data}; + refOutData = {params.expectedOutput.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "iType=" << param.inputData.type; + result << "_iShape=" << param.inputData.shape; + result << "_pbType=" << param.padsBegin.type; + result << "_pbShape=" << param.padsBegin.shape; + result << "_peType=" << param.padsEnd.type; + result << "_peShape=" << param.padsEnd.shape; + result << "_oType=" << param.expectedOutput.type; + result << "_oShape=" << param.expectedOutput.shape; + result << "_=" << param.testcaseName; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const PadParams& params) { + const auto data = std::make_shared(params.inputData.type, + params.inputData.shape); + const auto padsBegin = op::v0::Constant::create(params.padsBegin.type, + params.padsBegin.shape, + params.padsBegin.data.data()); + const auto padsEnd = op::v0::Constant::create(params.padsEnd.type, + params.padsEnd.shape, + params.padsEnd.data.data()); + const auto f = [&] { + if (params.useConstValue) { + // pad_value should be used only in CONSTANT mode + const auto padVal = op::v0::Constant::create(params.constantValue.type, + params.constantValue.shape, + params.constantValue.data.data()); + return std::make_shared(std::make_shared(data, + padsBegin, + padsEnd, + padVal, + params.padMode), + ParameterVector{data}); + } + + return std::make_shared(std::make_shared(data, + padsBegin, + padsEnd, + params.padMode), + ParameterVector{data}); + }(); + return f; + } +}; + +TEST_P(ReferencePadTest, CompareWithRefs) { + Exec(); +} + +class ReferencePadTestParamsTooLarge : public ReferencePadTest {}; + +TEST_P(ReferencePadTestParamsTooLarge, CompareWithRefs) { + EXPECT_ANY_THROW(Exec()); +} + +class ReferencePadTestParamsOk : public ReferencePadTest {}; + +TEST_P(ReferencePadTestParamsOk, CompareWithRefs) { + EXPECT_NO_THROW(Exec()); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + using T_INT = typename element_type_traits::value_type; + std::vector params { + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{4}), + Tensor(ET_INT, {1}, std::vector{5}), + Tensor(ET, {15}, std::vector{ + 2112, 2112, 2112, 2112, 1, 2, 3, 4, 5, 6, 2112, 2112, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_1d_constant_const_value_provided_0"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{4}), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET, {10}, std::vector{ + 2112, 2112, 2112, 2112, 1, 2, 3, 4, 5, 6, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_1d_constant_const_value_provided_1"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {9}, std::vector{ + 1, 2, 3, 4, 5, 6, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_1d_constant_const_value_provided_2"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{4}), + Tensor(ET_INT, {1}, std::vector{5}), + Tensor(ET, {15}, std::vector{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, + }), + op::PadMode::CONSTANT, + "pad_1d_constant_use_default_const_0"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{4}), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET, {10}, std::vector{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + }), + op::PadMode::CONSTANT, + "pad_1d_constant_use_default_const_1"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {9}, std::vector{ + 1, 2, 3, 4, 5, 6, 0, 0, 0, + }), + op::PadMode::CONSTANT, + "pad_1d_constant_use_default_const_2"), + + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{3, 4}), + Tensor(ET, {6, 8}, std::vector{ + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 1, 2, 2112, 2112, 2112, 2112, + 2112, 2112, 3, 4, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_2d_constant_const_value_provided_0"), + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {3, 4}, std::vector{ + 2112, 2112, 2112, 2112, + 2112, 2112, 1, 2, + 2112, 2112, 3, 4, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_2d_constant_const_value_provided_1"), + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {3, 4}, std::vector{ + 1, 2, 2112, 2112, + 3, 4, 2112, 2112, + 2112, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_2d_constant_const_value_provided_2"), + + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{3, 4}), + Tensor(ET, {6, 8}, std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 0, 0, 0, 0, + 0, 0, 3, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }), + op::PadMode::CONSTANT, + "pad_2d_constant_use_default_const_0"), + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {3, 4}, std::vector{ + 0, 0, 0, 0, + 0, 0, 1, 2, + 0, 0, 3, 4, + }), + op::PadMode::CONSTANT, + "pad_2d_constant_use_default_const_1"), + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {3, 4}, std::vector{ + 1, 2, 0, 0, + 3, 4, 0, 0, + 0, 0, 0, 0, + }), + op::PadMode::CONSTANT, + "pad_2d_constant_use_default_const_2"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {11}, std::vector{ + 1, 1, 1, 2, 3, 4, 5, 6, 6, 6, 6, + }), + op::PadMode::EDGE, + "pad_1d_edge_0"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{1}), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET, {7}, std::vector{ + 1, 1, 2, 3, 4, 5, 6, + }), + op::PadMode::EDGE, + "pad_1d_edge_1"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET, {8}, std::vector{ + 1, 2, 3, 4, 5, 6, 6, 6, + }), + op::PadMode::EDGE, + "pad_1d_edge_2"), + + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{2, 1}), + Tensor(ET, {5, 5}, std::vector{ + 1, 1, 1, 2, 2, + 1, 1, 1, 2, 2, + 3, 3, 3, 4, 4, + 3, 3, 3, 4, 4, + 3, 3, 3, 4, 4, + }), + op::PadMode::EDGE, + "pad_2d_edge_0"), + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {3, 4}, std::vector{ + 1, 1, 1, 2, + 1, 1, 1, 2, + 3, 3, 3, 4, + }), + op::PadMode::EDGE, + "pad_2d_edge_1"), + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 3, 4, + }), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET_INT, {2}, std::vector{2, 1}), + Tensor(ET, {4, 3}, std::vector{ + 1, 2, 2, + 3, 4, 4, + 3, 4, 4, + 3, 4, 4, + }), + op::PadMode::EDGE, + "pad_2d_edge_2"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {11}, std::vector{ + 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, + }), + op::PadMode::REFLECT, + "pad_1d_reflect_0"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{1}), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET, {7}, std::vector{ + 2, 1, 2, 3, 4, 5, 6, + }), + op::PadMode::REFLECT, + "pad_1d_reflect_1"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET, {8}, std::vector{ + 1, 2, 3, 4, 5, 6, 5, 4, + }), + op::PadMode::REFLECT, + "pad_1d_reflect_2"), + + PadParams( + Tensor(ET, {3, 3}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{2, 1}), + Tensor(ET, {6, 6}, std::vector{ + 6, 5, 4, 5, 6, 5, + 3, 2, 1, 2, 3, 2, + 6, 5, 4, 5, 6, 5, + 9, 8, 7, 8, 9, 8, + 6, 5, 4, 5, 6, 5, + 3, 2, 1, 2, 3, 2, + }), + op::PadMode::REFLECT, + "pad_2d_reflect_0"), + PadParams( + Tensor(ET, {3, 3}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {4, 5}, std::vector{ + 6, 5, 4, 5, 6, + 3, 2, 1, 2, 3, + 6, 5, 4, 5, 6, + 9, 8, 7, 8, 9, + }), + op::PadMode::REFLECT, + "pad_2d_reflect_1"), + PadParams( + Tensor(ET, {3, 3}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + }), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET_INT, {2}, std::vector{2, 1}), + Tensor(ET, {5, 4}, std::vector{ + 1, 2, 3, 2, + 4, 5, 6, 5, + 7, 8, 9, 8, + 4, 5, 6, 5, + 1, 2, 3, 2, + }), + op::PadMode::REFLECT, + "pad_2d_reflect_2"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {11}, std::vector{ + 2, 1, 1, 2, 3, 4, 5, 6, 6, 5, 4, + }), + op::PadMode::SYMMETRIC, + "pad_1d_symmetric_0"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{1}), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET, {7}, std::vector{ + 1, 1, 2, 3, 4, 5, 6, + }), + op::PadMode::SYMMETRIC, + "pad_1d_symmetric_1"), + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{0}), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET, {8}, std::vector{ + 1, 2, 3, 4, 5, 6, 6, 5, + }), + op::PadMode::SYMMETRIC, + "pad_1d_symmetric_2"), + + PadParams( + Tensor(ET, {3, 3}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{2, 1}), + Tensor(ET, {6, 6}, std::vector{ + 2, 1, 1, 2, 3, 3, + 2, 1, 1, 2, 3, 3, + 5, 4, 4, 5, 6, 6, + 8, 7, 7, 8, 9, 9, + 8, 7, 7, 8, 9, 9, + 5, 4, 4, 5, 6, 6, + }), + op::PadMode::SYMMETRIC, + "pad_2d_symmetric_0"), + PadParams( + Tensor(ET, {3, 3}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {4, 5}, std::vector{ + 2, 1, 1, 2, 3, + 2, 1, 1, 2, 3, + 5, 4, 4, 5, 6, + 8, 7, 7, 8, 9, + }), + op::PadMode::SYMMETRIC, + "pad_2d_symmetric_1"), + PadParams( + Tensor(ET, {3, 3}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + }), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET_INT, {2}, std::vector{2, 1}), + Tensor(ET, {5, 4}, std::vector{ + 1, 2, 3, 3, + 4, 5, 6, 6, + 7, 8, 9, 9, + 7, 8, 9, 9, + 4, 5, 6, 6, + }), + op::PadMode::SYMMETRIC, + "pad_2d_symmetric"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{4}), + Tensor(ET_INT, {1}, std::vector{5}), + Tensor(ET, {15}, std::vector{ + 2112, 2112, 2112, 2112, 1, 2, 3, 4, 5, 6, 2112, 2112, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_exterior_1d"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{4}), + Tensor(ET_INT, {1}, std::vector{-2}), + Tensor(ET, {8}, std::vector{ + 2112, 2112, 2112, 2112, 1, 2, 3, 4, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_negative_exterior_1d"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{4}), + Tensor(ET_INT, {1}, std::vector{-7}), + Tensor(ET, {3}, std::vector{ + 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_negative_exterior_1d_check_limits"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {11}, std::vector{ + 1, 1, 1, 2, 3, 4, 5, 6, 6, 6, 6, + }), + op::PadMode::EDGE, + Tensor(ET, {}, std::vector{2112}), + "pad_edge_1d"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{-3}), + Tensor(ET, {5}, std::vector{ + 1, 1, 1, 2, 3, + }), + op::PadMode::EDGE, + Tensor(ET, {}, std::vector{2112}), + "pad_edge_1d_top_neg"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{-7}), + Tensor(ET, {1}, std::vector{ + 1, + }), + op::PadMode::EDGE, + Tensor(ET, {}, std::vector{2112}), + "pad_edge_1d_top_neg_bigger_than_tensor"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{-2}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {7}, std::vector{ + 3, 4, 5, 6, 6, 6, 6, + }), + op::PadMode::EDGE, + Tensor(ET, {}, std::vector{2112}), + "pad_edge_1d_bottom_neg"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{-7}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {2}, std::vector{ + 6, 6, + }), + op::PadMode::EDGE, + Tensor(ET, {}, std::vector{2112}), + "pad_edge_1d_bottom_neg_bigger_than_tensor"), + + PadParams( + Tensor(ET, {3, 4}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + }), + Tensor(ET_INT, {2}, std::vector{2, 3}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {6, 9}, std::vector{ + 1, 1, 1, 1, 2, 3, 4, 4, 4, + 1, 1, 1, 1, 2, 3, 4, 4, 4, + 1, 1, 1, 1, 2, 3, 4, 4, 4, + 5, 5, 5, 5, 6, 7, 8, 8, 8, + 9, 9, 9, 9, 10, 11, 12, 12, 12, + 9, 9, 9, 9, 10, 11, 12, 12, 12, + }), + op::PadMode::EDGE, + Tensor(ET, {}, std::vector{2112}), + "pad_edge_2d"), + + PadParams( + Tensor(ET, {3, 4}, std::vector{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + }), + Tensor(ET_INT, {2}, std::vector{2, -1}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {6, 5}, std::vector{ + 2, 3, 4, 4, 4, + 2, 3, 4, 4, 4, + 2, 3, 4, 4, 4, + 6, 7, 8, 8, 8, + 10, 11, 12, 12, 12, + 10, 11, 12, 12, 12, + }), + op::PadMode::EDGE, + Tensor(ET, {}, std::vector{2112}), + "pad_edge_2d_with_neg"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {11}, std::vector{ + 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, + }), + op::PadMode::REFLECT, + Tensor(ET, {}, std::vector{2112}), + "pad_reflect_1d"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{-3}), + Tensor(ET, {5}, std::vector{ + 3, 2, 1, 2, 3, + }), + op::PadMode::REFLECT, + Tensor(ET, {}, std::vector{2112}), + "pad_reflect_1d_top_neg"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{2}), + Tensor(ET_INT, {1}, std::vector{-7}), + Tensor(ET, {1}, std::vector{ + 3, + }), + op::PadMode::REFLECT, + Tensor(ET, {}, std::vector{2112}), + "pad_reflect_1d_top_neg_bigger_than_tensor"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{-2}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {7}, std::vector{ + 3, 4, 5, 6, 5, 4, 3, + }), + op::PadMode::REFLECT, + Tensor(ET, {}, std::vector{2112}), + "pad_reflect_1d_bottom_neg"), + + PadParams( + Tensor(ET, {6}, std::vector{ + 1, 2, 3, 4, 5, 6, + }), + Tensor(ET_INT, {1}, std::vector{-7}), + Tensor(ET_INT, {1}, std::vector{3}), + Tensor(ET, {2}, std::vector{ + 4, 3, + }), + op::PadMode::REFLECT, + Tensor(ET, {}, std::vector{2112}), + "pad_reflect_1d_bottom_neg_bigger_than_tensor"), + + PadParams( + Tensor(ET, {3, 4}, std::vector{ + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + }), + Tensor(ET_INT, {2}, std::vector{2, 3}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {6, 9}, std::vector{ + 12, 11, 10, 9, 10, 11, 12, 11, 10, + 8, 7, 6, 5, 6, 7, 8, 7, 6, + 4, 3, 2, 1, 2, 3, 4, 3, 2, + 8, 7, 6, 5, 6, 7, 8, 7, 6, + 12, 11, 10, 9, 10, 11, 12, 11, 10, + 8, 7, 6, 5, 6, 7, 8, 7, 6, + }), + op::PadMode::REFLECT, + Tensor(ET, {}, std::vector{2112}), + "pad_reflect_2d"), + + PadParams( + Tensor(ET, {3, 4}, std::vector{ + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + }), + Tensor(ET_INT, {2}, std::vector{2, -1}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {6, 5}, std::vector{ + 10, 11, 12, 11, 10, + 6, 7, 8, 7, 6, + 2, 3, 4, 3, 2, + 6, 7, 8, 7, 6, + 10, 11, 12, 11, 10, + 6, 7, 8, 7, 6, + }), + op::PadMode::REFLECT, + Tensor(ET, {}, std::vector{2112}), + "pad_reflect_2d_with_neg"), + + PadParams( + Tensor(ET, {2, 3}, std::vector{ + 1, 2, 3, + 4, 5, 6, + }), + Tensor(ET_INT, {2}, std::vector{1, -1}), + Tensor(ET_INT, {2}, std::vector{2, 0}), + Tensor(ET, {5, 2}, std::vector{ + 9, 9, + 2, 3, + 5, 6, + 9, 9, + 9, 9, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{9}), + "pad_negative_exterior_2d"), + + PadParams( + Tensor(ET, {3, 3}, std::vector{ + 1, 2, 3, + 4, 5, 6, + }), + Tensor(ET_INT, {2}, std::vector{-1, -1}), + Tensor(ET_INT, {2}, std::vector{-1, -1}), + Tensor(ET, {1, 1}, std::vector{5}), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{9}), + "pad_negative_exterior_2d_all_negative"), + + PadParams( + Tensor(ET, {0, 0}, std::vector{}), + Tensor(ET_INT, {2}, std::vector{2, 3}), + Tensor(ET_INT, {2}, std::vector{3, 2}), + Tensor(ET, {5, 5}, std::vector{ + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_exterior_2d_0x0"), + + PadParams( + Tensor(ET, {0, 3}, std::vector{}), + Tensor(ET_INT, {2}, std::vector{2, 1}), + Tensor(ET_INT, {2}, std::vector{3, 1}), + Tensor(ET, {5, 5}, std::vector{ + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_exterior_2d_0x3"), + + PadParams( + Tensor(ET, {3, 0}, std::vector{}), + Tensor(ET_INT, {2}, std::vector{1, 3}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {5, 5}, std::vector{ + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + 2112, 2112, 2112, 2112, 2112, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{2112}), + "pad_exterior_2d_3x0"), + + PadParams( + Tensor(ET, {2, 2, 4, 4}, std::vector{ + 0, 1, 0, 2, + 0, 3, 2, 0, + 2, 0, 0, 0, + 0, 2, 1, 0, + + 0, 0, 0, 2, + 0, 2, 3, 0, + 2, 0, 1, 0, + 2, 0, 0, 0, + + 0, 2, 1, 1, + 0, 0, 2, 0, + 0, 0, 1, 2, + 0, 0, 0, 0, + + 2, 1, 0, 0, + 0, 2, 0, 0, + 1, 1, 2, 0, + 1, 0, 0, 0, + }), + Tensor(ET_INT, {4}, std::vector{0, 0, 0, 0}), + Tensor(ET_INT, {4}, std::vector{0, 0, 2, 2}), + Tensor(ET, {2, 2, 6, 6}, std::vector{ + 0, 1, 0, 2, 42, 42, + 0, 3, 2, 0, 42, 42, + 2, 0, 0, 0, 42, 42, + 0, 2, 1, 0, 42, 42, + 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, + + 0, 0, 0, 2, 42, 42, + 0, 2, 3, 0, 42, 42, + 2, 0, 1, 0, 42, 42, + 2, 0, 0, 0, 42, 42, + 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, + + 0, 2, 1, 1, 42, 42, + 0, 0, 2, 0, 42, 42, + 0, 0, 1, 2, 42, 42, + 0, 0, 0, 0, 42, 42, + 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, + + 2, 1, 0, 0, 42, 42, + 0, 2, 0, 0, 42, 42, + 1, 1, 2, 0, 42, 42, + 1, 0, 0, 0, 42, 42, + 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{42}), + "pad_2channel_2image_asym"), + + PadParams( + Tensor(ET, {2, 3}, std::vector{ + 1, 2, 3, + 4, 5, 6, + }), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET_INT, {2}, std::vector{1, 2}), + Tensor(ET, {4, 7}, std::vector{ + 2, 1, 1, 2, 3, 3, 2, + 2, 1, 1, 2, 3, 3, 2, + 5, 4, 4, 5, 6, 6, 5, + 5, 4, 4, 5, 6, 6, 5, + }), + op::PadMode::SYMMETRIC, + Tensor(ET, {}, std::vector{2112}), + "pad_symmetric"), + }; + return params; +} + +template +std::vector generateParamsFloatValue() { + using T = typename element_type_traits::value_type; + using T_INT = typename element_type_traits::value_type; + std::vector params { + PadParams( + Tensor(ET, {1, 2, 2, 2}, std::vector{ + 0.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 0.0f, + 0.0f, 0.0f, + }), + Tensor(ET_INT, {4}, std::vector{0, 0, 1, 1}), + Tensor(ET_INT, {4}, std::vector{0, 0, 1, 1}), + Tensor(ET, {1, 2, 4, 4}, std::vector{ + 42.0f, 42.0f, 42.0f, 42.0f, + 42.0f, 0.0f, 0.0f, 42.0f, + 42.0f, 0.0f, 0.0f, 42.0f, + 42.0f, 42.0f, 42.0f, 42.0f, + 42.0f, 42.0f, 42.0f, 42.0f, + 42.0f, 0.0f, 0.0f, 42.0f, + 42.0f, 0.0f, 0.0f, 42.0f, + 42.0f, 42.0f, 42.0f, 42.0f, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{42}), + "pad_exterior_4d_1x2x2x2"), + + PadParams( + Tensor(ET, {1, 3, 2, 2}, std::vector{ + 0.0f, 0.0f, + 0.0f, 0.0f, + 1.0f, 1.0f, + 1.0f, 1.0f, + 2.0f, 2.0f, + 2.0f, 2.0f, + }), + Tensor(ET_INT, {4}, std::vector{0, -1, 1, 1}), + Tensor(ET_INT, {4}, std::vector{0, -1, 1, 1}), + Tensor(ET, {1, 1, 4, 4}, std::vector{ + 42.0f, 42.0f, 42.0f, 42.0f, + 42.0f, 1.0f, 1.0f, 42.0f, + 42.0f, 1.0f, 1.0f, 42.0f, + 42.0f, 42.0f, 42.0f, 42.0f, + }), + op::PadMode::CONSTANT, + Tensor(ET, {}, std::vector{42}), + "pad_negative_exterior_4d"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParamsFloatValue(), + generateParamsFloatValue(), + generateParamsFloatValue(), + generateParamsFloatValue(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTest, + testing::ValuesIn(generateCombinedParams()), ReferencePadTest::getTestCaseName); + +template +std::vector generateParamsTooLarge() { + using T = typename element_type_traits::value_type; + using T_INT = typename element_type_traits::value_type; + std::vector params { + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 4, 5, + }), + Tensor(ET_INT, {2}, std::vector{0, 3}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {2, 5}, std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }), + op::PadMode::SYMMETRIC, + "pad_to_large_symmetric_padding"), + + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 4, 5, + }), + Tensor(ET_INT, {2}, std::vector{0, 2}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {2, 4}, std::vector{ + 0, 0, 0, 0, 0, 0, 0, 0, + }), + op::PadMode::REFLECT, + "pad_to_large_reflect_padding"), + }; + return params; +} + +std::vector generateCombinedParamsTooLarge() { + const std::vector> generatedParams { + generateParamsTooLarge(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTestParamsTooLarge, + testing::ValuesIn(generateCombinedParamsTooLarge()), ReferencePadTest::getTestCaseName); + +template +std::vector generateParamsOk() { + using T = typename element_type_traits::value_type; + using T_INT = typename element_type_traits::value_type; + std::vector params { + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 4, 5, + }), + Tensor(ET_INT, {2}, std::vector{0, 2}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {2, 4}, std::vector{ + 2, 1, 1, 2, 5, 4, 4, 5, + }), + op::PadMode::SYMMETRIC, + "pad_ok_symmetric_padding"), + + PadParams( + Tensor(ET, {2, 2}, std::vector{ + 1, 2, 4, 5, + }), + Tensor(ET_INT, {2}, std::vector{0, 1}), + Tensor(ET_INT, {2}, std::vector{0, 0}), + Tensor(ET, {2, 3}, std::vector{ + 2, 1, 2, 5, 4, 5, + }), + op::PadMode::REFLECT, + "pad_ok_reflect_padding"), + }; + return params; +} + +std::vector generateCombinedParamsOk() { + const std::vector> generatedParams { + generateParamsOk(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_Pad_With_Hardcoded_Refs, ReferencePadTestParamsOk, + testing::ValuesIn(generateCombinedParamsOk()), ReferencePadTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/prior_box.cpp b/docs/template_plugin/tests/functional/op_reference/prior_box.cpp new file mode 100644 index 00000000000000..e24ae7a72b05a4 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/prior_box.cpp @@ -0,0 +1,126 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/prior_box.hpp" +#include "base_reference_test.hpp" +#include "openvino/opsets/opset1.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct PriorBoxParams { + template + PriorBoxParams(const std::vector& min_size, + const std::vector& aspect_ratio, + const bool scale_all_size, + const ov::Shape& layerShapeShape, const ov::Shape& imageShapeShape, + const ov::element::Type& iType, + const std::vector& layerShapeValues, const std::vector& imageShapeValues, + const std::vector& oValues, + const std::string& testcaseName = "") + : layerShapeShape(layerShapeShape), + imageShapeShape(imageShapeShape), + inType(iType), + outType(ov::element::Type_t::f32), + layerShapeData(CreateTensor(iType, layerShapeValues)), + imageShapeData(CreateTensor(iType, imageShapeValues)), + refData(CreateTensor(outType, oValues)), + testcaseName(testcaseName) { + attrs.min_size = min_size; + attrs.aspect_ratio = aspect_ratio; + attrs.scale_all_sizes = scale_all_size; + } + + ov::op::v0::PriorBox::Attributes attrs; + ov::Shape layerShapeShape; + ov::Shape imageShapeShape; + ov::element::Type inType; + ov::element::Type outType; + ov::runtime::Tensor layerShapeData; + ov::runtime::Tensor imageShapeData; + ov::runtime::Tensor refData; + std::string testcaseName; +}; + +class ReferencePriorBoxLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {}; + refOutData = {params.refData}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "layerShapeShape=" << param.layerShapeShape << "_"; + result << "imageShapeShape=" << param.imageShapeShape << "_"; + result << "iType=" << param.inType << "_"; + result << "oType=" << param.outType; + if (param.testcaseName != "") + result << "_" << param.testcaseName; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const PriorBoxParams& params) { + auto LS = std::make_shared(params.inType, params.layerShapeShape, params.layerShapeData.data()); + auto IS = std::make_shared(params.inType, params.imageShapeShape, params.imageShapeData.data()); + const auto PriorBox = std::make_shared(LS, IS, params.attrs); + return std::make_shared(NodeVector {PriorBox}, ParameterVector {}); + } +}; + +TEST_P(ReferencePriorBoxLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generatePriorBoxFloatParams() { + using T = typename element_type_traits::value_type; + + std::vector priorBoxParams { + PriorBoxParams({2.0f}, {1.5f}, false, + {2}, {2}, + IN_ET, + std::vector{2, 2}, + std::vector{10, 10}, + std::vector{-0.75, -0.75, 1.25, 1.25, -0.974745, -0.566497, 1.47474, 1.0665, + -0.25, -0.75, 1.75, 1.25, -0.474745, -0.566497, 1.97474, 1.0665, + -0.75, -0.25, 1.25, 1.75, -0.974745, -0.0664966, 1.47474, 1.5665, + -0.25, -0.25, 1.75, 1.75, -0.474745, -0.0664966, 1.97474, 1.5665, + 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.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.1}), + }; + return priorBoxParams; +} + +std::vector generatePriorBoxCombinedParams() { + const std::vector> priorBoxTypeParams { + generatePriorBoxFloatParams(), + generatePriorBoxFloatParams(), + generatePriorBoxFloatParams(), + generatePriorBoxFloatParams(), + generatePriorBoxFloatParams(), + generatePriorBoxFloatParams(), + generatePriorBoxFloatParams(), + generatePriorBoxFloatParams(), + }; + std::vector combinedParams; + + for (const auto& params : priorBoxTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_PriorBox_With_Hardcoded_Refs, ReferencePriorBoxLayerTest, + testing::ValuesIn(generatePriorBoxCombinedParams()), ReferencePriorBoxLayerTest::getTestCaseName); + +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/prior_box_clustered.cpp b/docs/template_plugin/tests/functional/op_reference/prior_box_clustered.cpp new file mode 100644 index 00000000000000..33b2ce5bdabb57 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/prior_box_clustered.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/prior_box.hpp" +#include "base_reference_test.hpp" +#include "openvino/opsets/opset1.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct PriorBoxClusteredParams { + template + PriorBoxClusteredParams(const std::vector& widths, + const std::vector& heights, + const bool clip, + const ov::Shape& layerShapeShape, const ov::Shape& imageShapeShape, + const ov::element::Type& iType, + const std::vector& layerShapeValues, const std::vector& imageShapeValues, + const std::vector& oValues, + const std::vector& variances = {}, + const std::string& testcaseName = "") + : layerShapeShape(layerShapeShape), + imageShapeShape(imageShapeShape), + inType(iType), + outType(ov::element::Type_t::f32), + layerShapeData(CreateTensor(iType, layerShapeValues)), + imageShapeData(CreateTensor(iType, imageShapeValues)), + refData(CreateTensor(outType, oValues)), + testcaseName(testcaseName) { + attrs.widths = widths; + attrs.heights = heights; + attrs.clip = clip; + if ( variances.size() != 0) + attrs.variances = variances; + } + + ov::op::v0::PriorBoxClustered::Attributes attrs; + ov::Shape layerShapeShape; + ov::Shape imageShapeShape; + ov::element::Type inType; + ov::element::Type outType; + ov::runtime::Tensor layerShapeData; + ov::runtime::Tensor imageShapeData; + ov::runtime::Tensor refData; + std::string testcaseName; +}; + +class ReferencePriorBoxClusteredLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {}; + refOutData = {params.refData}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "layerShapeShape=" << param.layerShapeShape << "_"; + result << "imageShapeShape=" << param.imageShapeShape << "_"; + result << "variancesSize=" << param.attrs.variances.size() << "_"; + result << "iType=" << param.inType << "_"; + result << "oType=" << param.outType; + if (param.testcaseName != "") + result << "_" << param.testcaseName; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const PriorBoxClusteredParams& params) { + auto LS = std::make_shared(params.inType, params.layerShapeShape, params.layerShapeData.data()); + auto IS = std::make_shared(params.inType, params.imageShapeShape, params.imageShapeData.data()); + const auto PriorBoxClustered = std::make_shared(LS, IS, params.attrs); + return std::make_shared(NodeVector {PriorBoxClustered}, ParameterVector {}); + } +}; + +TEST_P(ReferencePriorBoxClusteredLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generatePriorBoxClusteredFloatParams() { + using T = typename element_type_traits::value_type; + + std::vector priorBoxClusteredParams { + PriorBoxClusteredParams({3.0f}, {3.0f}, true, + {2}, {2}, + IN_ET, + std::vector{2, 2}, + std::vector{10, 10}, + std::vector{0, 0, 0.15f, 0.15f, 0.34999f, 0, 0.64999f, 0.15f, 0, 0.34999f, 0.15f, + 0.64999f, 0.34999f, 0.34999f, 0.64999f, 0.64999f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, + 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f}), + PriorBoxClusteredParams({3.0f}, {3.0f}, true, + {2}, {2}, + IN_ET, + std::vector{2, 2}, + std::vector{10, 10}, + std::vector{0, 0, 0.15f, 0.15f, 0.34999f, 0, 0.64999f, 0.15f, 0, 0.34999f, 0.15f, + 0.64999f, 0.34999f, 0.34999f, 0.64999f, 0.64999f, 0.1f, 0.2f, 0.3f, 0.4f, 0.1f, 0.2f, + 0.3f, 0.4f, 0.1f, 0.2f, 0.3f, 0.4f, 0.1f, 0.2f, 0.3f, 0.4f}, + {0.1f, 0.2f, 0.3f, 0.4f}), + }; + return priorBoxClusteredParams; +} + +std::vector generatePriorBoxClusteredCombinedParams() { + const std::vector> priorBoxClusteredTypeParams { + generatePriorBoxClusteredFloatParams(), + generatePriorBoxClusteredFloatParams(), + generatePriorBoxClusteredFloatParams(), + generatePriorBoxClusteredFloatParams(), + generatePriorBoxClusteredFloatParams(), + generatePriorBoxClusteredFloatParams(), + generatePriorBoxClusteredFloatParams(), + generatePriorBoxClusteredFloatParams(), + }; + std::vector combinedParams; + + for (const auto& params : priorBoxClusteredTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_PriorBoxClustered_With_Hardcoded_Refs, ReferencePriorBoxClusteredLayerTest, + testing::ValuesIn(generatePriorBoxClusteredCombinedParams()), ReferencePriorBoxClusteredLayerTest::getTestCaseName); + +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/reorg_yolo.cpp b/docs/template_plugin/tests/functional/op_reference/reorg_yolo.cpp new file mode 100644 index 00000000000000..b9c2618e56ad6a --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/reorg_yolo.cpp @@ -0,0 +1,123 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/reorg_yolo.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct ReorgYoloParams { + template + ReorgYoloParams(const ov::Strides& stride, + const ov::PartialShape& inputShape, + const ov::element::Type& iType, + const std::vector& oValues, + const std::string& testcaseName = "") + : stride(stride), + inputShape(inputShape), + inType(iType), + outType(iType), + refData(CreateTensor(iType, oValues)), + testcaseName(testcaseName) { + std::vector iValues(shape_size(inputShape.get_shape())); + std::iota(iValues.begin(), iValues.end(), 0); + inputData = CreateTensor(iType, iValues); + } + + ov::Strides stride; + ov::PartialShape inputShape; + ov::element::Type inType; + ov::element::Type outType; + ov::runtime::Tensor inputData; + ov::runtime::Tensor refData; + std::string testcaseName; +}; + +class ReferenceReorgYoloLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.inputData}; + refOutData = {params.refData}; + } + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "inputShape=" << param.inputShape << "_"; + result << "iType=" << param.inType << "_"; + result << "oType=" << param.outType << "_"; + result << "stride=" << param.stride; + if (param.testcaseName != "") + result << "_" << param.testcaseName; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const ReorgYoloParams& params) { + const auto p = std::make_shared(params.inType, params.inputShape); + const auto ReorgYolo = std::make_shared(p, params.stride); + return std::make_shared(NodeVector {ReorgYolo}, ParameterVector {p}); + } +}; + +TEST_P(ReferenceReorgYoloLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateReorgYoloParams() { + using T = typename element_type_traits::value_type; + + std::vector reorgYoloParams { + ReorgYoloParams({2}, + PartialShape {1, 8, 4, 4}, + IN_ET, + std::vector{0, 2, 4, 6, 16, 18, 20, 22, 32, 34, 36, 38, 48, 50, 52, 54, 64, 66, 68, 70, 80, 82, + 84, 86, 96, 98, 100, 102, 112, 114, 116, 118, 1, 3, 5, 7, 17, 19, 21, 23, 33, 35, 37, 39, + 49, 51, 53, 55, 65, 67, 69, 71, 81, 83, 85, 87, 97, 99, 101, 103, 113, 115, 117, 119, 8, 10, + 12, 14, 24, 26, 28, 30, 40, 42, 44, 46, 56, 58, 60, 62, 72, 74, 76, 78, 88, 90, 92, 94, + 104, 106, 108, 110, 120, 122, 124, 126, 9, 11, 13, 15, 25, 27, 29, 31, 41, 43, 45, 47, 57, 59, + 61, 63, 73, 75, 77, 79, 89, 91, 93, 95, 105, 107, 109, 111, 121, 123, 125, 127}), + ReorgYoloParams({3}, + PartialShape {1, 9, 3, 3}, + IN_ET, + std::vector{0, 3, 6, 27, 30, 33, 54, 57, 60, 1, 4, 7, 28, 31, 34, 55, 58, 61, 2, 5, 8, 29, 32, 35, 56, 59, 62, + 9, 12, 15, 36, 39, 42, 63, 66, 69, 10, 13, 16, 37, 40, 43, 64, 67, 70, 11, 14, 17, 38, 41, 44, 65, 68, 71, + 18, 21, 24, 45, 48, 51, 72, 75, 78, 19, 22, 25, 46, 49, 52, 73, 76, 79, 20, 23, 26, 47, 50, 53, 74, 77, 80}), + }; + return reorgYoloParams; +} + +std::vector generateReorgYoloCombinedParams() { + const std::vector> reorgYoloTypeParams { + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + generateReorgYoloParams(), + }; + std::vector combinedParams; + + for (const auto& params : reorgYoloTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_ReorgYolo_With_Hardcoded_Refs, ReferenceReorgYoloLayerTest, + testing::ValuesIn(generateReorgYoloCombinedParams()), ReferenceReorgYoloLayerTest::getTestCaseName); + +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/rnn_cell.cpp b/docs/template_plugin/tests/functional/op_reference/rnn_cell.cpp new file mode 100644 index 00000000000000..5bb43841029794 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/rnn_cell.cpp @@ -0,0 +1,304 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/rnn_cell.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct RNNCellParams { + RNNCellParams( + int32_t batchSize, int32_t inputSize, int32_t hiddenSize, + const Tensor& X, const Tensor& H_t, const Tensor& W, const Tensor& R, const Tensor& B, + const Tensor& Ho, const std::string& testcaseName = "") : + batchSize(batchSize), inputSize(inputSize), hiddenSize(hiddenSize), + X(X), H_t(H_t), W(W), R(R), B(B), Ho(Ho), testcaseName(testcaseName) {} + + int32_t batchSize; + int32_t inputSize; + int32_t hiddenSize; + Tensor X; + Tensor H_t; + Tensor W; + Tensor R; + Tensor B; + Tensor Ho; + std::string testcaseName; +}; + +class ReferenceRNNCellTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.X.data, params.H_t.data, params.W.data, params.R.data, params.B.data}; + refOutData = {params.Ho.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "bSize=" << param.batchSize; + result << "_iSize=" << param.inputSize; + result << "_hSize=" << param.hiddenSize; + result << "_xType=" << param.X.type; + result << "_xShape=" << param.X.shape; + result << "_htType=" << param.H_t.type; + result << "_htShape=" << param.H_t.shape; + result << "_wType=" << param.W.type; + result << "_wShape=" << param.W.shape; + result << "_rType=" << param.R.type; + result << "_rShape=" << param.R.shape; + result << "_hoType=" << param.Ho.type; + if (param.testcaseName != "") { + result << "_hoShape=" << param.Ho.shape; + result << "_=" << param.testcaseName; + } else { + result << "_hoShape=" << param.Ho.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const RNNCellParams& params) { + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto rnn_cell = std::make_shared(X, H_t, W, R, B, params.hiddenSize); + auto function = std::make_shared(NodeVector{rnn_cell}, ParameterVector{X, H_t, W, R, B}); + return function; + } +}; + +class ReferenceRNNCellTestBiasClip : public ReferenceRNNCellTest { +private: + static std::shared_ptr CreateFunction(const RNNCellParams& params) { + float clip = 2.88f; + + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto rnn_cell = std::make_shared( + X, H_t, W, R, B, params.hiddenSize, + std::vector{"tanh"}, std::vector{}, std::vector{}, clip); + auto function = std::make_shared(NodeVector{rnn_cell}, ParameterVector{X, H_t, W, R, B}); + return function; + } +}; + +class ReferenceRNNCellTestSigmoidActivationFunction : public ReferenceRNNCellTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.X.data, params.H_t.data, params.W.data, params.R.data, params.B.data}; + refOutData = {params.Ho.data}; + } + +private: + static std::shared_ptr CreateFunction(const RNNCellParams& params) { + float clip = 2.88f; + + const auto X = std::make_shared(params.X.type, params.X.shape); + const auto H_t = std::make_shared(params.H_t.type, params.H_t.shape); + const auto W = std::make_shared(params.W.type, params.W.shape); + const auto R = std::make_shared(params.R.type, params.R.shape); + const auto B = std::make_shared(params.B.type, params.B.shape); + + const auto rnn_cell = std::make_shared(X, + H_t, + W, + R, + B, + params.hiddenSize, + std::vector{"sigmoid"}, + std::vector{}, + std::vector{}, + clip); + auto function = std::make_shared(NodeVector{rnn_cell}, ParameterVector{X, H_t, W, R, B}); + return function; + } +}; + +TEST_P(ReferenceRNNCellTest, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceRNNCellTestBiasClip, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceRNNCellTestSigmoidActivationFunction, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + RNNCellParams( + 2, 3, 3, + Tensor(ET, {2, 3}, std::vector{ + 0.3432185f, 0.612268f, 0.20272376f, 0.9513413f, 0.30585995f, 0.7265472f}), + Tensor(ET, {2, 3}, std::vector{ + 0.12444675f, 0.52055854f, 0.46489045f, 0.4983964f, 0.7730452f, 0.28439692f}), + Tensor(ET, {3, 3}, std::vector{0.41930267f, + 0.7872176f, + 0.89940447f, + 0.23659843f, + 0.24676207f, + 0.17101714f, + 0.3147149f, + 0.6555601f, + 0.4559603f}), + Tensor(ET, {3, 3}, std::vector{0.8374871f, + 0.86660194f, + 0.82114047f, + 0.71549815f, + 0.18775631f, + 0.3182116f, + 0.25392973f, + 0.38301638f, + 0.85531586f}), + Tensor(ET, {3}, std::vector{0.0f, 0.0f, 0.0f}), + Tensor(ET, {2, 3}, std::vector{0.9408395f, 0.53823817f, 0.84270686f, 0.98932856f, 0.768665f, 0.90461975f}), + "rnn_cell_zero_bias_default_attrs"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParamsBiasClip() { + using T = typename element_type_traits::value_type; + std::vector params { + RNNCellParams( + 2, 3, 3, + Tensor(ET, {2, 3}, std::vector{ + 0.3432185f, 0.612268f, 0.20272376f, 0.9513413f, 0.30585995f, 0.7265472f}), + Tensor(ET, {2, 3}, std::vector{ + 0.12444675f, 0.52055854f, 0.46489045f, 0.4983964f, 0.7730452f, 0.28439692f}), + Tensor(ET, {3, 3}, std::vector{0.41930267f, + 0.7872176f, + 0.89940447f, + 0.23659843f, + 0.24676207f, + 0.17101714f, + 0.3147149f, + 0.6555601f, + 0.4559603f}), + Tensor(ET, {3, 3}, std::vector{0.8374871f, + 0.86660194f, + 0.82114047f, + 0.71549815f, + 0.18775631f, + 0.3182116f, + 0.25392973f, + 0.38301638f, + 0.85531586f}), + Tensor(ET, {3}, std::vector{1.0289404f, 1.6362579f, 0.4370661f}), + Tensor(ET, {2, 3}, std::vector{0.9922437f, 0.97749525f, 0.9312212f, 0.9937176f, 0.9901317f, 0.95906746f}), + "rnn_cell_bias_clip"), + }; + return params; +} + +std::vector generateCombinedParamsBiasClip() { + const std::vector> generatedParams { + generateParamsBiasClip(), + generateParamsBiasClip(), + generateParamsBiasClip(), + generateParamsBiasClip(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +template +std::vector generateParamsSigmoidActivationFunction() { + using T = typename element_type_traits::value_type; + std::vector params { + RNNCellParams( + 2, 3, 3, + Tensor(ET, {2, 3}, std::vector{ + 0.3432185f, 0.612268f, 0.20272376f, 0.9513413f, 0.30585995f, 0.7265472f}), + Tensor(ET, {2, 3}, std::vector{ + 0.12444675f, 0.52055854f, 0.46489045f, 0.4983964f, 0.7730452f, 0.28439692f}), + Tensor(ET, {3, 3}, std::vector{0.41930267f, + 0.7872176f, + 0.89940447f, + 0.23659843f, + 0.24676207f, + 0.17101714f, + 0.3147149f, + 0.6555601f, + 0.4559603f}), + Tensor(ET, {3, 3}, std::vector{0.8374871f, + 0.86660194f, + 0.82114047f, + 0.71549815f, + 0.18775631f, + 0.3182116f, + 0.25392973f, + 0.38301638f, + 0.85531586f}), + Tensor(ET, {3}, std::vector{1.0289404f, 1.6362579f, 0.4370661f}), + Tensor(ET, {2, 3}, std::vector{0.94126844f, 0.9036043f, 0.841243f, 0.9468489f, 0.934215f, 0.873708f}), + "rnn_cell_sigmoid_activation_function"), + }; + return params; +} + +std::vector generateCombinedParamsSigmoidActivationFunction() { + const std::vector> generatedParams { + generateParamsSigmoidActivationFunction(), + generateParamsSigmoidActivationFunction(), + generateParamsSigmoidActivationFunction(), + generateParamsSigmoidActivationFunction(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_RNNCell_With_Hardcoded_Refs, ReferenceRNNCellTest, + testing::ValuesIn(generateCombinedParams()), ReferenceRNNCellTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_RNNCell_With_Hardcoded_Refs, ReferenceRNNCellTestBiasClip, + testing::ValuesIn(generateCombinedParamsBiasClip()), ReferenceRNNCellTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_RNNCell_With_Hardcoded_Refs, ReferenceRNNCellTestSigmoidActivationFunction, + testing::ValuesIn(generateCombinedParamsSigmoidActivationFunction()), ReferenceRNNCellTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/roll.cpp b/docs/template_plugin/tests/functional/op_reference/roll.cpp new file mode 100644 index 00000000000000..3fdb1f4e217865 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/roll.cpp @@ -0,0 +1,212 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/opsets/opset1.hpp" +#include "openvino/opsets/opset7.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct RollParams { + RollParams(const Tensor& dataTensor, const Tensor& shiftTensor, const Tensor& axesTensor, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), shiftTensor(shiftTensor), axesTensor(axesTensor), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor shiftTensor; + Tensor axesTensor; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceRollLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_sType=" << param.shiftTensor.type; + result << "_sShape=" << param.shiftTensor.shape; + result << "_aType=" << param.axesTensor.type; + result << "_aShape=" << param.axesTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const RollParams& params) { + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto shift = std::make_shared(params.shiftTensor.type, + params.shiftTensor.shape, + params.shiftTensor.data.data()); + const auto axes = std::make_shared(params.axesTensor.type, + params.axesTensor.shape, + params.axesTensor.data.data()); + const auto roll = std::make_shared(data, shift, axes); + return std::make_shared(NodeVector {roll}, ParameterVector {data}); + } +}; + +TEST_P(ReferenceRollLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateRollParams() { + using T = typename element_type_traits::value_type; + std::vector rollParams { + // roll_repeated_axes + RollParams( + Tensor({4, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}), + Tensor({3}, element::i64, std::vector{1, 2, 1}), + Tensor({3}, element::i64, std::vector{0, 1, 0}), + Tensor({4, 3}, IN_ET, std::vector{8, 9, 7, 11, 12, 10, 2, 3, 1, 5, 6, 4}), + "roll_repeated_axes"), + + // roll_negative_axes + RollParams( + Tensor({4, 2, 3}, IN_ET, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}), + Tensor({3}, element::i64, std::vector{2, -1, -7}), + Tensor({3}, element::i64, std::vector{-1, -1, -2}), + Tensor({4, 2, 3}, IN_ET, std::vector{6, 4, 5, 3, 1, 2, 12, 10, 11, 9, 7, 8, 18, 16, 17, 15, 13, 14, 24, 22, 23, 21, 19, 20}), + "roll_negative_axes"), + }; + return rollParams; +} + +std::vector generateRollFloatingPointParams() { + std::vector rollParams { + // roll_2d_input + RollParams( + Tensor({4, 3}, element::f32, std::vector{50.2907, + 70.8054, + -68.3403, + 62.6444, + 4.9748, + -18.5551, + 40.5383, + -15.3859, + -4.5881, + -43.3479, + 94.1676, + -95.7097}), + Tensor({1}, element::i64, std::vector{1}), + Tensor({1}, element::i64, std::vector{0}), + Tensor({4, 3}, element::f32, std::vector{-43.3479, + 94.1676, + -95.7097, + 50.2907, + 70.8054, + -68.3403, + 62.6444, + 4.9748, + -18.5551, + 40.5383, + -15.3859, + -4.5881}), + "roll_2d_input"), + + // roll_2d_input_negative_shift + RollParams( + Tensor({4, 3}, element::f32, std::vector{50.2907, + 70.8054, + -68.3403, + 62.6444, + 4.9748, + -18.5551, + 40.5383, + -15.3859, + -4.5881, + -43.3479, + 94.1676, + -95.7097}), + Tensor({2}, element::i64, std::vector{-1, 2}), + Tensor({2}, element::i64, std::vector{0, 1}), + Tensor({4, 3}, element::f32, std::vector{4.9748, + -18.5551, + 62.6444, + -15.3859, + -4.5881, + 40.5383, + 94.1676, + -95.7097, + -43.3479, + 70.8054, + -68.3403, + 50.2907}), + "roll_2d_input_negative_shift"), + + // roll_3d_input + RollParams( + Tensor({4, 2, 3}, element::f32, std::vector{94.0773, 33.0599, 58.1724, -20.3640, 54.5372, -54.3023, 10.4662, 11.7532, + -11.7692, 56.4223, -95.3774, 8.8978, 1.9305, 13.8025, 12.0827, 81.4669, + 19.5321, -8.9553, -75.3226, 20.8033, 20.7660, 62.7361, 14.9372, -33.0825}), + Tensor({3}, element::i64, std::vector{2, 1, 3}), + Tensor({3}, element::i64, std::vector{0, 1, 2}), + Tensor({4, 2, 3}, element::f32, std::vector{81.4669, 19.5321, -8.9553, 1.9305, 13.8025, 12.0827, 62.7361, 14.9372, + -33.0825, -75.3226, 20.8033, 20.7660, -20.3640, 54.5372, -54.3023, 94.0773, + 33.0599, 58.1724, 56.4223, -95.3774, 8.8978, 10.4662, 11.7532, -11.7692}), + "roll_3d_input"), + + // roll_3d_input_negative_shift + RollParams( + Tensor({4, 2, 3}, element::f32, std::vector{94.0773, 33.0599, 58.1724, -20.3640, 54.5372, -54.3023, 10.4662, 11.7532, + -11.7692, 56.4223, -95.3774, 8.8978, 1.9305, 13.8025, 12.0827, 81.4669, + 19.5321, -8.9553, -75.3226, 20.8033, 20.7660, 62.7361, 14.9372, -33.0825}), + Tensor({3}, element::i64, std::vector{-5, 1, 3}), + Tensor({3}, element::i64, std::vector{0, 1, 1}), + Tensor({4, 2, 3}, element::f32, std::vector{10.4662, 11.7532, -11.7692, 56.4223, -95.3774, 8.8978, 1.9305, 13.8025, + 12.0827, 81.4669, 19.5321, -8.9553, -75.3226, 20.8033, 20.7660, 62.7361, + 14.9372, -33.0825, 94.0773, 33.0599, 58.1724, -20.3640, 54.5372, -54.3023}), + "roll_3d_input_negative_shift"), + }; + return rollParams; +} + +std::vector generateRollCombinedParams() { + const std::vector> rollTypeParams { + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollParams(), + generateRollFloatingPointParams(), + }; + std::vector combinedParams; + + for (const auto& params : rollTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_Roll_With_Hardcoded_Refs, ReferenceRollLayerTest, + testing::ValuesIn(generateRollCombinedParams()), ReferenceRollLayerTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/shuffle_channels.cpp b/docs/template_plugin/tests/functional/op_reference/shuffle_channels.cpp new file mode 100644 index 00000000000000..1c6c613dba70be --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/shuffle_channels.cpp @@ -0,0 +1,209 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/opsets/opset1.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct ShuffleChannelsParams { + ShuffleChannelsParams(const Tensor& dataTensor, const int32_t axis, const int32_t group, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), axis(axis), group(group), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + int32_t axis; + int32_t group; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceShuffleChannelsLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_axis=" << param.axis; + result << "_group=" << param.group; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_=" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const ShuffleChannelsParams& params) { + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto function = std::make_shared(data, params.axis, params.group); + return std::make_shared(NodeVector {function}, ParameterVector {data}); + } +}; + +TEST_P(ReferenceShuffleChannelsLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + // shuffle_channels_simple + ShuffleChannelsParams( + Tensor({1, 15, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}), + 1, + 5, + Tensor({1, 15, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51, + 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, + 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59}), + "shuffle_channels_simple"), + + // shuffle_channels_negative_axis + ShuffleChannelsParams( + Tensor({15, 2, 1, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}), + -4, + 5, + Tensor({15, 2, 1, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51, + 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, + 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59}), + "shuffle_channels_negative_axis"), + + // shuffle_channels_float + ShuffleChannelsParams( + Tensor({6, 1, 1, 1}, IN_ET, std::vector{0, 1, 2, 3, 4, 5}), + 0, + 2, + Tensor({6, 1, 1, 1}, IN_ET, std::vector{0, 3, 1, 4, 2, 5}), + "shuffle_channels_float"), + + // shuffle_channels_1d + ShuffleChannelsParams( + Tensor({15}, IN_ET, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}), + 0, + 5, + Tensor({15}, IN_ET, std::vector{0, 3, 6, 9, 12, 1, 4, 7, 10, 13, 2, 5, 8, 11, 14}), + "shuffle_channels_1d"), + + // shuffle_channels_2d + ShuffleChannelsParams( + Tensor({15, 4}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}), + 0, + 5, + Tensor({15, 4}, IN_ET, std::vector{ + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, + 39, 48, 49, 50, 51, 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, + 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, 8, 9, 10, 11, 20, + 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59}), + "shuffle_channels_2d"), + + // shuffle_channels_3d + ShuffleChannelsParams( + Tensor({15, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}), + 0, + 5, + Tensor({15, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, + 39, 48, 49, 50, 51, 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, + 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, 8, 9, 10, 11, 20, + 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59}), + "shuffle_channels_3d"), + + // shuffle_channels_5d + ShuffleChannelsParams( + Tensor({2, 2, 15, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}), + 2, + 5, + Tensor({2, 2, 15, 2, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51, + 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, + 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59, + + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51, + 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, + 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59, + + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51, + 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, + 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59, + + 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39, 48, 49, 50, 51, + 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43, 52, 53, 54, 55, + 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47, 56, 57, 58, 59}), + "shuffle_channels_5d"), + }; + return params; +} + +std::vector generateShuffleChannelsCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_ShuffleChannels_With_Hardcoded_Refs, ReferenceShuffleChannelsLayerTest, + testing::ValuesIn(generateShuffleChannelsCombinedParams()), ReferenceShuffleChannelsLayerTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/space_to_batch.cpp b/docs/template_plugin/tests/functional/op_reference/space_to_batch.cpp new file mode 100644 index 00000000000000..42a5c950648734 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/space_to_batch.cpp @@ -0,0 +1,143 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/opsets/opset1.hpp" +#include "openvino/opsets/opset2.hpp" +#include "openvino/op/constant.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct SpaceToBatchParams { + SpaceToBatchParams(const Tensor& dataTensor, const Tensor& blockShapeTensor, + const Tensor& padsBeginTensor, const Tensor& padsEndTensor, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), blockShapeTensor(blockShapeTensor), + padsBeginTensor(padsBeginTensor), padsEndTensor(padsEndTensor), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + Tensor dataTensor; + Tensor blockShapeTensor; + Tensor padsBeginTensor; + Tensor padsEndTensor; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceSpaceToBatchLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_bsType=" << param.blockShapeTensor.type; + result << "_bsShape=" << param.blockShapeTensor.shape; + result << "_pbType=" << param.padsBeginTensor.type; + result << "_pbShape=" << param.padsBeginTensor.shape; + result << "_peType=" << param.padsEndTensor.type; + result << "_peShape=" << param.padsEndTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const SpaceToBatchParams& params) { + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto blockShape = std::make_shared(element::i64, params.blockShapeTensor.shape, params.blockShapeTensor.data.data()); + const auto padsBegin = std::make_shared(element::i64, params.padsBeginTensor.shape, params.padsBeginTensor.data.data()); + const auto padsEnd = std::make_shared(element::i64, params.padsEndTensor.shape, params.padsEndTensor.data.data()); + const auto batchToSpace = std::make_shared(data, blockShape, padsBegin, padsEnd); + return std::make_shared(NodeVector {batchToSpace}, ParameterVector {data}); + } +}; + +TEST_P(ReferenceSpaceToBatchLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector batchToSpaceParams { + // space_to_batch_4D + SpaceToBatchParams( + Tensor({1, 1, 2, 2}, IN_ET, std::vector{1, 1, 1, 1}), + Tensor({4}, element::i64, std::vector{1, 1, 1, 1}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({1, 1, 2, 2}, IN_ET, std::vector{1, 1, 1, 1}), + "space_to_batch_4D"), + + // space_to_batch_5D + SpaceToBatchParams( + Tensor({1, 1, 3, 2, 1}, IN_ET, std::vector{1, 1, 1, 1, 1, 1}), + Tensor({5}, element::i64, std::vector{1, 1, 3, 2, 2}), + Tensor({5}, element::i64, std::vector{0, 0, 1, 0, 3}), + Tensor({5}, element::i64, std::vector{0, 0, 2, 0, 0}), + Tensor({12, 1, 2, 1, 2}, IN_ET, std::vector{ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}), + "space_to_batch_5D"), + + // space_to_batch_4x4 + SpaceToBatchParams( + Tensor({1, 1, 4, 4}, IN_ET, std::vector{ + 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}), + Tensor({4}, element::i64, std::vector{1, 1, 1, 1}), + Tensor({4}, element::i64, std::vector{0, 0, 1, 0}), + Tensor({4}, element::i64, std::vector{0, 0, 0, 0}), + Tensor({1, 1, 5, 4}, IN_ET, std::vector{ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}), + "space_to_batch_4x4"), + }; + return batchToSpaceParams; +} + +std::vector generateCombinedParams() { + const std::vector> batchToSpaceTypeParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : batchToSpaceTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_SpaceToBatch_With_Hardcoded_Refs, ReferenceSpaceToBatchLayerTest, + testing::ValuesIn(generateCombinedParams()), ReferenceSpaceToBatchLayerTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/space_to_depth.cpp b/docs/template_plugin/tests/functional/op_reference/space_to_depth.cpp new file mode 100644 index 00000000000000..b834fbeee7d243 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/space_to_depth.cpp @@ -0,0 +1,169 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/opsets/opset1.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct SpaceToDepthParams { + SpaceToDepthParams(const Tensor& dataTensor, const std::string mode, const int32_t blockSize, + const Tensor& expectedTensor, const std::string& testcaseName = "") : + dataTensor(dataTensor), mode(mode), blockSize(blockSize), expectedTensor(expectedTensor), + testcaseName(testcaseName) {} + + Tensor dataTensor; + std::string mode; + int32_t blockSize; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceSpaceToDepthLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.dataTensor.data}; + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const SpaceToDepthParams& params) { + opset1::SpaceToDepth::SpaceToDepthMode mode = params.mode == "DEPTH_FIRST" ? + opset1::SpaceToDepth::SpaceToDepthMode::DEPTH_FIRST : opset1::SpaceToDepth::SpaceToDepthMode::BLOCKS_FIRST; + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto SpaceToDepth = std::make_shared(data, mode, params.blockSize); + return std::make_shared(NodeVector {SpaceToDepth}, ParameterVector {data}); + } +}; + +TEST_P(ReferenceSpaceToDepthLayerTest, CompareWithRefs) { + Exec(); +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + // space_to_depth_block_first_K2_BS2 + SpaceToDepthParams( + Tensor({1, 2, 4, 4}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}), + "BLOCKS_FIRST", + 2, + Tensor({1, 8, 2, 2}, IN_ET, std::vector{ + 0, 2, 8, 10, 16, 18, 24, 26, 1, 3, 9, 11, 17, 19, 25, 27, + 4, 6, 12, 14, 20, 22, 28, 30, 5, 7, 13, 15, 21, 23, 29, 31}), + "space_to_depth_block_first_K2_BS2"), + + // space_to_depth_block_first_K2_BS3 + SpaceToDepthParams( + Tensor({1, 2, 6, 3}, IN_ET, std::vector{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 1, 5, 9, + 13, 17, 21, 25, 29, 33, 2, 6, 10, 14, 18, 22, + 26, 30, 34, 3, 7, 11, 15, 19, 23, 27, 31, 35}), + "BLOCKS_FIRST", + 3, + Tensor({1, 18, 2, 1}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}), + "space_to_depth_block_first_K2_BS3"), + + // space_to_depth_block_first_K1_BS3 + SpaceToDepthParams( + Tensor({1, 2, 6}, IN_ET, std::vector{ + 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11}), + "BLOCKS_FIRST", + 3, + Tensor({1, 6, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), + "space_to_depth_block_first_K1_BS3"), + + // space_to_depth_depth_first_K2_BS2 + SpaceToDepthParams( + Tensor({1, 2, 4, 4}, IN_ET, std::vector{ + 0, 16, 2, 18, 1, 17, 3, 19, 8, 24, 10, + 26, 9, 25, 11, 27, 4, 20, 6, 22, 5, 21, + 7, 23, 12, 28, 14, 30, 13, 29, 15, 31}), + "DEPTH_FIRST", + 2, + Tensor({1, 8, 2, 2}, IN_ET, std::vector{ + 0, 2, 8, 10, 16, 18, 24, 26, 1, 3, 9, 11, 17, 19, 25, 27, + 4, 6, 12, 14, 20, 22, 28, 30, 5, 7, 13, 15, 21, 23, 29, 31}), + "space_to_depth_depth_first_K2_BS2"), + + // space_to_depth_depth_first_K2_BS3 + SpaceToDepthParams( + Tensor({1, 2, 6, 3}, IN_ET, std::vector{ + 0, 2, 4, 6, 8, 10, 12, 14, 16, 1, 3, 5, + 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 28, + 30, 32, 34, 19, 21, 23, 25, 27, 29, 31, 33, 35}), + "DEPTH_FIRST", + 3, + Tensor({1, 18, 2, 1}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}), + "space_to_depth_depth_first_K2_BS3"), + + // space_to_depth_depth_first_K1_BS3 + SpaceToDepthParams( + Tensor({1, 2, 6}, IN_ET, std::vector{ + 0, 2, 4, 1, 3, 5, 6, 8, 10, 7, 9, 11}), + "DEPTH_FIRST", + 3, + Tensor({1, 6, 2}, IN_ET, std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}), + "space_to_depth_depth_first_K1_BS3"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_SpaceToDepth_With_Hardcoded_Refs, ReferenceSpaceToDepthLayerTest, + testing::ValuesIn(generateCombinedParams()), ReferenceSpaceToDepthLayerTest::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/op_reference/strided_slice.cpp b/docs/template_plugin/tests/functional/op_reference/strided_slice.cpp new file mode 100644 index 00000000000000..4e9d6b0ef6c640 --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/strided_slice.cpp @@ -0,0 +1,424 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "openvino/op/strided_slice.hpp" +#include "openvino/op/constant.hpp" +#include "base_reference_test.hpp" + +using namespace reference_tests; +using namespace ov; + +namespace { +struct StridedSliceParams { + StridedSliceParams(const PartialShape& dynamicDataShape, + const Tensor& dataTensor, + const Tensor& beginTensor, + const Tensor& endTensor, + const Tensor& stridesTensor, + const std::vector& beginMask, + const std::vector& endMask, + const std::vector& newAxisMask, + const std::vector& shrinkAxisMask, + const std::vector& ellipsisMask, + const Tensor& expectedTensor, + const std::string& testcaseName = "") : + dynamicDataShape(dynamicDataShape), dataTensor(dataTensor), + beginTensor(beginTensor), endTensor(endTensor), + stridesTensor(stridesTensor), beginMask(beginMask), endMask(endMask), + newAxisMask(newAxisMask), shrinkAxisMask(shrinkAxisMask), ellipsisMask(ellipsisMask), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + PartialShape dynamicDataShape; + Tensor dataTensor; + Tensor beginTensor; + Tensor endTensor; + Tensor stridesTensor; + std::vector beginMask; + std::vector endMask; + std::vector newAxisMask; + std::vector shrinkAxisMask; + std::vector ellipsisMask; + Tensor expectedTensor; + std::string testcaseName; +}; + +struct StridedSliceStrideOptionalParams { + StridedSliceStrideOptionalParams(const PartialShape& dynamicDataShape, + const Tensor& dataTensor, + const Tensor& beginTensor, + const Tensor& endTensor, + const std::vector& beginMask, + const std::vector& endMask, + const std::vector& newAxisMask, + const std::vector& shrinkAxisMask, + const std::vector& ellipsisMask, + const Tensor& expectedTensor, + const std::string& testcaseName = "") : + dynamicDataShape(dynamicDataShape), dataTensor(dataTensor), + beginTensor(beginTensor), endTensor(endTensor), + beginMask(beginMask), endMask(endMask), + newAxisMask(newAxisMask), shrinkAxisMask(shrinkAxisMask), ellipsisMask(ellipsisMask), + expectedTensor(expectedTensor), testcaseName(testcaseName) {} + + PartialShape dynamicDataShape; + Tensor dataTensor; + Tensor beginTensor; + Tensor endTensor; + std::vector beginMask; + std::vector endMask; + std::vector newAxisMask; + std::vector shrinkAxisMask; + std::vector ellipsisMask; + Tensor expectedTensor; + std::string testcaseName; +}; + +class ReferenceStridedSliceLayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + if (params.dynamicDataShape.is_static()) { + inputData = {params.dataTensor.data}; + } else { + inputData = {params.dataTensor.data, params.beginTensor.data, params.endTensor.data, params.stridesTensor.data}; + } + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "ddShape=" << param.dynamicDataShape; + result << "_dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_bType=" << param.beginTensor.type; + result << "_bShape=" << param.beginTensor.shape; + result << "_eType=" << param.endTensor.type; + result << "_eShape=" << param.endTensor.shape; + result << "_sType=" << param.stridesTensor.type; + result << "_sShape=" << param.stridesTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const StridedSliceParams& params) { + std::shared_ptr function; + if (params.dynamicDataShape.is_static()) { + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto beginOp = std::make_shared(params.beginTensor.type, params.beginTensor.shape, + params.beginTensor.data.data()); + const auto endOp = std::make_shared(params.endTensor.type, params.endTensor.shape, + params.endTensor.data.data()); + const auto stridesOp = std::make_shared(params.stridesTensor.type, params.stridesTensor.shape, + params.stridesTensor.data.data()); + const auto StridedSlice = std::make_shared(data, beginOp, endOp, stridesOp, + params.beginMask, params.endMask, params.newAxisMask, + params.shrinkAxisMask, params.ellipsisMask); + function = std::make_shared(NodeVector{StridedSlice}, ParameterVector{data}); + } else { + const auto data = std::make_shared(params.dataTensor.type, PartialShape::dynamic()); + const auto beginOp = std::make_shared(params.beginTensor.type, params.beginTensor.shape); + const auto endOp = std::make_shared(params.endTensor.type, params.endTensor.shape); + const auto stridesOp = std::make_shared(params.stridesTensor.type, params.stridesTensor.shape); + const auto StridedSlice = std::make_shared(data, beginOp, endOp, stridesOp, + params.beginMask, params.endMask, params.newAxisMask, + params.shrinkAxisMask, params.ellipsisMask); + function = std::make_shared(NodeVector{StridedSlice}, ParameterVector{data, beginOp, endOp, stridesOp}); + } + return function; + } +}; + +class ReferenceStridedSliceLayerTestStrideOptional : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + if (params.dynamicDataShape.is_static()) { + inputData = {params.dataTensor.data}; + } else { + inputData = {params.dataTensor.data, params.beginTensor.data, params.endTensor.data}; + } + refOutData = {params.expectedTensor.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + auto param = obj.param; + std::ostringstream result; + result << "ddShape=" << param.dynamicDataShape; + result << "_dType=" << param.dataTensor.type; + result << "_dShape=" << param.dataTensor.shape; + result << "_bType=" << param.beginTensor.type; + result << "_bShape=" << param.beginTensor.shape; + result << "_eType=" << param.endTensor.type; + result << "_eShape=" << param.endTensor.shape; + result << "_eType=" << param.expectedTensor.type; + if (param.testcaseName != "") { + result << "_eShape=" << param.expectedTensor.shape; + result << "_" << param.testcaseName; + } else { + result << "_eShape=" << param.expectedTensor.shape; + } + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const StridedSliceStrideOptionalParams& params) { + std::shared_ptr function; + if (params.dynamicDataShape.is_static()) { + const auto data = std::make_shared(params.dataTensor.type, params.dataTensor.shape); + const auto beginOp = std::make_shared(params.beginTensor.type, params.beginTensor.shape, + params.beginTensor.data.data()); + const auto endOp = std::make_shared(params.endTensor.type, params.endTensor.shape, + params.endTensor.data.data()); + const auto StridedSlice = std::make_shared(data, beginOp, endOp, + params.beginMask, params.endMask, params.newAxisMask, + params.shrinkAxisMask, params.ellipsisMask); + function = std::make_shared(NodeVector{StridedSlice}, ParameterVector{data}); + } else { + const auto data = std::make_shared(params.dataTensor.type, PartialShape::dynamic()); + const auto beginOp = std::make_shared(params.beginTensor.type, params.beginTensor.shape); + const auto endOp = std::make_shared(params.endTensor.type, params.endTensor.shape); + const auto StridedSlice = std::make_shared(data, beginOp, endOp, + params.beginMask, params.endMask, params.newAxisMask, + params.shrinkAxisMask, params.ellipsisMask); + function = std::make_shared(NodeVector{StridedSlice}, ParameterVector{data, beginOp, endOp}); + } + return function; + } +}; + +TEST_P(ReferenceStridedSliceLayerTest, CompareWithRefs) { + Exec(); +} + +TEST_P(ReferenceStridedSliceLayerTestStrideOptional, CompareWithRefs) { + Exec(); +} + +template +std::vector generateInputValues(const Shape& input_shape, T initial) { + std::vector input_values(shape_size(input_shape)); + std::iota(input_values.begin(), input_values.end(), static_cast(initial)); + return input_values; +} + +template +std::vector generateSmallParams() { + using T = typename element_type_traits::value_type; + std::vector params { + // strided_slice_0 + StridedSliceParams( + {}, + Tensor(IN_ET, {2, 3, 4}, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + Tensor(element::i64, {2}, std::vector{1, 0}), + Tensor(element::i64, {2}, std::vector{0, 0}), + Tensor(element::i64, {2}, std::vector{1, 1}), + std::vector{0, 0, 0}, + std::vector{0, 0, 0}, + std::vector{0, 1, 0}, + std::vector{1, 0, 0}, + std::vector{0, 0, 0}, + Tensor(IN_ET, {1, 3, 4}, std::vector{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + "strided_slice_0"), + // strided_slice_0_dynamic + StridedSliceParams( + PartialShape::dynamic(), + Tensor(IN_ET, {2, 3, 4}, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + Tensor(element::i64, {2}, std::vector{1, 0}), + Tensor(element::i64, {2}, std::vector{0, 0}), + Tensor(element::i64, {2}, std::vector{1, 1}), + std::vector{0, 0, 0}, + std::vector{0, 0, 0}, + std::vector{0, 1, 0}, + std::vector{1, 0, 0}, + std::vector{0, 0, 0}, + Tensor(IN_ET, {1, 3, 4}, std::vector{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + "strided_slice_0_dynamic"), + }; + return params; +} + +template +std::vector generateParams() { + using T = typename element_type_traits::value_type; + std::vector params { + // strided_slice_0 + StridedSliceParams( + {}, + Tensor(IN_ET, {2, 3, 4}, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + Tensor(element::i64, {2}, std::vector{1, 0}), + Tensor(element::i64, {2}, std::vector{0, 0}), + Tensor(element::i64, {2}, std::vector{1, 1}), + std::vector{0, 0, 0}, + std::vector{0, 0, 0}, + std::vector{0, 1, 0}, + std::vector{1, 0, 0}, + std::vector{0, 0, 0}, + Tensor(IN_ET, {1, 3, 4}, std::vector{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + "strided_slice_0"), + // strided_slice_0_dynamic + StridedSliceParams( + PartialShape::dynamic(), + Tensor(IN_ET, {2, 3, 4}, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + Tensor(element::i64, {2}, std::vector{1, 0}), + Tensor(element::i64, {2}, std::vector{0, 0}), + Tensor(element::i64, {2}, std::vector{1, 1}), + std::vector{0, 0, 0}, + std::vector{0, 0, 0}, + std::vector{0, 1, 0}, + std::vector{1, 0, 0}, + std::vector{0, 0, 0}, + Tensor(IN_ET, {1, 3, 4}, std::vector{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + "strided_slice_0_dynamic"), + // strided_slice_1 + StridedSliceParams( + {}, + Tensor(IN_ET, {2, 4, 6, 8, 2, 2, 2}, generateInputValues({2, 4, 6, 8, 2, 2, 2}, 0)), + Tensor(element::i64, {7}, std::vector{0, 0, 2, 7, 0, 0, 1}), + Tensor(element::i64, {7}, std::vector{0, 4, 6, 3, 0, 0, 0}), + Tensor(element::i64, {7}, std::vector{1, 1, 2, -2, 1, 1, 1}), + std::vector{0, 1, 0, 0, 0, 0, 0}, + std::vector{1, 0, 0, 0, 0, 0, 0}, + std::vector{0, 0, 0, 0, 1, 0, 0}, + std::vector{0, 0, 0, 0, 0, 0, 1}, + std::vector{0, 0, 0, 0, 0, 1, 0}, + Tensor(IN_ET, {2, 4, 2, 2, 1, 2, 2}, std::vector{ + 185, 187, 189, 191, 169, 171, 173, 175, 313, 315, 317, 319, 297, 299, 301, + 303, 569, 571, 573, 575, 553, 555, 557, 559, 697, 699, 701, 703, 681, 683, + 685, 687, 953, 955, 957, 959, 937, 939, 941, 943, 1081, 1083, 1085, 1087, 1065, + 1067, 1069, 1071, 1337, 1339, 1341, 1343, 1321, 1323, 1325, 1327, 1465, 1467, 1469, 1471, + 1449, 1451, 1453, 1455, 1721, 1723, 1725, 1727, 1705, 1707, 1709, 1711, 1849, 1851, 1853, + 1855, 1833, 1835, 1837, 1839, 2105, 2107, 2109, 2111, 2089, 2091, 2093, 2095, 2233, 2235, + 2237, 2239, 2217, 2219, 2221, 2223, 2489, 2491, 2493, 2495, 2473, 2475, 2477, 2479, 2617, + 2619, 2621, 2623, 2601, 2603, 2605, 2607, 2873, 2875, 2877, 2879, 2857, 2859, 2861, 2863, + 3001, 3003, 3005, 3007, 2985, 2987, 2989, 2991}), + "strided_slice_1"), + // strided_slice_1_dynamic + StridedSliceParams( + PartialShape::dynamic(), + Tensor(IN_ET, {2, 4, 6, 8, 2, 2, 2}, generateInputValues({2, 4, 6, 8, 2, 2, 2}, 0)), + Tensor(element::i64, {7}, std::vector{0, 0, 2, 7, 0, 0, 1}), + Tensor(element::i64, {7}, std::vector{0, 4, 6, 3, 0, 0, 0}), + Tensor(element::i64, {7}, std::vector{1, 1, 2, -2, 1, 1, 1}), + std::vector{0, 1, 0, 0, 0, 0, 0}, + std::vector{1, 0, 0, 0, 0, 0, 0}, + std::vector{0, 0, 0, 0, 1, 0, 0}, + std::vector{0, 0, 0, 0, 0, 0, 1}, + std::vector{0, 0, 0, 0, 0, 1, 0}, + Tensor(IN_ET, {2, 4, 2, 2, 1, 2, 2}, std::vector{ + 185, 187, 189, 191, 169, 171, 173, 175, 313, 315, 317, 319, 297, 299, 301, + 303, 569, 571, 573, 575, 553, 555, 557, 559, 697, 699, 701, 703, 681, 683, + 685, 687, 953, 955, 957, 959, 937, 939, 941, 943, 1081, 1083, 1085, 1087, 1065, + 1067, 1069, 1071, 1337, 1339, 1341, 1343, 1321, 1323, 1325, 1327, 1465, 1467, 1469, 1471, + 1449, 1451, 1453, 1455, 1721, 1723, 1725, 1727, 1705, 1707, 1709, 1711, 1849, 1851, 1853, + 1855, 1833, 1835, 1837, 1839, 2105, 2107, 2109, 2111, 2089, 2091, 2093, 2095, 2233, 2235, + 2237, 2239, 2217, 2219, 2221, 2223, 2489, 2491, 2493, 2495, 2473, 2475, 2477, 2479, 2617, + 2619, 2621, 2623, 2601, 2603, 2605, 2607, 2873, 2875, 2877, 2879, 2857, 2859, 2861, 2863, + 3001, 3003, 3005, 3007, 2985, 2987, 2989, 2991}), + "strided_slice_1_dynamic"), + }; + return params; +} + +template +std::vector generateStrideOptionalParams() { + using T = typename element_type_traits::value_type; + std::vector params { + // strided_slice_stride_optional + StridedSliceStrideOptionalParams( + {}, + Tensor(IN_ET, {2, 3, 4}, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + Tensor(element::i64, {3}, std::vector{-1, -1, 0}), + Tensor(element::i64, {3}, std::vector{0, 0, 0}), + std::vector{0, 0, 0}, + std::vector{0, 0, 0}, + std::vector{0, 0, 1}, + std::vector{1, 1, 0}, + std::vector{0, 0, 0}, + Tensor(IN_ET, {1, 4}, std::vector{20, 21, 22, 23}), + "strided_slice_stride_optional"), + // strided_slice_stride_optional_dynamic + StridedSliceStrideOptionalParams( + PartialShape::dynamic(), + Tensor(IN_ET, {2, 3, 4}, std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}), + Tensor(element::i64, {3}, std::vector{-1, -1, 0}), + Tensor(element::i64, {3}, std::vector{0, 0, 0}), + std::vector{0, 0, 0}, + std::vector{0, 0, 0}, + std::vector{0, 0, 1}, + std::vector{1, 1, 0}, + std::vector{0, 0, 0}, + Tensor(IN_ET, {1, 4}, std::vector{20, 21, 22, 23}), + "strided_slice_stride_optional_dynamic"), + }; + return params; +} + +std::vector generateCombinedParams() { + const std::vector> generatedParams { + generateSmallParams(), + generateParams(), + generateParams(), + generateParams(), + generateSmallParams(), + generateParams(), + generateParams(), + generateParams(), + generateSmallParams(), + generateSmallParams(), + generateParams(), + generateParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +std::vector generateCombinedStrideOptionalParams() { + const std::vector> generatedParams { + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + generateStrideOptionalParams(), + }; + std::vector combinedParams; + + for (const auto& params : generatedParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +INSTANTIATE_TEST_SUITE_P(smoke_StridedSlice_With_Hardcoded_Refs, ReferenceStridedSliceLayerTest, + testing::ValuesIn(generateCombinedParams()), ReferenceStridedSliceLayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_StridedSlice_With_Hardcoded_Refs, ReferenceStridedSliceLayerTestStrideOptional, + testing::ValuesIn(generateCombinedStrideOptionalParams()), ReferenceStridedSliceLayerTestStrideOptional::getTestCaseName); +} // namespace \ No newline at end of file diff --git a/docs/template_plugin/tests/functional/shared_tests_instances/hetero/synthetic.cpp b/docs/template_plugin/tests/functional/shared_tests_instances/hetero/synthetic.cpp index 17f14d66277bfd..be09f97667176c 100644 --- a/docs/template_plugin/tests/functional/shared_tests_instances/hetero/synthetic.cpp +++ b/docs/template_plugin/tests/functional/shared_tests_instances/hetero/synthetic.cpp @@ -11,6 +11,9 @@ namespace { using namespace HeteroTests; +// this tests load plugin by library name: this is not available during static linkage +#ifndef OPENVINO_STATIC_LIBRARY + INSTANTIATE_TEST_SUITE_P(smoke_SingleMajorNode, HeteroSyntheticTest, ::testing::Combine( ::testing::Values(std::vector{{"TEMPLATE0", "templatePlugin"}, {"TEMPLATE1", "templatePlugin"}}), @@ -69,4 +72,6 @@ INSTANTIATE_TEST_SUITE_P(nightly_RandomMajorNodes_dynamic_batch, HeteroSynthetic dynamicBuilders, true))), HeteroSyntheticTest::getTestCaseName); +#endif // !OPENVINO_STATIC_LIBRARY + } // namespace diff --git a/docs/template_plugin/tests/functional/skip_tests_config.cpp b/docs/template_plugin/tests/functional/skip_tests_config.cpp index fe8a939820bfe5..310aba60f53a45 100644 --- a/docs/template_plugin/tests/functional/skip_tests_config.cpp +++ b/docs/template_plugin/tests/functional/skip_tests_config.cpp @@ -59,6 +59,35 @@ std::vector disabledTestPatterns() { R"(.*ReferenceExperimentalGPLayerTest.*bf16.*)", // CVS-64105 R"(.*ReferenceGatherElementsTestNegative.*)", + // CVS-64052 + R"(.*ReferenceStridedSliceLayerTest.*strided_slice_stride_optional_dynamic)", + // CVS-64017 + R"(.*ReferenceGatherTest.*dType=i16.*)", + R"(.*ReferenceGatherTest.*dType=u16.*)", + R"(.*ReferenceGatherTest.*dType=bf16.*)", + R"(.*ReferenceGatherTest.*dType=f64.*)", + // CVS-64110 + R"(.*ReferenceGatherTestV7.*dType=i16.*)", + R"(.*ReferenceGatherTestV7.*dType=u16.*)", + R"(.*ReferenceGatherTestV7.*dType=bf16.*)", + R"(.*ReferenceGatherTestV7.*dType=f64.*)", + // CVS-64037 + R"(.*ReferencePadTest.*pad_exterior_2d_0x0)", + R"(.*ReferencePadTest.*pad_exterior_2d_0x3)", + R"(.*ReferencePadTest.*pad_exterior_2d_3x0)", + // CVS-70975 + R"(.*ReferencePadTestParamsTooLarge.*)", + // CVS-64006 + R"(.*ReferenceBatchToSpaceLayerTest.*dType=i4.*)", + R"(.*ReferenceBatchToSpaceLayerTest.*dType=u4.*)", + // CVS-64113 + R"(.*ReferenceRollLayerTest.*dType=i4.*)", + R"(.*ReferenceRollLayerTest.*dType=u4.*)", + // CVS-64050 + R"(.*ReferenceSpaceToBatchLayerTest.*dType=i4.*)", + R"(.*ReferenceSpaceToBatchLayerTest.*dType=u4.*)", + // CVS-64066 + R"(.*ReferenceGRUCellTestHardsigmoidActivationFunction.*gru_cell_hardsigmoid_activation_function)", }; #ifdef _WIN32 diff --git a/docs/template_plugin/tests/functional/subgraph_reference/preprocess.cpp b/docs/template_plugin/tests/functional/subgraph_reference/preprocess.cpp index 4ee210dab8d501..8ed19e49a89146 100644 --- a/docs/template_plugin/tests/functional/subgraph_reference/preprocess.cpp +++ b/docs/template_plugin/tests/functional/subgraph_reference/preprocess.cpp @@ -97,7 +97,7 @@ static RefPreprocessParams simple_mean_scale() { RefPreprocessParams res("simple_mean_scale"); res.function = []() { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().mean(1.f).scale(2.f))).build(f); + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().mean(1.f).scale(2.f))).build(); return f; }; res.inputs.emplace_back(Shape{1, 3, 2, 2}, element::f32, std::vector{1., 3., 5., 7., 9., 11., 13., 15., 17., 19., 21., 23.}); @@ -109,7 +109,7 @@ static RefPreprocessParams scale_then_mean() { RefPreprocessParams res("scale_then_mean"); res.function = []() { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().scale(2.0f).mean(2.0f))).build(f); + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().scale(2.0f).mean(2.0f))).build(); return f; }; @@ -122,14 +122,14 @@ static RefPreprocessParams convert_only() { RefPreprocessParams res("convert_only"); res.function = []() { auto f = create_simple_function(element::f32, Shape{1, 1, 2, 2}); - f = PrePostProcessor().input(InputInfo() + f = PrePostProcessor(f).input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::i16)) .preprocess(PreProcessSteps() .convert_element_type(element::f32) .scale(3.f) .convert_element_type(element::u8) .convert_element_type(element::f32))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 1, 2, 2}, element::i16, std::vector{2, 3, 4, 5}); @@ -141,14 +141,14 @@ static RefPreprocessParams convert_element_type_and_scale() { RefPreprocessParams res("convert_element_type_and_scale"); res.function = []() { auto f = create_simple_function(element::u8, Shape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::i16)) .preprocess(PreProcessSteps() .convert_element_type(element::f32) .scale(2.f) .convert_element_type(element::u8))) - .build(f); + .build(); return f; }; @@ -163,11 +163,11 @@ static RefPreprocessParams tensor_element_type_and_scale() { RefPreprocessParams res("tensor_element_type_and_scale"); res.function = []() { auto f = create_simple_function(element::i8, Shape{1, 3, 1, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::f32)) .preprocess(PreProcessSteps().scale(2.0f).convert_element_type(element::i8))) - .build(f); + .build(); return f; }; @@ -180,13 +180,13 @@ static RefPreprocessParams custom_preprocessing() { RefPreprocessParams res("custom_preprocessing"); res.function = []() { auto f = create_simple_function(element::i32, Shape{1, 3, 1, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess(PreProcessSteps().custom([](const Output& node) { auto abs = std::make_shared(node); abs->set_friendly_name(node.get_node_shared_ptr()->get_friendly_name() + "/abs"); return abs; }))) - .build(f); + .build(); return f; }; @@ -199,7 +199,7 @@ static RefPreprocessParams test_lvalue() { RefPreprocessParams res("test_lvalue"); res.function = []() { auto f = create_simple_function(element::i8, Shape{1, 3, 1, 1}); - auto p = PrePostProcessor(); + auto p = PrePostProcessor(f); auto p1 = std::move(p); p = std::move(p1); auto inputInfo = InputInfo(); @@ -230,7 +230,7 @@ static RefPreprocessParams test_lvalue() { inputInfo.preprocess(std::move(same)); } p.input(std::move(inputInfo)); - f = p.build(f); + f = p.build(); return f; }; @@ -243,7 +243,7 @@ static RefPreprocessParams test_2_inputs_basic() { RefPreprocessParams res("test_2_inputs_basic"); res.function = []() { auto f = create_2inputs(element::f32, Shape{1, 3, 1, 1}); - f = PrePostProcessor().input(InputInfo(0) + f = PrePostProcessor(f).input(InputInfo(0) .preprocess( PreProcessSteps() .mean(1.f))) @@ -252,7 +252,7 @@ static RefPreprocessParams test_2_inputs_basic() { .preprocess(PreProcessSteps() .mean(1.f) .scale(2.0f))) - .build(f); + .build(); return f; }; @@ -267,11 +267,11 @@ static RefPreprocessParams mean_scale_vector_tensor_layout() { RefPreprocessParams res("mean_scale_vector_tensor_layout"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 3, 2, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NC??")) .preprocess(PreProcessSteps().mean({1.f, 2.f, 3.f}).scale({2.f, 3.f, 4.f}))) - .build(f); + .build(); return f; }; @@ -284,11 +284,11 @@ static RefPreprocessParams mean_scale_dynamic_layout() { RefPreprocessParams res("mean_scale_dynamic_layout"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 2, 1, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("N...C")) .preprocess(PreProcessSteps().mean({1.f, 2.f, 3.f}).scale({2.f, 3.f, 4.f}))) - .build(f); + .build(); return f; }; @@ -301,13 +301,13 @@ static RefPreprocessParams resize_to_network_height() { RefPreprocessParams res("resize_to_network_height"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 2, 1, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_dynamic_shape()) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NHWC")) ) - .build(f); + .build(); return f; }; res.inputs.emplace_back(element::f32, Shape{1, 4, 1, 1}, std::vector{0., 2., 4., 6.}); @@ -319,12 +319,12 @@ static RefPreprocessParams resize_to_network_width() { RefPreprocessParams res("resize_to_network_width"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 1, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_dynamic_shape()) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(element::f32, Shape{1, 1, 2, 6}, std::vector{0., 1., 2., 3., 4., 5., @@ -339,12 +339,12 @@ static RefPreprocessParams resize_from_spatial_dims() { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 1, 1, 1}); auto t = InputTensorInfo(); t.set_spatial_static_shape(1, 4); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(std::move(t)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_CUBIC)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(element::f32, Shape{1, 1, 1, 7}, std::vector{0., 0.25, 1., 2.25, 4., 6.25, 9}); @@ -356,13 +356,13 @@ static RefPreprocessParams resize_i8() { RefPreprocessParams res("resize_i8"); res.function = []() { auto f = create_simple_function(element::i8, PartialShape{1, 3, 1, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo() .set_spatial_dynamic_shape()) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(element::i8, Shape{1, 3, 2, 2}, std::vector{0, 0, 0, 0, @@ -376,12 +376,12 @@ static RefPreprocessParams resize_to_network_width_height() { RefPreprocessParams res("resize_to_network_width_height"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 1, 4, 4}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(5, 5)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_NEAREST)) .network(InputNetworkInfo().set_layout("...HW"))) - .build(f); + .build(); return f; }; @@ -406,12 +406,12 @@ static RefPreprocessParams resize_to_specified_width_height() { RefPreprocessParams res("resize_to_specified_width_height"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 1, Dimension::dynamic(), Dimension::dynamic()}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_dynamic_shape()) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_NEAREST, 4, 4)) .network(InputNetworkInfo().set_layout("...HW"))) - .build(f); + .build(); return f; }; @@ -448,9 +448,9 @@ static RefPreprocessParams resize_lvalues() { i.tensor(std::move(t)); i.preprocess(std::move(s)); i.network(std::move(n)); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(std::move(i)) - .build(f); + .build(); return f; }; // clang-format off @@ -473,11 +473,11 @@ static RefPreprocessParams convert_layout_nhwc_to_nchw_lvalue() { auto p = PreProcessSteps(); p.convert_layout("NCHW"); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NHWC")) .preprocess(std::move(p))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 2, 2, 3}, element::u8, std::vector{1, 2, 3, // [H=0, W=0, RGB] @@ -497,11 +497,11 @@ static RefPreprocessParams convert_layout_nhwc_to_net_no_tensor_shape() { f->get_parameters()[0]->set_layout("NCHW"); auto p = PreProcessSteps(); p.convert_layout(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NHWC")) .preprocess(std::move(p))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 2, 2, 3}, element::u8, std::vector{1, 2, 3, // [H=0, W=0, RGB] @@ -518,10 +518,10 @@ static RefPreprocessParams convert_layout_by_dims() { RefPreprocessParams res("convert_layout_by_dims"); res.function = []() { auto f = create_simple_function(element::u8, {1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .preprocess(PreProcessSteps().convert_layout({0, 3, 1, 2}))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 2, 2, 3}, element::u8, std::vector{1, 2, 3, // [H=0, W=0, RGB] @@ -541,9 +541,9 @@ static RefPreprocessParams convert_layout_by_dims_multi() { auto p = PreProcessSteps(); p.convert_layout({0, 1, 3, 2}); // NHWC->NHCW p.convert_layout({0, 2, 1, 3}); // NHCW->NCHW - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess(std::move(p))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 2, 2, 3}, element::f32, std::vector{1, 2, 3, // [H=0, W=0] @@ -564,10 +564,10 @@ static RefPreprocessParams convert_layout_by_dims_multi_layout() { p.convert_layout({0, 1, 3, 2}); // NHWC->NHCW p.mean({1, 2, 2}); // Apply means to 'C' channel p.convert_layout({0, 2, 1, 3}); // NHCW->NCHW - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().tensor(InputTensorInfo().set_layout("N??C")) .preprocess(std::move(p))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 2, 2, 3}, element::f32, std::vector{1, 2, 3, // [H=0, W=0, RGB] @@ -584,7 +584,7 @@ static RefPreprocessParams resize_and_convert_layout() { RefPreprocessParams res("resize_and_convert_layout"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 2, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo() .set_layout("NCHW") @@ -593,7 +593,7 @@ static RefPreprocessParams resize_and_convert_layout() { .resize(ResizeAlgorithm::RESIZE_LINEAR) .convert_layout()) .network(InputNetworkInfo().set_layout("NHWC"))) - .build(f); + .build(); return f; }; @@ -622,13 +622,13 @@ static RefPreprocessParams convert_color_nv12_to_bgr_two_planes() { res.rel_threshold = 1.f; // Ignore relative pixel values comparison (100%) res.function = []() { auto f = create_simple_function(element::u8, PartialShape{1, 4, 4, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo() .set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess(PreProcessSteps() .convert_color(ColorFormat::BGR))) - .build(f); + .build(); return f; }; @@ -661,13 +661,13 @@ static RefPreprocessParams convert_color_nv12_single_plane() { res.rel_threshold = 1.f; // Ignore relative pixel values comparison (100%) res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 4, 4, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo() .set_color_format(ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps() .convert_color(ColorFormat::RGB))) - .build(f); + .build(); return f; }; @@ -696,7 +696,7 @@ static RefPreprocessParams convert_color_nv12_layout_resize() { res.rel_threshold = 1.f; // Ignore relative pixel values comparison (100%) res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo() .set_color_format(ColorFormat::NV12_SINGLE_PLANE) @@ -708,7 +708,7 @@ static RefPreprocessParams convert_color_nv12_layout_resize() { .convert_element_type(element::f32) .resize(ResizeAlgorithm::RESIZE_NEAREST)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(f); + .build(); return f; }; @@ -736,7 +736,7 @@ static RefPreprocessParams element_type_before_convert_color_nv12() { res.rel_threshold = 1.f; // Ignore relative pixel values comparison (100%) res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 2, 2, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo() .set_element_type(element::u8) @@ -745,7 +745,7 @@ static RefPreprocessParams element_type_before_convert_color_nv12() { .convert_element_type(element::f32) .convert_color(ColorFormat::RGB)) .network(InputNetworkInfo().set_layout("NHWC"))) - .build(f); + .build(); return f; }; @@ -767,7 +767,7 @@ static RefPreprocessParams postprocess_2_inputs_basic() { RefPreprocessParams res("postprocess_2_inputs_basic"); res.function = []() { auto f = create_2inputs(element::f32, Shape{1, 3, 1, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo("tensor_output1") .network(OutputNetworkInfo().set_layout("NCHW")) .postprocess(PostProcessSteps().convert_layout()) @@ -775,7 +775,7 @@ static RefPreprocessParams postprocess_2_inputs_basic() { .output(OutputInfo("tensor_output2") .postprocess(PostProcessSteps().convert_element_type()) .tensor(OutputTensorInfo().set_element_type(element::u8))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 3, 1, 2}, element::f32, std::vector{1.1, 2.1, 3.1, 4.1, 5.1, 6.1}); @@ -789,10 +789,10 @@ static RefPreprocessParams post_convert_layout_by_dims() { RefPreprocessParams res("post_convert_layout_by_dims"); res.function = []() { auto f = create_simple_function(element::u8, {1, 2, 2, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo() .postprocess(PostProcessSteps().convert_layout({0, 3, 1, 2}))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 2, 2, 3}, element::u8, std::vector{1, 2, 3, // [H=0, W=0, RGB] @@ -812,9 +812,9 @@ static RefPreprocessParams post_convert_layout_by_dims_multi() { auto p = PostProcessSteps(); p.convert_layout({0, 1, 3, 2}); // NHWC->NHCW p.convert_layout({0, 2, 1, 3}); // NHCW->NCHW - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo().postprocess(std::move(p))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 2, 2, 3}, element::f32, std::vector{1, 2, 3, // [H=0, W=0] @@ -831,7 +831,7 @@ static RefPreprocessParams pre_and_post_processing() { RefPreprocessParams res("pre_and_post_processing"); res.function = []() { auto f = create_2inputs(element::f32, Shape{1, 3, 1, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo(0) .tensor(InputTensorInfo().set_element_type(element::u8)) .preprocess(PreProcessSteps().convert_element_type(element::f32).mean(1.f))) @@ -844,7 +844,7 @@ static RefPreprocessParams pre_and_post_processing() { .output(OutputInfo("tensor_output2") .postprocess(PostProcessSteps().convert_element_type()) .tensor(OutputTensorInfo().set_element_type(element::u8))) - .build(f); + .build(); return f; }; res.inputs.emplace_back(Shape{1, 3, 1, 2}, element::u8, std::vector{1, 2, 3, 4, 5, 6}); @@ -858,9 +858,9 @@ static RefPreprocessParams rgb_to_bgr() { RefPreprocessParams res("rgb_to_bgr"); res.function = []() { auto f = create_simple_function(element::f32, Shape{2, 1, 1, 3}); - f = PrePostProcessor().input(InputInfo() + f = PrePostProcessor(f).input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::RGB)) - .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR))).build(f); + .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR))).build(); return f; }; @@ -873,9 +873,9 @@ static RefPreprocessParams bgr_to_rgb() { RefPreprocessParams res("bgr_to_rgb"); res.function = []() { auto f = create_simple_function(element::f32, Shape{2, 1, 1, 3}); - f = PrePostProcessor().input(InputInfo() + f = PrePostProcessor(f).input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::BGR)) - .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))).build(f); + .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))).build(); return f; }; @@ -888,9 +888,9 @@ static RefPreprocessParams reverse_channels_nchw() { RefPreprocessParams res("reverse_channels_nchw"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 2, 2, 2}); - f = PrePostProcessor().input(InputInfo() + f = PrePostProcessor(f).input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW")) - .preprocess(PreProcessSteps().reverse_channels())).build(f); + .preprocess(PreProcessSteps().reverse_channels())).build(); return f; }; @@ -903,9 +903,9 @@ static RefPreprocessParams reverse_channels_dyn_layout() { RefPreprocessParams res("reverse_channels_dyn_layout"); res.function = []() { auto f = create_simple_function(element::f32, PartialShape{1, 1, 3, 2}); - f = PrePostProcessor().input(InputInfo() + f = PrePostProcessor(f).input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::BGR).set_layout("...CN")) - .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))).build(f); + .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))).build(); return f; }; @@ -921,9 +921,9 @@ static RefPreprocessParams reverse_dyn_shape() { Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}); - f = PrePostProcessor().input(InputInfo() + f = PrePostProcessor(f).input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW")) - .preprocess(PreProcessSteps().reverse_channels())).build(f); + .preprocess(PreProcessSteps().reverse_channels())).build(); return f; }; @@ -938,9 +938,9 @@ static RefPreprocessParams reverse_fully_dyn_shape() { auto f = create_simple_function(element::u8, PartialShape::dynamic()); auto p = PreProcessSteps(); p.reverse_channels(); - f = PrePostProcessor().input(InputInfo() + f = PrePostProcessor(f).input(InputInfo() .tensor(InputTensorInfo().set_layout("...C??")) - .preprocess(std::move(p))).build(f); + .preprocess(std::move(p))).build(); return f; }; diff --git a/docs/template_plugin/tests/functional/subgraph_reference/preprocess_legacy.cpp b/docs/template_plugin/tests/functional/subgraph_reference/preprocess_legacy.cpp index 6c41db9bd96a3b..e0bfa67f9028af 100644 --- a/docs/template_plugin/tests/functional/subgraph_reference/preprocess_legacy.cpp +++ b/docs/template_plugin/tests/functional/subgraph_reference/preprocess_legacy.cpp @@ -54,7 +54,7 @@ static std::shared_ptr create_simple_function_nv12(const PartialShape& TEST_F(ReferencePreprocessLegacyTest, mean) { function = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - function = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().mean(1.f))).build(function); + function = PrePostProcessor(function).input(InputInfo().preprocess(PreProcessSteps().mean(1.f))).build(); auto f2 = create_simple_function(element::f32, Shape{1, 3, 2, 2}); legacy_network = InferenceEngine::CNNNetwork(f2); @@ -72,7 +72,7 @@ TEST_F(ReferencePreprocessLegacyTest, mean) { TEST_F(ReferencePreprocessLegacyTest, mean_scale) { function = create_simple_function(element::f32, Shape{1, 3, 20, 20}); - function = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().scale(2.f))).build(function); + function = PrePostProcessor(function).input(InputInfo().preprocess(PreProcessSteps().scale(2.f))).build(); auto f2 = create_simple_function(element::f32, Shape{1, 3, 20, 20}); legacy_network = InferenceEngine::CNNNetwork(f2); @@ -93,11 +93,11 @@ TEST_F(ReferencePreprocessLegacyTest, resize) { auto f2 = create_simple_function(element::f32, Shape{1, 3, 5, 5}); legacy_network = InferenceEngine::CNNNetwork(f2); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW").set_spatial_static_shape(42, 30)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); auto &preProcess = legacy_network.getInputsInfo().begin()->second->getPreProcess(); preProcess.setResizeAlgorithm(InferenceEngine::ResizeAlgorithm::RESIZE_BILINEAR); @@ -114,12 +114,12 @@ class ConvertNV12WithLegacyTest: public ReferencePreprocessLegacyTest { inputData.clear(); legacy_input_blobs.clear(); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_color_format( ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); const auto ¶m = function->get_parameters()[0]; inputData.emplace_back(param->get_element_type(), param->get_shape(), ov20_input_yuv.data()); diff --git a/docs/template_plugin/tests/functional/subgraph_reference/preprocess_opencv.cpp b/docs/template_plugin/tests/functional/subgraph_reference/preprocess_opencv.cpp index cf9abb1adae08a..14ff3f3ac27ae7 100644 --- a/docs/template_plugin/tests/functional/subgraph_reference/preprocess_opencv.cpp +++ b/docs/template_plugin/tests/functional/subgraph_reference/preprocess_opencv.cpp @@ -72,11 +72,11 @@ TEST_F(PreprocessOpenCVReferenceTest_NV12, convert_nv12_full_color_range) { inputData.clear(); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_color_format( ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR))) - .build(function); + .build(); const auto ¶m = function->get_parameters()[0]; inputData.emplace_back(param->get_element_type(), param->get_shape(), ov20_input_yuv.data()); @@ -101,12 +101,12 @@ TEST_F(PreprocessOpenCVReferenceTest_NV12, convert_nv12_colored) { inputData.clear(); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_color_format( ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR)) ) - .build(function); + .build(); const auto ¶m = function->get_parameters()[0]; inputData.emplace_back(param->get_element_type(), param->get_shape(), input_yuv.data()); @@ -128,12 +128,12 @@ TEST_F(PreprocessOpenCVReferenceTest, resize_u8_simple_linear) { inputData.clear(); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(2, 2)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW")) ) - .build(function); + .build(); const auto ¶m = function->get_parameters()[0]; inputData.emplace_back(param->get_element_type(), param->get_shape(), input_img.data()); @@ -167,12 +167,12 @@ TEST_F(PreprocessOpenCVReferenceTest, resize_u8_large_picture_linear) { inputData.clear(); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(input_height, input_width)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW")) ) - .build(function); + .build(); const auto ¶m = function->get_parameters()[0]; inputData.emplace_back(param->get_element_type(), param->get_shape(), input_img.data()); @@ -205,12 +205,12 @@ TEST_F(PreprocessOpenCVReferenceTest, resize_f32_large_picture_linear) { inputData.clear(); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(input_height, input_width)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW")) ) - .build(function); + .build(); const auto ¶m = function->get_parameters()[0]; inputData.emplace_back(param->get_element_type(), param->get_shape(), input_img.data()); @@ -234,12 +234,12 @@ TEST_F(PreprocessOpenCVReferenceTest, DISABLED_resize_f32_large_picture_cubic_sm auto element_type = element::f32; auto input_img = std::vector {1.f, 2.f, 3.f, 4.f, 4.f, 3.f, 2.f, 1.f, 1.f, 2.f, 3.f, 4.f, 4.f, 3.f, 2.f, 1.f}; function = create_simple_function(element_type, func_shape); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(input_height, input_width)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_CUBIC)) .network(InputNetworkInfo().set_layout("NCHW")) ) - .build(function); + .build(); inputData.emplace_back(element_type, input_shape, input_img.data()); diff --git a/inference-engine/CMakeLists.txt b/inference-engine/CMakeLists.txt index 304098403a6eba..942907895b4bfd 100644 --- a/inference-engine/CMakeLists.txt +++ b/inference-engine/CMakeLists.txt @@ -63,4 +63,3 @@ elseif(WIN32) PATTERN speech_libs_and_demos EXCLUDE PATTERN .clang-format EXCLUDE) endif() - diff --git a/inference-engine/cmake/ie_parallel.cmake b/inference-engine/cmake/ie_parallel.cmake index 6c87d9b4eb940d..4f724840d377d9 100644 --- a/inference-engine/cmake/ie_parallel.cmake +++ b/inference-engine/cmake/ie_parallel.cmake @@ -91,7 +91,10 @@ function(set_ie_threading_interface_for TARGET_NAME) if(TARGET ${library}) get_target_property(include_directories ${library} INTERFACE_INCLUDE_DIRECTORIES) if(include_directories) - target_include_directories(${TARGET_NAME} SYSTEM BEFORE ${LINK_TYPE} ${include_directories}) + foreach(include_directory IN LISTS include_directories) + target_include_directories(${TARGET_NAME} SYSTEM BEFORE + ${LINK_TYPE} $) + endforeach() endif() endif() endforeach() @@ -178,6 +181,6 @@ function(set_ie_threading_interface_for TARGET_NAME) if (NOT THREADING STREQUAL "SEQ") find_package(Threads REQUIRED) - ie_target_link_libraries(${TARGET_NAME} ${LINK_TYPE} ${CMAKE_THREAD_LIBS_INIT}) + ie_target_link_libraries(${TARGET_NAME} ${LINK_TYPE} Threads::Threads) endif() endfunction(set_ie_threading_interface_for) diff --git a/inference-engine/ie_bridges/c/include/c_api/ie_c_api.h b/inference-engine/ie_bridges/c/include/c_api/ie_c_api.h index f46e59c38265fa..fdc50ae2efe2c8 100644 --- a/inference-engine/ie_bridges/c/include/c_api/ie_c_api.h +++ b/inference-engine/ie_bridges/c/include/c_api/ie_c_api.h @@ -372,7 +372,7 @@ INFERENCE_ENGINE_C_API(void) ie_core_versions_free(ie_core_versions_t *vers); /** * @brief Reads the model from the .xml and .bin files of the IR. Use the ie_network_free() method to free memory. * @ingroup Core - * @param core A pointer to ie_core_t instance. + * @param core A pointer to the ie_core_t instance. * @param xml .xml file's path of the IR. * @param weights_file .bin file's path of the IR, if path is empty, will try to read bin file with the same name as xml and * if bin file with the same name was not found, will load IR without weights. @@ -384,7 +384,7 @@ INFERENCE_ENGINE_C_API(IE_NODISCARD IEStatusCode) ie_core_read_network(ie_core_t /** * @brief Reads the model from an xml string and a blob of the bin part of the IR. Use the ie_network_free() method to free memory. * @ingroup Core - * @param core A pointer to ie_core_t instance. + * @param core A pointer to the ie_core_t instance. * @param xml_content Xml content of the IR. * @param xml_content_size Number of bytes in the xml content of the IR. * @param weight_blob Blob containing the bin part of the IR. @@ -395,12 +395,50 @@ INFERENCE_ENGINE_C_API(IE_NODISCARD IEStatusCode) ie_core_read_network_from_memo const ie_blob_t *weight_blob, ie_network_t **network); /** - * @brief Creates an executable network from a network object. Users can create as many networks as they need and use +* @brief Creates an executable network from a network previously exported to a file. Users can create as many networks as they need and use +* them simultaneously (up to the limitation of the hardware resources). Use the ie_exec_network_free() method to free memory. +* @ingroup Core +* @param core A pointer to the ie_core_t instance. +* @param file_name A path to the location of the exported file. +* @param device_name A name of the device to load the network to. +* @param config Device configuration. +* @param exe_network A pointer to the newly created executable network. +* @return Status code of the operation: OK(0) for success. +*/ +INFERENCE_ENGINE_C_API(IE_NODISCARD IEStatusCode) ie_core_import_network(ie_core_t *core, const char *file_name, const char *device_name, \ + const ie_config_t *config, ie_executable_network_t **exe_network); + +/** +* @brief Creates an executable network from a network previously exported to memory. Users can create as many networks as they need and use +* them simultaneously (up to the limitation of the hardware resources). Use the ie_exec_network_free() method to free memory. +* @ingroup Core +* @param core A pointer to the ie_core_t instance. +* @param content A pointer to content of the exported network. +* @param content_size Number of bytes in the exported network. +* @param device_name A name of the device to load the network to. +* @param config Device configuration. +* @param exe_network A pointer to the newly created executable network. +* @return Status code of the operation: OK(0) for success. +*/ +INFERENCE_ENGINE_C_API(IE_NODISCARD IEStatusCode) ie_core_import_network_from_memory(ie_core_t *core, const uint8_t *content, size_t content_size, + const char *device_name, const ie_config_t *config, ie_executable_network_t **exe_network); + +/** +* @brief Exports an executable network to a .bin file. +* @ingroup Core +* @param exe_network A pointer to the newly created executable network. +* @param file_name Path to the file to export the network to. +* @return Status code of the operation: OK(0) for success. +*/ +INFERENCE_ENGINE_C_API(IE_NODISCARD IEStatusCode) ie_core_export_network(ie_executable_network_t *exe_network, const char *file_name); + +/** + * @brief Creates an executable network from a given network object. Users can create as many networks as they need and use * them simultaneously (up to the limitation of the hardware resources). Use the ie_exec_network_free() method to free memory. * @ingroup Core - * @param core A pointer to ie_core_t instance. - * @param network A pointer to ie_network instance. - * @param device_name Name of device to load network to. + * @param core A pointer to the ie_core_t instance. + * @param network A pointer to the input ie_network instance to create the executable network from. + * @param device_name Name of the device to load the network to. * @param config Device configuration. * @param exe_network A pointer to the newly created executable network. * @return Status code of the operation: OK(0) for success. @@ -412,7 +450,7 @@ INFERENCE_ENGINE_C_API(IE_NODISCARD IEStatusCode) ie_core_load_network(ie_core_t * @brief Reads model and creates an executable network from IR or ONNX file. Users can create as many networks as they need and use * them simultaneously (up to the limitation of the hardware resources). Use the ie_exec_network_free() method to free memory. * @ingroup Core -* @param core A pointer to ie_core_t instance. +* @param core A pointer to the ie_core_t instance. * @param xml .xml file's path of the IR. Weights file name will be calculated automatically * @param device_name Name of device to load network to. * @param config Device configuration. diff --git a/inference-engine/ie_bridges/c/src/CMakeLists.txt b/inference-engine/ie_bridges/c/src/CMakeLists.txt index ecc8165ca349fa..4a60879bb52073 100644 --- a/inference-engine/ie_bridges/c/src/CMakeLists.txt +++ b/inference-engine/ie_bridges/c/src/CMakeLists.txt @@ -17,6 +17,10 @@ target_link_libraries(${TARGET_NAME} PRIVATE inference_engine) target_include_directories(${TARGET_NAME} PUBLIC $) +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(${TARGET_NAME} PUBLIC OPENVINO_STATIC_LIBRARY) +endif() + add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME}) set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) diff --git a/inference-engine/ie_bridges/c/src/ie_c_api.cpp b/inference-engine/ie_bridges/c/src/ie_c_api.cpp index f3b0e8f6b32dad..4eaf8539e81d12 100644 --- a/inference-engine/ie_bridges/c/src/ie_c_api.cpp +++ b/inference-engine/ie_bridges/c/src/ie_c_api.cpp @@ -9,10 +9,11 @@ #include #include #include -#include #include #include #include +#include +#include #include #include "inference_engine.hpp" #include "ie_compound_blob.h" @@ -60,6 +61,47 @@ struct ie_network { IE::CNNNetwork object; }; +/** + * @struct mem_stringbuf + * @brief This struct puts memory buffer to stringbuf. + */ +struct mem_stringbuf : std::streambuf { + mem_stringbuf(const char *buffer, size_t sz) { + char * bptr(const_cast(buffer)); + setg(bptr, bptr, bptr + sz); + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override { + switch (dir) { + case std::ios_base::beg: + setg(eback(), eback() + off, egptr()); + break; + case std::ios_base::end: + setg(eback(), egptr() + off, egptr()); + break; + case std::ios_base::cur: + setg(eback(), gptr() + off, egptr()); + break; + default: + return pos_type(off_type(-1)); + } + return (gptr() < eback() || gptr() > egptr()) ? pos_type(off_type(-1)) : pos_type(gptr() - eback()); + } + + pos_type seekpos(pos_type pos, std::ios_base::openmode which) override { + return seekoff(pos, std::ios_base::beg, which); + } +}; + +/** + * @struct mem_istream + * @brief This struct puts stringbuf buffer to istream. + */ +struct mem_istream: virtual mem_stringbuf, std::istream { + mem_istream(const char * buffer, size_t sz) : mem_stringbuf(buffer, sz), std::istream(static_cast(this)) { + } +}; + std::map status_map = {{IE::StatusCode::GENERAL_ERROR, IEStatusCode::GENERAL_ERROR}, {IE::StatusCode::INFER_NOT_STARTED, IEStatusCode::INFER_NOT_STARTED}, {IE::StatusCode::NETWORK_NOT_LOADED, IEStatusCode::NETWORK_NOT_LOADED}, @@ -143,7 +185,6 @@ std::map colorformat_map = {{IE::ColorFormat::RA std::map config2Map(const ie_config_t *config) { std::map m; const ie_config_t *tmp = config; - while (tmp && tmp->name && tmp->value) { m[tmp->name] = tmp->value; tmp = tmp->next; @@ -335,18 +376,71 @@ IEStatusCode ie_core_read_network_from_memory(ie_core_t *core, const uint8_t *xm return status; } +IEStatusCode ie_core_import_network(ie_core_t *core, const char *file_name, const char *device_name, + const ie_config_t *config, ie_executable_network_t **exe_network) { + IEStatusCode status = IEStatusCode::OK; + + if (core == nullptr || file_name == nullptr || device_name == nullptr || exe_network == nullptr) { + status = IEStatusCode::GENERAL_ERROR; + return status; + } + + try { + std::map conf_map = config2Map(config); + std::unique_ptr exe_net(new ie_executable_network_t); + + exe_net->object = core->object.ImportNetwork(file_name, device_name, conf_map); + *exe_network = exe_net.release(); + } CATCH_IE_EXCEPTIONS + + return status; +} + +IEStatusCode ie_core_import_network_from_memory(ie_core_t *core, const uint8_t *content, size_t content_size, const char *device_name, + const ie_config_t *config, ie_executable_network_t **exe_network) { + if (core == nullptr || content == nullptr || device_name == nullptr || exe_network == nullptr) { + return IEStatusCode::GENERAL_ERROR; + } + + IEStatusCode status = IEStatusCode::OK; + try { + mem_istream model_stream(reinterpret_cast(content), content_size); + + std::map conf_map = config2Map(config); + std::unique_ptr exe_net(new ie_executable_network_t); + + exe_net->object = core->object.ImportNetwork(model_stream, device_name, conf_map); + *exe_network = exe_net.release(); + } CATCH_IE_EXCEPTIONS + + return status; +} + +IEStatusCode ie_core_export_network(ie_executable_network_t *exe_network, const char *file_name) { + IEStatusCode status = IEStatusCode::OK; + + if (file_name == nullptr || exe_network == nullptr) { + status = IEStatusCode::GENERAL_ERROR; + return status; + } + try { + exe_network->object.Export(file_name); + } CATCH_IE_EXCEPTIONS + + return status; +} + IEStatusCode ie_core_load_network(ie_core_t *core, const ie_network_t *network, const char *device_name, \ const ie_config_t *config, ie_executable_network_t **exe_network) { IEStatusCode status = IEStatusCode::OK; - if (core == nullptr || network == nullptr || device_name == nullptr || config == nullptr || exe_network == nullptr) { + if (core == nullptr || network == nullptr || device_name == nullptr || exe_network == nullptr) { status = IEStatusCode::GENERAL_ERROR; return status; } try { - std::map conf_map; - conf_map = config2Map(config); + std::map conf_map = config2Map(config); std::unique_ptr exe_net(new ie_executable_network_t); // create plugin in the registery and then create ExecutableNetwork. @@ -361,14 +455,13 @@ IEStatusCode ie_core_load_network_from_file(ie_core_t *core, const char *xml, co const ie_config_t *config, ie_executable_network_t **exe_network) { IEStatusCode status = IEStatusCode::OK; - if (core == nullptr || xml == nullptr || device_name == nullptr || config == nullptr || exe_network == nullptr) { + if (core == nullptr || xml == nullptr || device_name == nullptr || exe_network == nullptr) { status = IEStatusCode::GENERAL_ERROR; return status; } try { - std::map conf_map; - conf_map = config2Map(config); + std::map conf_map = config2Map(config); std::unique_ptr exe_net(new ie_executable_network_t); exe_net->object = core->object.LoadNetwork(xml, device_name, conf_map); diff --git a/inference-engine/ie_bridges/c/tests/ie_c_api_test.cpp b/inference-engine/ie_bridges/c/tests/ie_c_api_test.cpp index c12f98013dee6b..d422448bc69907 100644 --- a/inference-engine/ie_bridges/c/tests/ie_c_api_test.cpp +++ b/inference-engine/ie_bridges/c/tests/ie_c_api_test.cpp @@ -145,6 +145,9 @@ TEST(ie_core_get_available_devices, getAvailableDevices) { ie_core_free(&core); } +// TODO: CVS-68982 +#ifndef OPENVINO_STATIC_LIBRARY + TEST(ie_core_register_plugin, registerPlugin) { ie_core_t *core = nullptr; IE_ASSERT_OK(ie_core_create("", &core)); @@ -213,6 +216,8 @@ TEST(ie_core_unregister_plugin, unregisterPlugin) { ie_core_free(&core); } +#endif // !OPENVINO_STATIC_LIBRARY + TEST(ie_core_set_config, setConfig) { ie_core_t *core = nullptr; IE_ASSERT_OK(ie_core_create("", &core)); @@ -312,7 +317,7 @@ TEST(ie_core_read_network_from_memory, networkReadFromMemory) { if (weights_blob != nullptr) { std::vector xml_content(content_from_file(xml, false)); - + ie_network_t *network = nullptr; IE_EXPECT_OK(ie_core_read_network_from_memory(core, xml_content.data(), xml_content.size(), weights_blob, &network)); EXPECT_NE(nullptr, network); @@ -321,6 +326,115 @@ TEST(ie_core_read_network_from_memory, networkReadFromMemory) { } ie_blob_free(&weights_blob); } + ie_core_free(&core); +} + +TEST(ie_core_export_network_to_file, exportNetworktoFile) { + ie_core_t *core = nullptr; + IE_ASSERT_OK(ie_core_create("", &core)); + ASSERT_NE(nullptr, core); + + ie_config_t config = {nullptr, nullptr, nullptr}; + ie_executable_network_t *exe_network = nullptr; + + IE_EXPECT_OK(ie_core_load_network_from_file(core, xml, "HETERO:CPU", &config, &exe_network)); + EXPECT_NE(nullptr, exe_network); + + std::string export_path = TestDataHelpers::generate_model_path("test_model", "exported_model.blob"); + IE_EXPECT_OK(ie_core_export_network(exe_network, export_path.c_str())); + std::ifstream file(export_path.c_str()); + EXPECT_NE(file.peek(), std::ifstream::traits_type::eof()); + + EXPECT_NE(nullptr, exe_network); + ie_exec_network_free(&exe_network); + ie_core_free(&core); +} + +TEST(ie_core_import_network_from_memory, importNetworkFromMem) { + ie_core_t *core = nullptr; + IE_ASSERT_OK(ie_core_create("", &core)); + ASSERT_NE(nullptr, core); + + ie_executable_network_t *exe_network = nullptr; + + IE_EXPECT_OK(ie_core_load_network_from_file(core, xml, "HETERO:CPU", nullptr, &exe_network)); + EXPECT_NE(nullptr, exe_network); + + std::string export_path = TestDataHelpers::generate_model_path("test_model", "exported_model.blob"); + IE_EXPECT_OK(ie_core_export_network(exe_network, export_path.c_str())); + + std::vector buffer(content_from_file(export_path.c_str(), true)); + ie_executable_network_t *network = nullptr; + + IE_EXPECT_OK(ie_core_import_network_from_memory(core, buffer.data(), buffer.size(), "HETERO:CPU", nullptr, &network)); + EXPECT_NE(nullptr, network); + if (network != nullptr) { + ie_exec_network_free(&network); + } + if (exe_network != nullptr) { + ie_exec_network_free(&exe_network); + } + ie_core_free(&core); +} + +TEST(ie_core_import_network_from_file, importNetworkFromFile) { + ie_core_t *core = nullptr; + IE_ASSERT_OK(ie_core_create("", &core)); + ASSERT_NE(nullptr, core); + + ie_config_t conf = {nullptr, nullptr, nullptr}; + + ie_executable_network_t *exe_network = nullptr; + IE_EXPECT_OK(ie_core_load_network_from_file(core, xml, "HETERO:CPU", &conf, &exe_network)); + EXPECT_NE(nullptr, exe_network); + + std::string exported_model = TestDataHelpers::generate_model_path("test_model", "exported_model.blob"); + IE_EXPECT_OK(ie_core_export_network(exe_network, exported_model.c_str())); + std::ifstream file(exported_model); + EXPECT_NE(file.peek(), std::ifstream::traits_type::eof()); + + IE_EXPECT_OK(ie_core_import_network(core, exported_model.c_str(), "HETERO:CPU", &conf, &exe_network)); + EXPECT_NE(nullptr, exe_network); + ie_exec_network_free(&exe_network); + ie_core_free(&core); +} + +TEST(ie_core_import_network_from_file, importNetwork_errorHandling) { + ie_core_t *core = nullptr; + IE_ASSERT_OK(ie_core_create("", &core)); + ASSERT_NE(nullptr, core); + + ie_config_t config = {nullptr, nullptr, nullptr}; + + ie_executable_network_t *network = nullptr; + IE_EXPECT_OK(ie_core_load_network_from_file(core, xml, "HETERO:CPU", &config, &network)); + EXPECT_NE(nullptr, network); + + std::string exported_model = TestDataHelpers::generate_model_path("test_model", "exported_model.blob"); + IE_EXPECT_OK(ie_core_export_network(network, exported_model.c_str())); + + ie_executable_network_t *exe_network = nullptr; + IE_EXPECT_NOT_OK(ie_core_import_network(core, nullptr, "HETERO:CPU", &config, &exe_network)); + EXPECT_EQ(nullptr, exe_network); + + IE_EXPECT_NOT_OK(ie_core_import_network(core, exported_model.c_str(), nullptr, &config, &exe_network)); + EXPECT_EQ(nullptr, exe_network); + + IE_EXPECT_NOT_OK(ie_core_import_network(core, exported_model.c_str(), "HETERO:CPU", &config, nullptr)); + EXPECT_EQ(nullptr, exe_network); + + IE_EXPECT_NOT_OK(ie_core_import_network(core, exported_model.c_str(), "UnregisteredDevice", &config, &exe_network)); + EXPECT_EQ(nullptr, exe_network); + + IE_EXPECT_OK(ie_core_import_network(core, exported_model.c_str(), "HETERO:CPU", nullptr, &exe_network)); + EXPECT_NE(nullptr, exe_network); + + if (network != nullptr) { + ie_exec_network_free(&network); + } + if (exe_network != nullptr) { + ie_exec_network_free(&exe_network); + } ie_core_free(&core); } @@ -366,6 +480,24 @@ TEST(ie_core_load_network, loadNetworkNoConfig) { ie_core_free(&core); } +TEST(ie_core_load_network, loadNetworkNullConfig) { + ie_core_t *core = nullptr; + IE_ASSERT_OK(ie_core_create("", &core)); + ASSERT_NE(nullptr, core); + + ie_network_t *network = nullptr; + IE_EXPECT_OK(ie_core_read_network(core, xml, bin, &network)); + EXPECT_NE(nullptr, network); + + ie_executable_network_t *exe_network = nullptr; + IE_EXPECT_OK(ie_core_load_network(core, network, "CPU", nullptr, &exe_network)); + EXPECT_NE(nullptr, exe_network); + + ie_exec_network_free(&exe_network); + ie_network_free(&network); + ie_core_free(&core); +} + TEST(ie_core_load_network_from_file, loadNetworkNoConfig) { ie_core_t *core = nullptr; IE_ASSERT_OK(ie_core_create("", &core)); @@ -380,6 +512,20 @@ TEST(ie_core_load_network_from_file, loadNetworkNoConfig) { ie_core_free(&core); } +TEST(ie_core_load_network_from_file, loadNetworkNullConfig) { + ie_core_t *core = nullptr; + IE_ASSERT_OK(ie_core_create("", &core)); + ASSERT_NE(nullptr, core); + + ie_executable_network_t *exe_network = nullptr; + IE_EXPECT_OK(ie_core_load_network_from_file(core, xml, "CPU", nullptr, &exe_network)); + EXPECT_NE(nullptr, exe_network); + + ie_exec_network_free(&exe_network); + ie_core_free(&core); +} + + TEST(ie_core_load_network_from_file, loadNetwork_errorHandling) { ie_core_t *core = nullptr; IE_ASSERT_OK(ie_core_create("", &core)); @@ -396,9 +542,6 @@ TEST(ie_core_load_network_from_file, loadNetwork_errorHandling) { IE_EXPECT_NOT_OK(ie_core_load_network_from_file(core, xml, nullptr, &config, &exe_network)); EXPECT_EQ(nullptr, exe_network); - IE_EXPECT_NOT_OK(ie_core_load_network_from_file(core, xml, "CPU", nullptr, &exe_network)); - EXPECT_EQ(nullptr, exe_network); - IE_EXPECT_NOT_OK(ie_core_load_network_from_file(core, xml, "CPU", &config, nullptr)); EXPECT_EQ(nullptr, exe_network); diff --git a/inference-engine/ie_bridges/c/tests/test_model_repo.hpp b/inference-engine/ie_bridges/c/tests/test_model_repo.hpp index e6a099f591f126..bd84e76a7ef54a 100644 --- a/inference-engine/ie_bridges/c/tests/test_model_repo.hpp +++ b/inference-engine/ie_bridges/c/tests/test_model_repo.hpp @@ -50,4 +50,4 @@ std::string generate_image_path(std::string dir, std::string filename) { std::string generate_ieclass_xml_path(std::string filename) { return getModelPathNonFatal() + kPathSeparator + "ie_class" + kPathSeparator + filename; } -} // namespace TestDataHelpers \ No newline at end of file +} // namespace TestDataHelpers diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/CMakeLists.txt b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/CMakeLists.txt index bc9115229e621c..72a69fb5904ad6 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/CMakeLists.txt +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/CMakeLists.txt @@ -29,10 +29,10 @@ if(COMMAND ie_add_vs_version_file) FILEDESCRIPTION "Offline Transformatoins Python library") endif() -if(TARGET offline_transformations) - list(APPEND link_libraries offline_transformations) -else() +if(InferenceEngineDeveloperPackage_FOUND) list(APPEND link_libraries IE::offline_transformations) +else() + list(APPEND link_libraries offline_transformations) endif() target_include_directories(${TARGET_NAME} SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../inference_engine") diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx index 2ca15561620a4d..4b42bee7805ef2 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api.pyx @@ -31,6 +31,10 @@ def ApplyLowLatencyTransformation(IENetwork network, bool use_const_initializer C.ApplyLowLatencyTransformation(network.impl, use_const_initializer) +def CompressModelTransformation(IENetwork network): + C.CompressModelTransformation(network.impl) + + def ApplyPruningTransformation(IENetwork network): C.ApplyPruningTransformation(network.impl) diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp index bae64e826a7843..9a7d652866643b 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -56,6 +58,13 @@ void InferenceEnginePython::GenerateMappingFile(InferenceEnginePython::IENetwork manager.run_passes(network.actual->getFunction()); } +void InferenceEnginePython::CompressModelTransformation(InferenceEnginePython::IENetwork network) { + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(network.actual->getFunction()); +} + void InferenceEnginePython::Serialize(InferenceEnginePython::IENetwork network, std::string path_to_xml, std::string path_to_bin) { @@ -80,4 +89,4 @@ void InferenceEnginePython::CheckAPI() { auto reshape = f->get_result()->input_value(0).get_node_shared_ptr(); assert(std::dynamic_pointer_cast(reshape->input_value(0).get_node_shared_ptr())); assert(std::dynamic_pointer_cast(reshape->input_value(1).get_node_shared_ptr())); -} \ No newline at end of file +} diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp index c135919a91f638..5de87dc29991fe 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl.hpp @@ -25,6 +25,8 @@ void ApplyPruningTransformation(InferenceEnginePython::IENetwork network); void GenerateMappingFile(InferenceEnginePython::IENetwork network, std::string path, bool extract_names); +void CompressModelTransformation(InferenceEnginePython::IENetwork network); + void Serialize(InferenceEnginePython::IENetwork network, std::string path_to_xml, std::string path_to_bin); void CheckAPI(); diff --git a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd index 82f6133df887e9..41755a0b2e06af 100644 --- a/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd +++ b/inference-engine/ie_bridges/python/src/openvino/offline_transformations/offline_transformations_api_impl_defs.pxd @@ -17,6 +17,8 @@ cdef extern from "offline_transformations_api_impl.hpp" namespace "InferenceEngi cdef void ApplyMakeStatefulTransformation(IENetwork network, map[string, string]& in_out_names) cdef void ApplyPruningTransformation(IENetwork network) + + cdef void CompressModelTransformation(IENetwork network) cdef void GenerateMappingFile(IENetwork network, string path, bool extract_names) diff --git a/inference-engine/ie_bridges/python/src/openvino/test_utils/CMakeLists.txt b/inference-engine/ie_bridges/python/src/openvino/test_utils/CMakeLists.txt index c6ae33c7951305..86dd25996b90ee 100644 --- a/inference-engine/ie_bridges/python/src/openvino/test_utils/CMakeLists.txt +++ b/inference-engine/ie_bridges/python/src/openvino/test_utils/CMakeLists.txt @@ -29,10 +29,10 @@ if(COMMAND ie_add_vs_version_file) FILEDESCRIPTION "Test Utils Python library") endif() -if(TARGET commonTestUtils) - list(APPEND link_libraries commonTestUtils) -else() +if(InferenceEngineDeveloperPackage_FOUND) list(APPEND link_libraries IE::commonTestUtils) +else() + list(APPEND link_libraries commonTestUtils) endif() target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/inference-engine/ie_bridges/python/tests/conftest.py b/inference-engine/ie_bridges/python/tests/conftest.py index 9d429a1d9c2885..2be7c5e1783cb2 100644 --- a/inference-engine/ie_bridges/python/tests/conftest.py +++ b/inference-engine/ie_bridges/python/tests/conftest.py @@ -45,9 +45,8 @@ def device(): def pytest_configure(config): # register an additional markers - config.addinivalue_line( - "markers", "template_plugin" - ) + config.addinivalue_line("markers", "template_plugin: Skip test on Template plugin") + config.addinivalue_line("markers", "dynamic_library: Runs tests only in dynamic libraries case") def create_encoder(input_shape, levels = 4): diff --git a/inference-engine/ie_bridges/python/tests/test_IECore.py b/inference-engine/ie_bridges/python/tests/test_IECore.py index 6e57f0958e3841..f7b67e20feb2d1 100644 --- a/inference-engine/ie_bridges/python/tests/test_IECore.py +++ b/inference-engine/ie_bridges/python/tests/test_IECore.py @@ -75,6 +75,7 @@ def test_query_network(device): assert next(iter(set(query_res.values()))) == device, "Wrong device for some layers" +@pytest.mark.dynamic_library @pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device dependent test") def test_register_plugin(): ie = IECore() @@ -86,6 +87,7 @@ def test_register_plugin(): assert isinstance(exec_net, ExecutableNetwork), "Cannot load the network to the registered plugin with name 'BLA'" +@pytest.mark.dynamic_library @pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device dependent test") def test_register_plugins(): ie = IECore() diff --git a/inference-engine/ie_bridges/python/wheel/CMakeLists.txt b/inference-engine/ie_bridges/python/wheel/CMakeLists.txt index ce1306f3f69fb3..211e63492378ae 100644 --- a/inference-engine/ie_bridges/python/wheel/CMakeLists.txt +++ b/inference-engine/ie_bridges/python/wheel/CMakeLists.txt @@ -47,7 +47,7 @@ endif() # create target for openvino.wheel set(openvino_wheel_deps ie_api offline_transformations_api) -foreach(_target ie_libraries ie_plugins _pyngraph) +foreach(_target ie_libraries ie_plugins _pyngraph pyopenvino) if(TARGET ${_target}) list(APPEND openvino_wheel_deps ${_target}) endif() @@ -70,4 +70,4 @@ add_custom_command(OUTPUT ${openvino_wheel_path} COMMENT "Building Python wheel ${openvino_wheel_name}" VERBATIM) -add_custom_target(ie_wheel DEPENDS ${openvino_wheel_path}) +add_custom_target(ie_wheel ALL DEPENDS ${openvino_wheel_path}) diff --git a/inference-engine/ie_bridges/python/wheel/requirements-dev.txt b/inference-engine/ie_bridges/python/wheel/requirements-dev.txt index 8c4ce47c35fcbb..26c6de3b960323 100644 --- a/inference-engine/ie_bridges/python/wheel/requirements-dev.txt +++ b/inference-engine/ie_bridges/python/wheel/requirements-dev.txt @@ -1,3 +1,3 @@ -setuptools>=53.0.0 +setuptools>=53.0.0,<=58.4.0 wheel>=0.36.2 python-decouple>=3.4 diff --git a/inference-engine/ie_bridges/python/wheel/setup.py b/inference-engine/ie_bridges/python/wheel/setup.py index dcf7967260c94c..de276d831d970c 100644 --- a/inference-engine/ie_bridges/python/wheel/setup.py +++ b/inference-engine/ie_bridges/python/wheel/setup.py @@ -109,6 +109,11 @@ 'prefix': 'site-packages', 'install_dir': PY_PACKAGES_DIR, }, + 'pyopenvino' : { + 'name': f'pyopenvino_{PYTHON_VERSION}', + 'prefix': 'site-packages', + 'install_dir': PY_PACKAGES_DIR, + }, } diff --git a/inference-engine/samples/CMakeLists.txt b/inference-engine/samples/CMakeLists.txt index b78e32b2fa79a3..c64dfbfe0451e3 100644 --- a/inference-engine/samples/CMakeLists.txt +++ b/inference-engine/samples/CMakeLists.txt @@ -227,6 +227,13 @@ macro(ie_add_sample) target_link_libraries(${IE_SAMPLE_NAME} PRIVATE gflags) endif() + install( + TARGETS ${IE_SAMPLE_NAME} + RUNTIME DESTINATION samples_bin/ + COMPONENT samples_bin + EXCLUDE_FROM_ALL + ) + # create global target with all samples / demo apps if(NOT TARGET ie_samples) add_custom_target(ie_samples ALL) diff --git a/inference-engine/samples/benchmark_app/CMakeLists.txt b/inference-engine/samples/benchmark_app/CMakeLists.txt index 4913084f94d872..b040829b422c65 100644 --- a/inference-engine/samples/benchmark_app/CMakeLists.txt +++ b/inference-engine/samples/benchmark_app/CMakeLists.txt @@ -4,6 +4,10 @@ set(TARGET_NAME "benchmark_app") +if(ENABLE_OPENCV) + set(OPENCV_MODULES core) +endif() + file (GLOB SRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) file (GLOB HDR ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) @@ -11,7 +15,7 @@ ie_add_sample(NAME ${TARGET_NAME} SOURCES ${SRC} HEADERS ${HDR} DEPENDENCIES format_reader ie_samples_utils - OPENCV_DEPENDENCIES core) + OPENCV_DEPENDENCIES ${OPENCV_MODULES}) find_package(OpenCL) diff --git a/inference-engine/samples/build_samples.sh b/inference-engine/samples/build_samples.sh index ad92920ae50be8..75f59b0c3716ab 100755 --- a/inference-engine/samples/build_samples.sh +++ b/inference-engine/samples/build_samples.sh @@ -3,6 +3,44 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 +usage() { + echo "Build inference engine samples" + echo + echo "Options:" + echo " -h Print the help message" + echo " -b SAMPLE_BUILD_DIR Specify the sample build directory" + echo " -i SAMPLE_INSTALL_DIR Specify the sample install directory" + echo + exit 1 +} + +samples_type=$(basename "$PWD") +build_dir="$HOME/inference_engine_${samples_type}_samples_build" +sample_install_dir="" + +# parse command line options +while [[ $# -gt 0 ]] +do +case "$1" in + -b | --build_dir) + build_dir="$2" + shift + ;; + -i | --install_dir) + sample_install_dir="$2" + shift + ;; + -h | --help) + usage + ;; + *) + echo "Unrecognized option specified $1" + usage + ;; +esac +shift +done + error() { local code="${3:-1}" if [[ -n "$2" ]];then @@ -39,9 +77,6 @@ if ! command -v cmake &>/dev/null; then exit 1 fi -samples_type=$(basename "$PWD") -build_dir="$HOME/inference_engine_${samples_type}_samples_build" - OS_PATH=$(uname -m) NUM_THREADS="-j2" @@ -53,9 +88,16 @@ fi if [ -e "$build_dir/CMakeCache.txt" ]; then rm -rf "$build_dir/CMakeCache.txt" fi + mkdir -p "$build_dir" cd "$build_dir" cmake -DCMAKE_BUILD_TYPE=Release "$SAMPLES_PATH" make $NUM_THREADS -printf "\nBuild completed, you can find binaries for all samples in the $build_dir/%s/Release subfolder.\n\n" "$OS_PATH" +if [ "$sample_install_dir" != "" ]; then + cmake -DCMAKE_INSTALL_PREFIX="$sample_install_dir" -DCOMPONENT=samples_bin -P cmake_install.cmake + printf "\nBuild completed, you can find binaries for all samples in the %s/samples_bin subfolder.\n\n" "$sample_install_dir" +else + printf "\nBuild completed, you can find binaries for all samples in the $build_dir/%s/Release subfolder.\n\n" "$OS_PATH" +fi + diff --git a/inference-engine/samples/build_samples_msvc.bat b/inference-engine/samples/build_samples_msvc.bat index d986d7277d0667..4ef67b2901806c 100644 --- a/inference-engine/samples/build_samples_msvc.bat +++ b/inference-engine/samples/build_samples_msvc.bat @@ -8,24 +8,26 @@ SETLOCAL EnableDelayedExpansion set "ROOT_DIR=%~dp0" FOR /F "delims=\" %%i IN ("%ROOT_DIR%") DO set SAMPLES_TYPE=%%~nxi -set "SOLUTION_DIR64=%USERPROFILE%\Documents\Intel\OpenVINO\inference_engine_%SAMPLES_TYPE%_samples_build" - -set MSBUILD_BIN= -set VS_PATH= -set VS_VERSION= - -if not "%1" == "" ( - if "%1"=="VS2015" ( - set "VS_VERSION=2015" - ) else if "%1"=="VS2017" ( - set "VS_VERSION=2017" - ) else if "%1"=="VS2019" ( - set "VS_VERSION=2019" - ) else ( - echo Unrecognized option specified "%1" - echo Supported command line options: VS2015, VS2017, VS2019 - goto errorHandling - ) +set "SAMPLE_BUILD_DIR=%USERPROFILE%\Documents\Intel\OpenVINO\inference_engine_%SAMPLES_TYPE%_samples_build" +set SAMPLE_INSTALL_DIR= + +:: command line arguments parsing +:input_arguments_loop +if not "%1"=="" ( + if "%1"=="-b" ( + set SAMPLE_BUILD_DIR=%2 + shift + ) else if "%1"=="-i" ( + set SAMPLE_INSTALL_DIR=%2 + shift + ) else if "%1"=="-h" ( + goto usage + ) else ( + echo Unrecognized option specified "%1" + goto usage + ) + shift + goto :input_arguments_loop ) if "%INTEL_OPENVINO_DIR%"=="" ( @@ -36,7 +38,6 @@ if "%INTEL_OPENVINO_DIR%"=="" ( echo To fix, run the following command: ^\setupvars.bat echo where INSTALL_DIR is the OpenVINO installation directory. GOTO errorHandling - ) ) ) @@ -46,87 +47,31 @@ if "%PROCESSOR_ARCHITECTURE%" == "AMD64" ( set "PLATFORM=Win32" ) -set VSWHERE="false" -if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ( - set VSWHERE="true" - cd "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer" -) else if exist "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" ( - set VSWHERE="true" - cd "%ProgramFiles%\Microsoft Visual Studio\Installer" -) else ( - echo "vswhere tool is not found" -) - -if !VSWHERE! == "true" ( - if "!VS_VERSION!"=="" ( - echo Searching the latest Visual Studio... - for /f "usebackq tokens=*" %%i in (`vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath`) do ( - set VS_PATH=%%i - ) - ) else ( - echo Searching Visual Studio !VS_VERSION!... - for /f "usebackq tokens=*" %%i in (`vswhere -products * -requires Microsoft.Component.MSBuild -property installationPath`) do ( - set CUR_VS=%%i - if not "!CUR_VS:%VS_VERSION%=!"=="!CUR_VS!" ( - set VS_PATH=!CUR_VS! - ) - ) - ) - if exist "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=14 2015" - ) - if exist "!VS_PATH!\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\15.0\Bin\MSBuild.exe" - ) - if exist "!VS_PATH!\MSBuild\Current\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\Current\Bin\MSBuild.exe" - ) -) - -if "!MSBUILD_BIN!" == "" ( - if "!VS_VERSION!"=="2015" ( - if exist "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=14 2015" - ) - ) else if "!VS_VERSION!"=="2017" ( - if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) else if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) else if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) - ) -) else ( - if not "!MSBUILD_BIN:2019=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=16 2019" - if not "!MSBUILD_BIN:2017=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=15 2017" - if not "!MSBUILD_BIN:2015=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=14 2015" -) - -if "!MSBUILD_BIN!" == "" ( - echo Build tools for Microsoft Visual Studio !VS_VERSION! cannot be found. If you use Visual Studio 2017, please download and install build tools from https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017 - GOTO errorHandling -) - -if exist "%SOLUTION_DIR64%\CMakeCache.txt" del "%SOLUTION_DIR64%\CMakeCache.txt" +if exist "%SAMPLE_BUILD_DIR%\CMakeCache.txt" del "%SAMPLE_BUILD_DIR%\CMakeCache.txt" -echo Creating Visual Studio %MSBUILD_VERSION% %PLATFORM% files in %SOLUTION_DIR64%... && ^ -cd "%ROOT_DIR%" && cmake -E make_directory "%SOLUTION_DIR64%" && cd "%SOLUTION_DIR64%" && cmake -G "Visual Studio !MSBUILD_VERSION!" -A %PLATFORM% "%ROOT_DIR%" +cd "%ROOT_DIR%" && cmake -E make_directory "%SAMPLE_BUILD_DIR%" && cd "%SAMPLE_BUILD_DIR%" && cmake -G "Visual Studio 16 2019" -A %PLATFORM% "%ROOT_DIR%" echo. echo ###############^|^| Build Inference Engine samples using MS Visual Studio (MSBuild.exe) ^|^|############### echo. -echo "!MSBUILD_BIN!" Samples.sln /p:Configuration=Release -"!MSBUILD_BIN!" Samples.sln /p:Configuration=Release + +echo cmake --build . --config Release +cmake --build . --config Release if ERRORLEVEL 1 GOTO errorHandling +if NOT "%SAMPLE_INSTALL_DIR%"=="" cmake -DCMAKE_INSTALL_PREFIX="%SAMPLE_INSTALL_DIR%" -DCOMPONENT=samples_bin -P cmake_install.cmake + echo Done. -goto :eof +exit /b + +:usage +echo Build inference engine samples +echo. +echo Options: +echo -h Print the help message +echo -b SAMPLE_BUILD_DIR Specify the sample build directory +echo -i SAMPLE_INSTALL_DIR Specify the sample install directory +exit /b :errorHandling echo Error diff --git a/inference-engine/samples/classification_sample_async/main.cpp b/inference-engine/samples/classification_sample_async/main.cpp index 56d942c1515387..9c8c168f0cda8b 100644 --- a/inference-engine/samples/classification_sample_async/main.cpp +++ b/inference-engine/samples/classification_sample_async/main.cpp @@ -104,28 +104,22 @@ int main(int argc, char* argv[]) { // -------- Step 3. Apply preprocessing -------- const ov::Layout tensor_layout{"NHWC"}; - // clang-format off - model = PrePostProcessor(). - // 1) InputInfo() with no args assumes a model has a single input - input(InputInfo(). - // 2) Set input tensor information: - // - precision of tensor is supposed to be 'u8' - // - layout of data is 'NHWC' - tensor(InputTensorInfo(). - set_element_type(ov::element::u8). - set_layout(tensor_layout)). - // 3) Here we suppose model has 'NCHW' layout for input - network(InputNetworkInfo(). - set_layout("NCHW"))). - output(OutputInfo(). - // 4) Set output tensor information: - // - precision of tensor is supposed to be 'f32' - tensor(OutputTensorInfo(). - set_element_type(ov::element::f32))). - // 5) Once the build() method is called, the preprocessing steps - // for layout and precision conversions are inserted automatically - build(model); - // clang-format on + PrePostProcessor proc(model); + // 1) input() with no args assumes a model has a single input + InputInfo& input_info = proc.input(); + // 2) Set input tensor information: + // - precision of tensor is supposed to be 'u8' + // - layout of data is 'NHWC' + input_info.tensor().set_element_type(ov::element::u8).set_layout(tensor_layout); + // 3) Here we suppose model has 'NCHW' layout for input + input_info.network().set_layout("NCHW"); + // 4) output() with no args assumes a model has a single result + // - output() with no args assumes a model has a single result + // - precision of tensor is supposed to be 'f32' + proc.output().tensor().set_element_type(ov::element::f32); + // 5) Once the build() method is called, the pre(post)processing steps + // for layout and precision conversions are inserted automatically + model = proc.build(); // -------- Step 4. read input images -------- slog::info << "Read input images" << slog::endl; diff --git a/inference-engine/samples/common/format_reader/CMakeLists.txt b/inference-engine/samples/common/format_reader/CMakeLists.txt index f4a3dfd0c7dd61..2bc71df4b2f611 100644 --- a/inference-engine/samples/common/format_reader/CMakeLists.txt +++ b/inference-engine/samples/common/format_reader/CMakeLists.txt @@ -40,3 +40,9 @@ set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_PDB_NAME ${TARGET_NAME} if(COMMAND add_clang_format_target) add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) endif() + +install( + TARGETS ${TARGET_NAME} + RUNTIME DESTINATION samples_bin/ COMPONENT samples_bin EXCLUDE_FROM_ALL + LIBRARY DESTINATION samples_bin/ COMPONENT samples_bin EXCLUDE_FROM_ALL +) diff --git a/inference-engine/samples/common/format_reader/opencv_wrapper.cpp b/inference-engine/samples/common/format_reader/opencv_wrapper.cpp index 26161e082fe71c..c302782e0be0d2 100644 --- a/inference-engine/samples/common/format_reader/opencv_wrapper.cpp +++ b/inference-engine/samples/common/format_reader/opencv_wrapper.cpp @@ -36,7 +36,7 @@ std::shared_ptr OCVReader::getData(size_t width = 0, size_t heigh size_t size = width * height * img.channels(); _data.reset(new unsigned char[size], std::default_delete()); - cv::Mat resized(width, height, img.type(), _data.get()); + cv::Mat resized(cv::Size(width, height), img.type(), _data.get()); if (width != img.cols || height != img.rows) { slog::warn << "Image is resized from (" << img.cols << ", " << img.rows << ") to (" << width << ", " << height diff --git a/inference-engine/samples/common/utils/include/samples/args_helper.hpp b/inference-engine/samples/common/utils/include/samples/args_helper.hpp index f216f370f5d2e5..e05f1ee905e567 100644 --- a/inference-engine/samples/common/utils/include/samples/args_helper.hpp +++ b/inference-engine/samples/common/utils/include/samples/args_helper.hpp @@ -38,3 +38,4 @@ void processLayout(InferenceEngine::CNNNetwork& network, const std::string& iol); void printInputAndOutputsInfo(const InferenceEngine::CNNNetwork& network); +void printInputAndOutputsInfo(const ov::Function& network); diff --git a/inference-engine/samples/common/utils/include/samples/common.hpp b/inference-engine/samples/common/utils/include/samples/common.hpp index 397e1f0ab35fbd..728071441e0003 100644 --- a/inference-engine/samples/common/utils/include/samples/common.hpp +++ b/inference-engine/samples/common/utils/include/samples/common.hpp @@ -33,6 +33,36 @@ # endif #endif +/** + * @brief Unicode string wrappers + */ +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) +# define tchar wchar_t +# define tstring std::wstring +# define tmain wmain +# define TSTRING2STRING(tstr) wstring2string(tstr) +#else +# define tchar char +# define tstring std::string +# define tmain main +# define TSTRING2STRING(tstr) tstr +#endif + +#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) + +/** + * @brief Convert wstring to string + * @param ref on wstring + * @return string + */ +inline std::string wstring2string(const std::wstring& wstr) { + std::string str; + for (auto&& wc : wstr) + str += static_cast(wc); + return str; +} +#endif + /** * @brief trim from start (in place) * @param s - string to trim diff --git a/inference-engine/samples/common/utils/src/args_helper.cpp b/inference-engine/samples/common/utils/src/args_helper.cpp index 43bf96d86a695a..a1cf3219054658 100644 --- a/inference-engine/samples/common/utils/src/args_helper.cpp +++ b/inference-engine/samples/common/utils/src/args_helper.cpp @@ -326,3 +326,35 @@ void printInputAndOutputsInfo(const InferenceEngine::CNNNetwork& network) { << layer.second->getLayout() << std::endl; } } + +void printInputAndOutputsInfo(const ov::Function& network) { + slog::info << "model name: " << network.get_friendly_name() << slog::endl; + + const std::vector> inputs = network.inputs(); + for (const ov::Output input : inputs) { + slog::info << " inputs" << slog::endl; + + const std::string name = input.get_names().empty() ? "NONE" : input.get_any_name(); + slog::info << " input name: " << name << slog::endl; + + const ov::element::Type type = input.get_element_type(); + slog::info << " input type: " << type << slog::endl; + + const ov::Shape shape = input.get_shape(); + slog::info << " input shape: " << shape << slog::endl; + } + + const std::vector> outputs = network.outputs(); + for (const ov::Output output : outputs) { + slog::info << " outputs" << slog::endl; + + const std::string name = output.get_names().empty() ? "NONE" : output.get_any_name(); + slog::info << " output name: " << name << slog::endl; + + const ov::element::Type type = output.get_element_type(); + slog::info << " output type: " << type << slog::endl; + + const ov::Shape shape = output.get_shape(); + slog::info << " output shape: " << shape << slog::endl; + } +} diff --git a/inference-engine/samples/hello_classification/CMakeLists.txt b/inference-engine/samples/hello_classification/CMakeLists.txt index 9b0509bab82c23..bef82baa3cecee 100644 --- a/inference-engine/samples/hello_classification/CMakeLists.txt +++ b/inference-engine/samples/hello_classification/CMakeLists.txt @@ -4,6 +4,5 @@ ie_add_sample(NAME hello_classification SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" - DEPENDENCIES ie_samples_utils - OPENCV_DEPENDENCIES core imgcodecs) + DEPENDENCIES format_reader ie_samples_utils) diff --git a/inference-engine/samples/hello_classification/main.cpp b/inference-engine/samples/hello_classification/main.cpp index baa359cbbd6901..2169652695f9cf 100644 --- a/inference-engine/samples/hello_classification/main.cpp +++ b/inference-engine/samples/hello_classification/main.cpp @@ -4,122 +4,75 @@ #include #include -#include #include #include -#include "openvino/core/layout.hpp" +// clang-format off #include "openvino/openvino.hpp" -#include "samples/classification_results.h" + +#include "samples/args_helper.hpp" #include "samples/common.hpp" -#include "samples/ocv_common.hpp" +#include "samples/classification_results.h" +#include "samples/slog.hpp" +#include "format_reader_ptr.h" +// clang-format on using namespace ov::preprocess; -/** - * @brief Define names based depends on Unicode path support - */ -#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) -# define tcout std::wcout -# define file_name_t std::wstring -# define imread_t imreadW -# define ClassificationResult_t ClassificationResultW -#else -# define tcout std::cout -# define file_name_t std::string -# define imread_t cv::imread -# define ClassificationResult_t ClassificationResult -#endif - -#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) -/** - * @brief Realization cv::imread with support Unicode paths - */ -cv::Mat imreadW(std::wstring input_image_path) { - cv::Mat image; - std::ifstream input_image_stream; - input_image_stream.open(input_image_path.c_str(), std::iostream::binary | std::ios_base::ate | std::ios_base::in); - if (input_image_stream.is_open()) { - if (input_image_stream.good()) { - input_image_stream.seekg(0, std::ios::end); - std::size_t file_size = input_image_stream.tellg(); - input_image_stream.seekg(0, std::ios::beg); - std::vector buffer(0); - std::copy(std::istreambuf_iterator(input_image_stream), - std::istreambuf_iterator(), - std::back_inserter(buffer)); - image = cv::imdecode(cv::Mat(1, file_size, CV_8UC1, &buffer[0]), cv::IMREAD_COLOR); - } else { - tcout << "Input file '" << input_image_path << "' processing error" << std::endl; - } - input_image_stream.close(); - } else { - tcout << "Unable to read input file '" << input_image_path << "'" << std::endl; - } - return image; -} - -/** - * @brief Convert wstring to string - * @param ref on wstring - * @return string - */ -std::string simpleConvert(const std::wstring& wstr) { - std::string str; - for (auto&& wc : wstr) - str += static_cast(wc); - return str; -} - /** * @brief Main with support Unicode paths, wide strings */ -int wmain(int argc, wchar_t* argv[]) { -#else - -int main(int argc, char* argv[]) { -#endif +int tmain(int argc, tchar* argv[]) { try { - // -------- Get OpenVINO Runtime version -------- - slog::info << "OpenVINO runtime: " << ov::get_openvino_version() << slog::endl; + // -------- Get OpenVINO runtime version -------- + slog::info << ov::get_openvino_version() << slog::endl; // -------- Parsing and validation of input arguments -------- if (argc != 4) { - tcout << "Usage : " << argv[0] << " " << std::endl; + slog::info << "Usage : " << argc << " " << slog::endl; return EXIT_FAILURE; } - const file_name_t input_model{argv[1]}; - const file_name_t input_image_path{argv[2]}; -#if defined(ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) - const std::string device_name = simpleConvert(argv[3]); -#else - const std::string device_name{argv[3]}; -#endif + const std::string args = TSTRING2STRING(argv[0]); + const std::string model_path = TSTRING2STRING(argv[1]); + const std::string image_path = TSTRING2STRING(argv[2]); + const std::string device_name = TSTRING2STRING(argv[3]); // -------- Step 1. Initialize OpenVINO Runtime Core -------- ov::runtime::Core core; // -------- Step 2. Read a model -------- - auto model = core.read_model(input_model); + slog::info << "Loading model files: " << model_path << slog::endl; + auto model = core.read_model(model_path); + printInputAndOutputsInfo(*model); OPENVINO_ASSERT(model->get_parameters().size() == 1, "Sample supports models with 1 input only"); OPENVINO_ASSERT(model->get_results().size() == 1, "Sample supports models with 1 output only"); - // -------- Step 3. Initialize inference engine core + // -------- Step 3. Set up input // Read input image to a tensor and set it to an infer request // without resize and layout conversions - cv::Mat image = imread_t(input_image_path); - // just wrap Mat data by ov::runtime::Tensor without allocating of new memory - ov::runtime::Tensor input_tensor = wrapMat2Tensor(image); + FormatReader::ReaderPtr reader(image_path.c_str()); + if (reader.get() == nullptr) { + slog::warn << "Image " + image_path + " cannot be read!" << slog::endl; + throw std::logic_error(""); + } + + ov::element::Type input_type = ov::element::u8; + ov::Shape input_shape = {1, reader->height(), reader->width(), 3}; + std::shared_ptr input_data = reader->getData(); + + // just wrap image data by ov::runtime::Tensor without allocating of new memory + ov::runtime::Tensor input_tensor = ov::runtime::Tensor(input_type, input_shape, input_data.get()); + const ov::Shape tensor_shape = input_tensor.get_shape(); + const ov::Layout tensor_layout{"NHWC"}; // -------- Step 4. Apply preprocessing -------- - const ov::Layout tensor_layout{"NHWC"}; // clang-format off - model = PrePostProcessor(). + model = PrePostProcessor(model). // 1) InputInfo() with no args assumes a model has a single input input(InputInfo(). // 2) Set input tensor information: @@ -147,8 +100,8 @@ int main(int argc, char* argv[]) { // - precision of tensor is supposed to be 'f32' tensor(OutputTensorInfo(). set_element_type(ov::element::f32))). - // 6) Apply preprocessing modifing the original 'model' - build(model); + // 6) Apply preprocessing modifing the original 'model' + build(); // clang-format on // -------- Step 5. Loading a model to the device -------- @@ -165,18 +118,16 @@ int main(int argc, char* argv[]) { infer_request.infer(); // -------- Step 9. Process output - ov::runtime::Tensor output_tensor = infer_request.get_output_tensor(); + const ov::runtime::Tensor& output_tensor = infer_request.get_output_tensor(); // Print classification results - ClassificationResult_t classification_result(output_tensor, {input_image_path}); + ClassificationResult classification_result(output_tensor, {image_path}); classification_result.show(); // ----------------------------------------------------------------------------------------------------- } catch (const std::exception& ex) { std::cerr << ex.what() << std::endl; return EXIT_FAILURE; } - std::cout << "This sample is an API example, for any performance measurements " - "please use the dedicated benchmark_app tool" - << std::endl; + return EXIT_SUCCESS; } diff --git a/inference-engine/samples/hello_reshape_ssd/CMakeLists.txt b/inference-engine/samples/hello_reshape_ssd/CMakeLists.txt index 5be6137ab2a716..ae7283c3634ca5 100644 --- a/inference-engine/samples/hello_reshape_ssd/CMakeLists.txt +++ b/inference-engine/samples/hello_reshape_ssd/CMakeLists.txt @@ -5,5 +5,4 @@ ie_add_sample(NAME hello_reshape_ssd SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/reshape_ssd_extension.hpp" - DEPENDENCIES ie_samples_utils - OPENCV_DEPENDENCIES core imgproc imgcodecs) + DEPENDENCIES format_reader ie_samples_utils) diff --git a/inference-engine/samples/hello_reshape_ssd/main.cpp b/inference-engine/samples/hello_reshape_ssd/main.cpp index b91c2e1118699f..13d30a8c50bb08 100644 --- a/inference-engine/samples/hello_reshape_ssd/main.cpp +++ b/inference-engine/samples/hello_reshape_ssd/main.cpp @@ -2,10 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 // +#include + #include #include #include -#include +#include #include #include @@ -54,12 +56,19 @@ int main(int argc, char* argv[]) { std::string input_name; SizeVector input_shape; std::tie(input_name, input_shape) = *input_shapes.begin(); - cv::Mat image = cv::imread(input_image_path); + FormatReader::ReaderPtr reader(input_image_path.c_str()); + if (reader.get() == nullptr) { + std::cout << "Image " + input_image_path + " cannot be read!" << std::endl; + return 1; + } + size_t image_width, image_height; + image_width = reader->width(); + image_height = reader->height(); input_shape[0] = batch_size; - input_shape[2] = static_cast(image.rows); - input_shape[3] = static_cast(image.cols); + input_shape[2] = image_height; + input_shape[3] = image_width; input_shapes[input_name] = input_shape; - std::cout << "Resizing network to the image size = [" << image.rows << "x" << image.cols << "] " + std::cout << "Resizing network to the image size = [" << image_height << "x" << image_width << "] " << "with batch = " << batch_size << std::endl; network.reshape(input_shapes); // ----------------------------------------------------------------------------------------------------- @@ -132,10 +141,51 @@ int main(int argc, char* argv[]) { // --------------------------- Step 6. Prepare input // -------------------------------------------------------- - Blob::Ptr input = infer_request.GetBlob(input_name); - for (size_t b = 0; b < batch_size; b++) { - matU8ToBlob(image, input, b); + /** Collect images data ptrs **/ + std::shared_ptr image_data, original_image_data; + /** Store image data **/ + std::shared_ptr original_data(reader->getData()); + std::shared_ptr data_reader( + reader->getData(input_info->getTensorDesc().getDims()[3], input_info->getTensorDesc().getDims()[2])); + if (data_reader.get() != nullptr) { + original_image_data = original_data; + image_data = data_reader; + } else { + throw std::logic_error("Valid input images were not found!"); + } + + /** Creating input blob **/ + Blob::Ptr image_input = infer_request.GetBlob(input_name); + + /** Filling input tensor with images. First b channel, then g and r channels **/ + MemoryBlob::Ptr mimage = as(image_input); + if (!mimage) { + std::cout << "We expect image blob to be inherited from MemoryBlob, but by fact we were not able " + "to cast imageInput to MemoryBlob" + << std::endl; + return 1; + } + // locked memory holder should be alive all time while access to its buffer happens + auto minputHolder = mimage->wmap(); + + size_t num_channels = mimage->getTensorDesc().getDims()[1]; + size_t image_size = mimage->getTensorDesc().getDims()[3] * mimage->getTensorDesc().getDims()[2]; + + unsigned char* data = minputHolder.as(); + + /** Iterate over all input images **/ + for (size_t image_id = 0; image_id < batch_size; ++image_id) { + /** Iterate over all pixel in image (b,g,r) **/ + for (size_t pid = 0; pid < image_size; pid++) { + /** Iterate over all channels **/ + for (size_t ch = 0; ch < num_channels; ++ch) { + /** [images stride + channels stride + pixel id ] all in bytes **/ + data[image_id * image_size * num_channels + ch * image_size + pid] = + image_data.get()[pid * num_channels + ch]; + } + } } + // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 7. Do inference @@ -156,37 +206,51 @@ int main(int argc, char* argv[]) { auto moutputHolder = moutput->rmap(); const float* detection = moutputHolder.as(); + std::vector> boxes(batch_size); + std::vector> classes(batch_size); + /* Each detection has image_id that denotes processed image */ for (size_t cur_proposal = 0; cur_proposal < max_proposal_count; cur_proposal++) { - float image_id = detection[cur_proposal * object_size + 0]; - float label = detection[cur_proposal * object_size + 1]; - float confidence = detection[cur_proposal * object_size + 2]; - /* CPU and GPU devices have difference in DetectionOutput layer, so we - * need both checks */ - if (image_id < 0 || confidence == 0.0f) { - continue; + auto image_id = static_cast(detection[cur_proposal * object_size + 0]); + if (image_id < 0) { + break; } - float xmin = detection[cur_proposal * object_size + 3] * image.cols; - float ymin = detection[cur_proposal * object_size + 4] * image.rows; - float xmax = detection[cur_proposal * object_size + 5] * image.cols; - float ymax = detection[cur_proposal * object_size + 6] * image.rows; + float confidence = detection[cur_proposal * object_size + 2]; + auto label = static_cast(detection[cur_proposal * object_size + 1]); + auto xmin = detection[cur_proposal * object_size + 3] * image_width; + auto ymin = detection[cur_proposal * object_size + 4] * image_height; + auto xmax = detection[cur_proposal * object_size + 5] * image_width; + auto ymax = detection[cur_proposal * object_size + 6] * image_height; if (confidence > 0.5f) { /** Drawing only objects with >50% probability **/ - std::ostringstream conf; - conf << ":" << std::fixed << std::setprecision(3) << confidence; - cv::rectangle(image, cv::Point2f(xmin, ymin), cv::Point2f(xmax, ymax), cv::Scalar(0, 0, 255)); + classes[image_id].push_back(label); + boxes[image_id].push_back(static_cast(xmin)); + boxes[image_id].push_back(static_cast(ymin)); + boxes[image_id].push_back(static_cast(xmax - xmin)); + boxes[image_id].push_back(static_cast(ymax - ymin)); + std::cout << "[" << cur_proposal << "," << label << "] element, prob = " << confidence << ", bbox = (" << xmin << "," << ymin << ")-(" << xmax << "," << ymax << ")" << ", batch id = " << image_id << std::endl; } } - cv::imwrite("hello_reshape_ssd_output.jpg", image); - std::cout << "The resulting image was saved in the file: " - "hello_reshape_ssd_output.jpg" - << std::endl; + for (size_t batch_id = 0; batch_id < batch_size; ++batch_id) { + addRectangles(original_image_data.get(), + image_height, + image_width, + boxes[batch_id], + classes[batch_id], + BBOX_THICKNESS); + const std::string image_path = "hello_reshape_ssd_output.bmp"; + if (writeOutputBmp(image_path, original_image_data.get(), image_height, image_width)) { + std::cout << "The resulting image was saved in the file: " + image_path << std::endl; + } else { + throw std::logic_error(std::string("Can't create a file: ") + image_path); + } + } // ----------------------------------------------------------------------------------------------------- } catch (const std::exception& ex) { std::cerr << ex.what() << std::endl; diff --git a/inference-engine/samples/hello_reshape_ssd/reshape_ssd_extension.hpp b/inference-engine/samples/hello_reshape_ssd/reshape_ssd_extension.hpp index 1b1d6c934ff094..fdc4837e31bee6 100644 --- a/inference-engine/samples/hello_reshape_ssd/reshape_ssd_extension.hpp +++ b/inference-engine/samples/hello_reshape_ssd/reshape_ssd_extension.hpp @@ -12,6 +12,9 @@ #define CUSTOM_RELU_TYPE "CustomReLU" +/* thickness of a line (in pixels) to be used for bounding boxes */ +#define BBOX_THICKNESS 2 + class CustomReLUImpl : public InferenceEngine::ILayerExecImpl { public: explicit CustomReLUImpl(const std::shared_ptr& node) : _node(node) {} diff --git a/inference-engine/samples/ngraph_function_creation_sample/main.cpp b/inference-engine/samples/ngraph_function_creation_sample/main.cpp index 14a37c4d3ef929..24db7a4e0a3890 100644 --- a/inference-engine/samples/ngraph_function_creation_sample/main.cpp +++ b/inference-engine/samples/ngraph_function_creation_sample/main.cpp @@ -278,7 +278,7 @@ int main(int argc, char* argv[]) { // apply preprocessing // clang-format off using namespace ov::preprocess; - model = PrePostProcessor() + model = PrePostProcessor(model) // 1) InputInfo() with no args assumes a model has a single input .input(InputInfo() // 2) Set input tensor information: @@ -292,7 +292,7 @@ int main(int argc, char* argv[]) { .set_layout("NCHW"))) // 4) Once the build() method is called, the preprocessing steps // for layout and precision conversions are inserted automatically - .build(model); + .build(); // clang-format on // -------- Step 4. Read input images -------- diff --git a/inference-engine/src/CMakeLists.txt b/inference-engine/src/CMakeLists.txt index 7db652e7a2e1fe..b74d4b2830b4a4 100644 --- a/inference-engine/src/CMakeLists.txt +++ b/inference-engine/src/CMakeLists.txt @@ -9,8 +9,6 @@ endif() add_subdirectory(transformations) -add_subdirectory(legacy_api) - add_subdirectory(low_precision_transformations) add_subdirectory(offline_transformations) @@ -43,6 +41,8 @@ endif() add_subdirectory(inference_engine) +add_subdirectory(legacy_api) + add_subdirectory(readers) add_subdirectory(preprocessing) @@ -59,17 +59,21 @@ if(ENABLE_IR_V7_READER) endif() if(NGRAPH_IR_FRONTEND_ENABLE) - add_dependencies(ie_libraries ir_ngraph_frontend) + if(BUILD_SHARED_LIBS) + add_dependencies(ie_libraries ir_ngraph_frontend) + endif() + # use this one once CVS-69781 is fixed + # add_dependencies(inference_engine ir_ngraph_frontend) endif() if(NGRAPH_ONNX_FRONTEND_ENABLE) - add_dependencies(ie_libraries onnx_ngraph_frontend) + add_dependencies(inference_engine onnx_ngraph_frontend) endif() if(NGRAPH_PDPD_FRONTEND_ENABLE) - add_dependencies(ie_libraries paddlepaddle_ngraph_frontend) + add_dependencies(inference_engine paddlepaddle_ngraph_frontend) endif() if(NGRAPH_TF_FRONTEND_ENABLE) - add_dependencies(ie_libraries tensorflow_ngraph_frontend) + add_dependencies(inference_engine tensorflow_ngraph_frontend) endif() diff --git a/inference-engine/src/cldnn_engine/CMakeLists.txt b/inference-engine/src/cldnn_engine/CMakeLists.txt index 07fdb08df843c1..c28ff772540bb4 100644 --- a/inference-engine/src/cldnn_engine/CMakeLists.txt +++ b/inference-engine/src/cldnn_engine/CMakeLists.txt @@ -43,6 +43,11 @@ target_include_directories(${TARGET_NAME} PRIVATE set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) +# Workaround to avoid warnings during LTO build +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS_RELEASE "-Wno-error=maybe-uninitialized -Wno-maybe-uninitialized") +endif() + # Failed because of OpenCL # ie_add_api_validator_post_build_step(TARGET ${TARGET_NAME}) diff --git a/inference-engine/src/cldnn_engine/cldnn_async_infer_request.cpp b/inference-engine/src/cldnn_engine/cldnn_async_infer_request.cpp index 9e69ddeb0c8f28..c6c5faf11c42fb 100644 --- a/inference-engine/src/cldnn_engine/cldnn_async_infer_request.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_async_infer_request.cpp @@ -17,29 +17,34 @@ CLDNNPlugin::CLDNNAsyncInferRequest::CLDNNAsyncInferRequest(const CLDNNInferRequ _pipeline.push_back({taskExecutor, [this] { OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "CLDNNAsyncInferRequest::PreprocessingAndStartPipeline"); + _inferRequest->setup_stream_graph(); _inferRequest->preprocess(); _inferRequest->enqueue(); + _inferRequest->wait(); } }); + } else { + _pipeline.push_back({ _waitExecutor, + [this] { + OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "CLDNNAsyncInferRequest::WaitPipeline"); + _inferRequest->wait_notify(); + } }); } - _pipeline.push_back({_waitExecutor, - [this] { - OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "CLDNNAsyncInferRequest::WaitPipeline"); - _inferRequest->wait(); - }}); } void CLDNNPlugin::CLDNNAsyncInferRequest::Infer_ThreadUnsafe() { if (_inferRequest->use_external_queue()) { - _inferRequest->preprocess(); - _inferRequest->enqueue(); + _inferRequest->setup_stream_graph(); + _inferRequest->preprocess_notify(); + _inferRequest->enqueue_notify(); } Parent::Infer_ThreadUnsafe(); } void CLDNNPlugin::CLDNNAsyncInferRequest::StartAsync_ThreadUnsafe() { if (_inferRequest->use_external_queue()) { - _inferRequest->preprocess(); - _inferRequest->enqueue(); + _inferRequest->setup_stream_graph(); + _inferRequest->preprocess_notify(); + _inferRequest->enqueue_notify(); } Parent::StartAsync_ThreadUnsafe(); } diff --git a/inference-engine/src/cldnn_engine/cldnn_graph.h b/inference-engine/src/cldnn_engine/cldnn_graph.h index d65d4183d90a76..27a9a3f029a005 100644 --- a/inference-engine/src/cldnn_engine/cldnn_graph.h +++ b/inference-engine/src/cldnn_engine/cldnn_graph.h @@ -70,6 +70,7 @@ class CLDNNGraph { } m_cv.notify_one(); } + std::mutex& get_mutex() { return m_infer_mutex; } bool use_external_queue() const; diff --git a/inference-engine/src/cldnn_engine/cldnn_infer_request.cpp b/inference-engine/src/cldnn_engine/cldnn_infer_request.cpp index c71acf4e6d975a..c98b06ce4cffcb 100644 --- a/inference-engine/src/cldnn_engine/cldnn_infer_request.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_infer_request.cpp @@ -450,10 +450,7 @@ void CLDNNInferRequest::SetBatch(int new_batch) { CLDNNInferRequest::CLDNNInferRequest(InputsDataMap networkInputs, OutputsDataMap networkOutputs, const CLDNNExecNetwork::Ptr& execNetwork) - : IInferRequestInternal(networkInputs, networkOutputs) - , m_useProfiling(false) - , m_useStreams(false) - , m_useExternalQueue(false) { + : IInferRequestInternal(networkInputs, networkOutputs) { IE_ASSERT(nullptr != execNetwork); streamExecutor = dynamic_cast(execNetwork->m_taskExecutor.get()); } @@ -461,9 +458,7 @@ CLDNNInferRequest::CLDNNInferRequest(InputsDataMap networkInputs, OutputsDataMap CLDNNInferRequest::CLDNNInferRequest(const std::vector>& inputs, const std::vector>& outputs, const CLDNNExecNetwork::Ptr& execNetwork) - : IInferRequestInternal(inputs, outputs) - , m_useProfiling(false) - , m_useStreams(false) { + : IInferRequestInternal(inputs, outputs) { IE_ASSERT(nullptr != execNetwork); streamExecutor = dynamic_cast(execNetwork->m_taskExecutor.get()); } @@ -471,28 +466,30 @@ CLDNNInferRequest::CLDNNInferRequest(const std::vector(_exeNetwork.get())->m_graphs; - if (nullptr != streamExecutor) { - streamID = streamExecutor->GetStreamId(); - int numGraphs = streamGraphs.size(); - streamID = streamID % numGraphs; - } - m_graph = streamGraphs[streamID]; - +void CLDNNInferRequest::preprocess_notify() { m_graph->wait(CLDNNGraph::Stage::PREPROC); if (m_graph->GetMaxDynamicBatchSize() > 1) { preprocess_dynamic(); - return; + } else { + execDataPreprocessing(_inputs, true); // "true" stands for serial preprocessing in case of OpenMP } - execDataPreprocessing(_inputs, true); // "true" stands for serial preprocessing in case of OpenMP m_graph->notify(CLDNNGraph::Stage::PREPROC); } -void CLDNNInferRequest::enqueue() { +void CLDNNInferRequest::preprocess() { + if (m_graph->GetMaxDynamicBatchSize() > 1) { + preprocess_dynamic(); + } else { + execDataPreprocessing(_inputs, true); // "true" stands for serial preprocessing in case of OpenMP + } +} + +void CLDNNInferRequest::enqueue_notify() { m_graph->wait(CLDNNGraph::Stage::EXECUTE); + enqueue(); +} + +void CLDNNInferRequest::enqueue() { if (m_graph->GetMaxDynamicBatchSize() > 1) { enqueue_dynamic(); return; @@ -541,6 +538,11 @@ void CLDNNInferRequest::enqueue() { internal_outputs = m_graph->GetNetwork()->execute(dependencies); } +void CLDNNInferRequest::wait_notify() { + wait(); + m_graph->notify(CLDNNGraph::Stage::EXECUTE); +} + void CLDNNInferRequest::wait() { if (m_graph->GetMaxDynamicBatchSize() > 1) { wait_dynamic(); @@ -568,13 +570,11 @@ void CLDNNInferRequest::wait() { if (m_useProfiling) { m_graph->UpdatePerfStatistics(); } - m_graph->notify(CLDNNGraph::Stage::EXECUTE); } void CLDNNInferRequest::preprocess_dynamic() { // execute input pre-processing. execDataPreprocessing(_inputs, true); // "true" stands for serial preprocessing in case of OpenMP - m_graph->notify(CLDNNGraph::Stage::PREPROC); } void CLDNNInferRequest::enqueue_dynamic() { @@ -619,12 +619,21 @@ void CLDNNInferRequest::wait_dynamic() { } } } - m_graph->notify(CLDNNGraph::Stage::EXECUTE); } // ----------------------------------------------------------------------------------------- // // ---------------------------- internal utils --------- ----------------------------------- // // ----------------------------------------------------------------------------------------- // +void CLDNNInferRequest::setup_stream_graph() { + int streamID = 0; + auto& streamGraphs = static_cast(_exeNetwork.get())->m_graphs; + if (nullptr != streamExecutor) { + streamID = streamExecutor->GetStreamId(); + int numGraphs = streamGraphs.size(); + streamID = streamID % numGraphs; + } + m_graph = streamGraphs[streamID]; +} Blob::Ptr CLDNNInferRequest::create_host_blob(const TensorDesc& desc, uint8_t* mem_ptr) { OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "CLDNNInferRequest::create_host_blob"); @@ -746,6 +755,21 @@ void CLDNNInferRequest::copy_input_data(std::shared_ptr network, } } +Blob::Ptr CLDNNInferRequest::host_blob_from_device_blob(Blob::Ptr blobPtr) { + uint8_t* bufferMem = nullptr; + auto clblobPtr = std::dynamic_pointer_cast(blobPtr); + if (clblobPtr) { + const auto memPtr = getBlobImpl(clblobPtr.get())->getMemory(); + if (memPtr->get_allocation_type() == cldnn::allocation_type::usm_host) { + bufferMem = reinterpret_cast(memPtr->get_internal_params().mem); + } + } + Blob::Ptr hostBlob = create_host_blob(blobPtr->getTensorDesc(), bufferMem); + hostBlob->allocate(); + + return hostBlob; +} + void CLDNNInferRequest::allocate_inputs() { OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "CLDNNInferRequest::allocate_inputs"); auto inputLayouts = m_graph->GetInputLayouts(); @@ -777,7 +801,7 @@ void CLDNNInferRequest::allocate_inputs() { } else { auto blobPtr = create_device_blob(desc, litr->second); _deviceInputs[name] = blobPtr; - _inputs[name] = blobPtr; + _inputs[name] = host_blob_from_device_blob(blobPtr); } } } @@ -823,7 +847,7 @@ void CLDNNInferRequest::allocate_outputs() { } auto blobPtr = create_device_blob(desc, output_layout); _deviceOutputs[no.first] = blobPtr; - _outputs[no.first] = blobPtr; + _outputs[no.first] = host_blob_from_device_blob(blobPtr); outputsMap[no.first] = outputID; } } @@ -852,7 +876,8 @@ void CLDNNInferRequest::allocate_outputs_dynamic() { void CLDNNInferRequest::InferImpl() { OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "CLDNNInferRequest::InferImpl"); - + setup_stream_graph(); + std::lock_guard lk(m_graph->get_mutex()); preprocess(); enqueue(); wait(); diff --git a/inference-engine/src/cldnn_engine/cldnn_infer_request.h b/inference-engine/src/cldnn_engine/cldnn_infer_request.h index 72c924b015e964..ae152855b45b59 100644 --- a/inference-engine/src/cldnn_engine/cldnn_infer_request.h +++ b/inference-engine/src/cldnn_engine/cldnn_infer_request.h @@ -49,6 +49,11 @@ class CLDNNInferRequest : public InferenceEngine::IInferRequestInternal { void EnableProfiling() { m_useProfiling = true; } void EnableStreams() { m_useStreams = true; } + void setup_stream_graph(); + void preprocess_notify(); + void enqueue_notify(); + void wait_notify(); + void preprocess(); void enqueue(); void wait(); @@ -65,9 +70,9 @@ class CLDNNInferRequest : public InferenceEngine::IInferRequestInternal { std::map inputsMap; std::map outputsMap; - bool m_useProfiling; - bool m_useStreams; - bool m_useExternalQueue; + bool m_useProfiling = false; + bool m_useStreams = false; + bool m_useExternalQueue = false; std::shared_ptr m_graph; // dynamic batch stuff @@ -87,6 +92,7 @@ class CLDNNInferRequest : public InferenceEngine::IInferRequestInternal { const cldnn::layout& inputLayout, const InferenceEngine::Blob &inputBlob, buf_info* bi = nullptr); + InferenceEngine::Blob::Ptr host_blob_from_device_blob(const InferenceEngine::Blob::Ptr blobPtr); void allocate_inputs(); void allocate_outputs(); void allocate_inputs_dynamic(); diff --git a/inference-engine/src/cldnn_engine/cldnn_program.cpp b/inference-engine/src/cldnn_engine/cldnn_program.cpp index 22a55d743bd153..1841631937b171 100644 --- a/inference-engine/src/cldnn_engine/cldnn_program.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_program.cpp @@ -6,6 +6,7 @@ #include "ngraph/ops.hpp" #include "ngraph_ops/nms_ie_internal.hpp" #include "cldnn_itt.h" +#include "cldnn/runtime/debug_configuration.hpp" using namespace InferenceEngine; using namespace InferenceEngine::details; @@ -231,6 +232,12 @@ void Program::CreateSingleLayerPrimitive(cldnn::topology& topology, const std::s OV_ITT_SCOPED_TASK(itt::domains::CLDNNPlugin, "Program::CreateSingleLayerPrimitive"); InitProfileInfo(op->get_friendly_name(), op->get_type_name()); + GPU_DEBUG_GET_INSTANCE(debug_config); + GPU_DEBUG_IF(debug_config->verbose >= 2) { + GPU_DEBUG_COUT << "Process " << "op::v" << op->get_type_info().version << "::" << op->get_type_name() << " operation " + << "(friendly_name=" << op->get_friendly_name() << ")" << std::endl; + } + bool is_created = false; const ngraph::NodeTypeInfo* op_type_info = &op->get_type_info(); while (op_type_info != nullptr) { @@ -251,8 +258,8 @@ void Program::CreateSingleLayerPrimitive(cldnn::topology& topology, const std::s if (!is_created) { IE_THROW() << "Operation: " << op->get_friendly_name() - << " of type " << op->get_type_name() - << "(op::v" << op->get_type_info().version << ") is not supported"; + << " of type " << op->get_type_name() + << "(op::v" << op->get_type_info().version << ") is not supported"; } } diff --git a/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp b/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp index 3b015a94e57be0..f043b6e4a891b0 100644 --- a/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_remote_context.cpp @@ -204,6 +204,7 @@ CLDNNExecutionContextImpl::CLDNNExecutionContextImpl(const std::shared_ptr(params, GPU_PARAM_KEY(OCL_CONTEXT)); + + if (params.find(GPU_PARAM_KEY(OCL_QUEUE)) != params.end()) + m_external_queue = _ObjFromParamSimple(params, GPU_PARAM_KEY(OCL_QUEUE)); + + if (params.find(GPU_PARAM_KEY(OCL_CONTEXT_DEVICE_ID)) != params.end()) + ctx_device_id = _ObjFromParamSimple(params, GPU_PARAM_KEY(OCL_CONTEXT_DEVICE_ID)); } else if (GPU_PARAM_VALUE(VA_SHARED) == contextTypeStr) { m_va_display = _va_device = _ObjFromParamSimple(params, GPU_PARAM_KEY(VA_DEVICE)); m_type = ContextType::DEV_SHARED; @@ -222,16 +229,13 @@ CLDNNExecutionContextImpl::CLDNNExecutionContextImpl(const std::shared_ptrsecond.as(); } - - if (params.find(GPU_PARAM_KEY(OCL_QUEUE)) != params.end()) - m_external_queue = _ObjFromParamSimple(params, GPU_PARAM_KEY(OCL_QUEUE)); } // TODO: Parameterize this based on plugin config and compilation options auto engine_type = cldnn::engine_types::ocl; auto runtime_type = cldnn::runtime_types::ocl; // Use actual runtime and engine types - cldnn::device_query device_query(engine_type, runtime_type, _context_id, _va_device, target_tile_id); + cldnn::device_query device_query(engine_type, runtime_type, _context_id, _va_device, ctx_device_id, target_tile_id); auto device_map = device_query.get_available_devices(); auto iter = device_map.find(m_config.device_id); @@ -273,6 +277,7 @@ ParamMap CLDNNExecutionContextImpl::getParams() const { switch (m_type) { case OCL: ret[GPU_PARAM_KEY(CONTEXT_TYPE)] = GPU_PARAM_VALUE(OCL); + ret[GPU_PARAM_KEY(OCL_QUEUE)] = static_cast(m_external_queue); break; case DEV_SHARED: ret[GPU_PARAM_KEY(CONTEXT_TYPE)] = GPU_PARAM_VALUE(VA_SHARED); @@ -287,6 +292,19 @@ ParamMap CLDNNExecutionContextImpl::getParams() const { std::string CLDNNExecutionContextImpl::getDeviceName() const noexcept { auto devName = m_plugin.lock()->GetName(); + + auto engine_type = cldnn::engine_types::ocl; + auto runtime_type = cldnn::runtime_types::ocl; + // Use actual runtime and engine types + cldnn::device_query device_query(engine_type, runtime_type); + auto all_devices = device_query.get_available_devices(); + auto current_device = m_engine->get_device(); + + for (auto& kv : all_devices) { + if (current_device->is_same(kv.second)) + return devName + "." + kv.first; + } + if (!m_config.device_id.empty()) devName += "." + m_config.device_id; return devName; diff --git a/inference-engine/src/cldnn_engine/cldnn_transformations_pipeline.cpp b/inference-engine/src/cldnn_engine/cldnn_transformations_pipeline.cpp index c979d19f2626ab..d1c0eb38a01a16 100644 --- a/inference-engine/src/cldnn_engine/cldnn_transformations_pipeline.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_transformations_pipeline.cpp @@ -34,6 +34,7 @@ #include #include #include "transformations/common_optimizations/convert_quantize_dequantize.hpp" +#include "transformations/common_optimizations/convert_compression_only_to_legacy.hpp" #include #include #include @@ -163,6 +164,8 @@ void TransformationsPipeline::apply(std::shared_ptr func) { auto pass_config = manager.get_pass_config(); + pass_config->enable(); + // SpaceToDepth/DepthToSpace node implementation supports only equal input/output tensors with rank <= 5 pass_config->set_callback( diff --git a/inference-engine/src/cldnn_engine/ops/constant.cpp b/inference-engine/src/cldnn_engine/ops/constant.cpp index d2b4a37e63cd4d..26e8c2845ee5d6 100644 --- a/inference-engine/src/cldnn_engine/ops/constant.cpp +++ b/inference-engine/src/cldnn_engine/ops/constant.cpp @@ -103,7 +103,7 @@ static void CreateConstantOp(Program& p, const std::shared_ptrget_input_size(); j++) { auto& in_shape = outOp->get_input_shape(j); - if (in_shape.size() != 1) + if (in_shape.size() > 1) all_inputs_1d = false; } needsBatchInterpretation = all_inputs_1d; diff --git a/inference-engine/src/gna_plugin/CMakeLists.txt b/inference-engine/src/gna_plugin/CMakeLists.txt index a476318dc03e89..3ec2d5b089c6c3 100644 --- a/inference-engine/src/gna_plugin/CMakeLists.txt +++ b/inference-engine/src/gna_plugin/CMakeLists.txt @@ -65,10 +65,13 @@ target_compile_definitions(${TARGET_NAME}_test_static INTEGER_LOW_P USE_STATIC_IE) -target_link_libraries(${TARGET_NAME}_test_static PUBLIC inference_engine_preproc_s inference_engine_transformations libGNA::API) -target_include_directories(${TARGET_NAME}_test_static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - $ - PRIVATE $) +target_link_libraries(${TARGET_NAME}_test_static PUBLIC inference_engine_s inference_engine_preproc_s inference_engine_transformations libGNA::API) +target_include_directories(${TARGET_NAME}_test_static + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + $ + PRIVATE + $) set_target_properties(${TARGET_NAME}_test_static PROPERTIES COMPILE_PDB_NAME ${TARGET_NAME}_test_static) set_target_properties(${TARGET_NAME} ${TARGET_NAME}_test_static diff --git a/inference-engine/src/gna_plugin/backend/am_intel_dnn.cpp b/inference-engine/src/gna_plugin/backend/am_intel_dnn.cpp index d246d3406d5fa5..826cbfc3151062 100644 --- a/inference-engine/src/gna_plugin/backend/am_intel_dnn.cpp +++ b/inference-engine/src/gna_plugin/backend/am_intel_dnn.cpp @@ -270,7 +270,8 @@ void GNAPluginNS::backend::AMIntelDNN::updateNumberOfOutputsIfPoolingEnabled(Gna IE_ASSERT(gnaOp.Parameters != nullptr || gnaOp.NumberOfParameters == 0); if (gnaOp.Type == Gna2OperationTypeConvolution && inputShape.NumberOfDimensions == 2 && gnaOp.NumberOfParameters >= PoolStrideParamIdx && - gnaOp.Parameters[PoolWinParamIdx]!= nullptr && + gnaOp.Parameters != nullptr && + gnaOp.Parameters[PoolWinParamIdx] != nullptr && gnaOp.Parameters[PoolStrideParamIdx] != nullptr) { IE_ASSERT(gnaOp.Operands[OutOpIdx] != nullptr); IE_ASSERT(gnaOp.Operands[FilterOpIdx] != nullptr); diff --git a/inference-engine/src/gna_plugin/gna_executable_network.hpp b/inference-engine/src/gna_plugin/gna_executable_network.hpp index d7a9cd1bd71701..923fcc92f5ae08 100644 --- a/inference-engine/src/gna_plugin/gna_executable_network.hpp +++ b/inference-engine/src/gna_plugin/gna_executable_network.hpp @@ -67,13 +67,6 @@ class GNAExecutableNetwork : public InferenceEngine::IExecutableNetworkInternal return std::make_shared(plg, inputs, outputs); } - INFERENCE_ENGINE_DEPRECATED("Use InferRequest::QueryState instead") - std::vector QueryState() override { - IE_SUPPRESS_DEPRECATED_START - return plg->QueryState(); - IE_SUPPRESS_DEPRECATED_END - } - void Export(const std::string &modelFileName) override { plg->Export(modelFileName); } diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index fde061f91b7424..83c2c0dbaea57e 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -70,6 +70,7 @@ #include "transformations/op_conversions/lstm_cell_decomposition.hpp" #include "transformations/remove_single_input_concat.hpp" #include "transformations/broadcast_const.hpp" +#include "transformations/substitute_softsign.hpp" #include @@ -713,6 +714,7 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { manager.register_pass(); manager.register_pass(); manager.register_pass(); + manager.register_pass(); manager.register_pass(); manager.register_pass(); manager.register_pass(); @@ -781,6 +783,9 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { passes->registerPass(); } + if (fake_quantized) + passes->registerPass(); + // fake quantisation aware passes passes->registerPass(); passes->registerPass(); @@ -788,7 +793,6 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { passes->registerPass(); passes->registerPass(); - passes->registerPass(); passes->registerPass(); passes->registerPass(); diff --git a/inference-engine/src/gna_plugin/ops/softsign.cpp b/inference-engine/src/gna_plugin/ops/softsign.cpp new file mode 100644 index 00000000000000..eb10bffea2798b --- /dev/null +++ b/inference-engine/src/gna_plugin/ops/softsign.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "softsign.hpp" + +#include + +#include "ngraph/attribute_visitor.hpp" +#include "ngraph/runtime/host_tensor.hpp" + +#include +#include + +NGRAPH_RTTI_DEFINITION(GNAPluginNS::SoftSign, "SoftSign", 0); + +namespace GNAPluginNS { + +template +void softsign(const T* arg, T* out, size_t count) { + for (size_t i = 0; i < count; i++) { + out[i] = 1 / (1 + std::abs(arg[i])); + } +} + +SoftSign::SoftSign(const ngraph::Output& arg) : ov::op::util::UnaryElementwiseArithmetic(arg) { + constructor_validate_and_infer_types(); +} + +std::shared_ptr SoftSign::clone_with_new_inputs(const ngraph::OutputVector& new_args) const { + check_new_args_count(this, new_args); + return std::make_shared(new_args.at(0)); +} + +template +inline bool evaluate(const ov::runtime::Tensor& arg, ov::runtime::Tensor& out, const size_t count) { + using T = typename ngraph::element_type_traits::value_type; + softsign(arg.data(), out.data(), count); + return true; +} + +namespace { +bool evaluate_softsign(const ov::runtime::Tensor& arg, ov::runtime::Tensor& out) { + bool rc = true; + size_t count = shape_size(arg.get_shape()); + + switch (arg.get_element_type()) { + case ov::element::Type_t::f16: + rc = evaluate(arg, out, count); + break; + case ov::element::Type_t::f32: + rc = evaluate(arg, out, count); + break; + default: + rc = false; + break; + } + return rc; +} +} // namespace + +bool SoftSign::evaluate(ov::runtime::TensorVector& outputs, + const ov::runtime::TensorVector& inputs, + const ov::EvaluationContext& evaluation_context) const { + return evaluate_softsign(inputs[0], outputs[0]); +} + +bool SoftSign::has_evaluate() const { + switch (get_input_element_type(0)) { + case ngraph::element::f16: + case ngraph::element::f32: + return true; + default: + break; + } + return false; +} + +} // namespace GNAPluginNS diff --git a/inference-engine/src/gna_plugin/ops/softsign.hpp b/inference-engine/src/gna_plugin/ops/softsign.hpp new file mode 100644 index 00000000000000..ffbcbc9dbb959e --- /dev/null +++ b/inference-engine/src/gna_plugin/ops/softsign.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "openvino/op/op.hpp" +#include "ngraph/node.hpp" +#include "openvino/op/util/unary_elementwise_arithmetic.hpp" + +namespace GNAPluginNS { +/// \brief Neural Activation Function +/// f(x) = x/(1.0 + |x|) +/// +class SoftSign : public ov::op::util::UnaryElementwiseArithmetic { +public: + NGRAPH_RTTI_DECLARATION; + + SoftSign() = default; + /// \brief Constructs an SoftSign operation. + /// + /// \param data Input tensor + SoftSign(const ngraph::Output& arg); + std::shared_ptr clone_with_new_inputs(const ngraph::OutputVector& new_args) const override; + bool evaluate(ov::runtime::TensorVector& output_values, + const ov::runtime::TensorVector& input_values, + const ov::EvaluationContext & evaluation_context) const override; + bool has_evaluate() const override; +}; +} // namespace GNAPluginNS diff --git a/inference-engine/src/gna_plugin/runtime/pwl.cpp b/inference-engine/src/gna_plugin/runtime/pwl.cpp index d214f06413b9cd..de577d0a029cc0 100644 --- a/inference-engine/src/gna_plugin/runtime/pwl.cpp +++ b/inference-engine/src/gna_plugin/runtime/pwl.cpp @@ -61,7 +61,8 @@ double pivot_search(std::vector& result, const double alpha_0, const double alpha_N, const double threshold, - const bool negative) { + const bool negative, + size_t iter_num) { std::vector> t(N + 1); std::vector> alpha(N + 1); std::vector> epsilon(N + 1); @@ -114,7 +115,7 @@ double pivot_search(std::vector& result, if (fabs(epsilon[i][j]) > max_epsilon) max_epsilon = fabs(epsilon[i][j]); if (fabs(epsilon[i][j]) < min_epsilon) min_epsilon = fabs(epsilon[i][j]); } - if ((j == PWL_MAX_ITERATIONS) || (max_epsilon - min_epsilon < threshold * min_epsilon)) { + if ((j == iter_num) || (max_epsilon - min_epsilon < threshold * min_epsilon)) { pwl_t value; result.resize(0); epsilon_final = (max_epsilon + min_epsilon) / 4.0; // Andrzej's modification @@ -133,7 +134,7 @@ double pivot_search(std::vector& result, value.alpha = alpha[N][j]; value.beta = sgn * first_deriv_f(t[N - 1][j]) * (alpha[N][j] - t[N - 1][j]) + sgn * f(t[N - 1][j]) - epsilon_final; result.push_back(value); - if (j == PWL_MAX_ITERATIONS) { + if (j == iter_num) { THROW_GNA_EXCEPTION << "Failed to converge in pivot_search!"; } return(epsilon_final); @@ -178,7 +179,8 @@ double pivot_search(std::vector& result, double(*f)(const double), const double alpha_0, const double alpha_N, const double threshold, - const bool negative) { + const bool negative, + size_t iter_num) { double epsilon_final = 0.0; if (f == nullptr || @@ -189,7 +191,7 @@ double pivot_search(std::vector& result, double(*f)(const double), auto fun = [&f](double x) -> double { return f(x); }; auto first_deriv = [&first_deriv_f](double x) -> double { return first_deriv_f(x); }; - return pivot_search(result, fun, first_deriv, N, alpha_0, alpha_N, threshold, negative); + return pivot_search(result, fun, first_deriv, N, alpha_0, alpha_N, threshold, negative, iter_num); } double calculate_error_pct(const DnnActivation& activation_type, @@ -406,30 +408,37 @@ std::vector pwl_search(const DnnActivation& activation_type, switch (activation_type) { case kActSigmoid: if (u_bound == 0) negative = true; // make left half convex - err = pivot_search(pwl, sigmoid, first_deriv_sigmoid, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, sigmoid, first_deriv_sigmoid, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActTanh: if (u_bound == 0) negative = true; // make left half convex - err = pivot_search(pwl, tanh, first_deriv_tanh, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, tanh, first_deriv_tanh, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActSoftSign: if (u_bound == 0) negative = true; // make left half convex - err = pivot_search(pwl, softsign, first_deriv_softsign, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, softsign, first_deriv_softsign, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActExp: negative = true; // make function convex - err = pivot_search(pwl, exp, first_deriv_exp, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, exp, first_deriv_exp, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActLog: - err = pivot_search(pwl, log, first_deriv_log, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, log, first_deriv_log, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_LOG); break; case kActNegLog: negative = true; // make function convex - err = pivot_search(pwl, neglog, first_deriv_neglog, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, neglog, first_deriv_neglog, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_LOG); break; case kActNegHalfLog: negative = true; // make function convex - err = pivot_search(pwl, neghalflog, first_deriv_neghalflog, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, neghalflog, first_deriv_neghalflog, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_LOG); break; case kActPow: { negative = (fmod(activation_type.args.pow.exponent, 1.0) == 0) ? true : false; @@ -438,7 +447,8 @@ std::vector pwl_search(const DnnActivation& activation_type, activation_type.args.pow.offset }; auto fun = [&args](double x) -> double { return power(x, args); }; auto first_deriv = [&args](double x) -> double { return first_deriv_power(x, args); }; - err = pivot_search(pwl, fun, first_deriv, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, fun, first_deriv, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; } default: @@ -446,29 +456,36 @@ std::vector pwl_search(const DnnActivation& activation_type, } err_pct = calculate_error_pct(activation_type, l_bound, u_bound, err, samples); - while ((n_segments < PWL_MAX_ITERATIONS) && (allowed_err_pct < err_pct)) { + while ((n_segments < PWL_MAX_NUM_SEGMENTS) && (allowed_err_pct < err_pct)) { n_segments += 1; switch (activation_type) { case kActSigmoid: - err = pivot_search(pwl, sigmoid, first_deriv_sigmoid, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, sigmoid, first_deriv_sigmoid, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActTanh: - err = pivot_search(pwl, tanh, first_deriv_tanh, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, tanh, first_deriv_tanh, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActSoftSign: - err = pivot_search(pwl, softsign, first_deriv_softsign, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, softsign, first_deriv_softsign, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActExp: - err = pivot_search(pwl, exp, first_deriv_exp, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, exp, first_deriv_exp, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; case kActLog: - err = pivot_search(pwl, log, first_deriv_log, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, log, first_deriv_log, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_LOG); break; case kActNegLog: - err = pivot_search(pwl, neglog, first_deriv_neglog, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, neglog, first_deriv_neglog, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_LOG); break; case kActNegHalfLog: - err = pivot_search(pwl, neghalflog, first_deriv_neghalflog, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, neghalflog, first_deriv_neghalflog, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_LOG); break; case kActPow: { auto args = std::tuple{ activation_type.args.pow.exponent, @@ -476,7 +493,8 @@ std::vector pwl_search(const DnnActivation& activation_type, activation_type.args.pow.offset }; auto fun = [&args](double x) { return power(x, args); }; auto first_deriv = [&args](double x) { return first_deriv_power(x, args); }; - err = pivot_search(pwl, fun, first_deriv, n_segments, l_bound, u_bound, threshold, negative); + err = pivot_search(pwl, fun, first_deriv, n_segments, l_bound, u_bound, + threshold, negative, PWL_MAX_ITERATIONS_DEFAULT); break; } default: @@ -485,7 +503,7 @@ std::vector pwl_search(const DnnActivation& activation_type, err_pct = calculate_error_pct(activation_type, l_bound, u_bound, err, samples); } - if (n_segments >= PWL_MAX_ITERATIONS) { + if (n_segments >= PWL_MAX_NUM_SEGMENTS) { THROW_GNA_EXCEPTION << "Failed to converge in pwl_search!"; } } diff --git a/inference-engine/src/gna_plugin/runtime/pwl.h b/inference-engine/src/gna_plugin/runtime/pwl.h index cf908f9e7652cb..1d11543e60320f 100644 --- a/inference-engine/src/gna_plugin/runtime/pwl.h +++ b/inference-engine/src/gna_plugin/runtime/pwl.h @@ -21,7 +21,8 @@ #define IDENTITY_NUM_SEGMENTS 3 #define IDENTITY_DOMAIN 10.0f #define PWL_MAX_ERR_PERCENT 1.0f -#define PWL_MAX_ITERATIONS 2000 +#define PWL_MAX_ITERATIONS_DEFAULT 2000 +#define PWL_MAX_ITERATIONS_LOG 5000 #define PWL_MAX_NUM_SEGMENTS 128 #define PWL_DESIGN_THRESHOLD 0.1f #define PWL_DESIGN_SAMPLES 500 @@ -61,7 +62,8 @@ double pivot_search(std::vector& result, double(*f)(const double), const double alpha_0, const double alpha_N, const double threshold, - const bool negative); + const bool negative, + size_t iter_num); inline std::vector negative_pwl(const std::vector& pwl); diff --git a/inference-engine/src/gna_plugin/transformations/remove_single_input_concat.hpp b/inference-engine/src/gna_plugin/transformations/remove_single_input_concat.hpp index 7730c36d9afe07..364d48a8458db4 100644 --- a/inference-engine/src/gna_plugin/transformations/remove_single_input_concat.hpp +++ b/inference-engine/src/gna_plugin/transformations/remove_single_input_concat.hpp @@ -10,6 +10,18 @@ namespace GNAPluginNS { /** * @brief remove concat layers with single input + * + * Searches for next pattern + * Any input layer + * | + * Concat + * | + * Any output layer + * + * And transforms to + * Any input layer + * | + * Any output layer */ class RemoveSingleInputConcat : public ngraph::pass::MatcherPass { public: diff --git a/inference-engine/src/gna_plugin/transformations/substitute_softsign.cpp b/inference-engine/src/gna_plugin/transformations/substitute_softsign.cpp new file mode 100644 index 00000000000000..36329ed7c34b6b --- /dev/null +++ b/inference-engine/src/gna_plugin/transformations/substitute_softsign.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "transformations/substitute_softsign.hpp" + +#include "transformations/utils/transformation_helper.hpp" +#include "transformations/utils/utils.hpp" + +#include +#include +#include +#include +#include + +using namespace GNAPluginNS; + +NGRAPH_RTTI_DEFINITION(SubstituteSoftsign, "SubstituteSoftsign", 0); + +using Node = std::shared_ptr; + +namespace { + +void DoTransformation(Node start_node, Node last_node) { + auto activation = std::make_shared(start_node); + activation->set_friendly_name(last_node->get_friendly_name()); + ngraph::copy_runtime_info(last_node, activation); + ngraph::replace_node(last_node, activation); +} + +class IsConstValueAcceptable { +public: + IsConstValueAcceptable(double expected_value) : + m_expected_value(expected_value) {} + + bool operator()(const ngraph::Output& output) const { + auto node = std::dynamic_pointer_cast(output.get_node_shared_ptr()); + if (!node) + return false; + + float value; + if (!ngraph::op::util::get_single_value(node, value)) { + return false; + } + + return (value == m_expected_value); + } + +private: + const double m_expected_value; +}; + +} // namespace + +SubstituteSoftsign::SubstituteSoftsign() { + MATCHER_SCOPE(SubstituteSoftsign); + + auto root = ngraph::pattern::any_input(); + auto abs = ngraph::pattern::wrap_type({root}); + + auto add_const = ngraph::pattern::wrap_type(IsConstValueAcceptable(1.0)); + auto add = ngraph::pattern::wrap_type({abs, add_const}); + + auto power_const = ngraph::pattern::wrap_type(IsConstValueAcceptable(-1.0)); + auto power = ngraph::pattern::wrap_type({add, power_const}); + + auto multiply = ngraph::pattern::wrap_type({root, power}); + auto divide = ngraph::pattern::wrap_type({root, add}); + auto last = std::make_shared(ngraph::OutputVector{multiply, divide}); + + ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher& m) { + const auto& pattern_map = m.get_pattern_value_map(); + auto root_node = pattern_map.at(root).get_node_shared_ptr(); + + auto last_node_it = pattern_map.find(multiply); + if (last_node_it == pattern_map.end()) + last_node_it = pattern_map.find(divide); + auto last_node = last_node_it->second.get_node_shared_ptr(); + + DoTransformation(root_node, last_node); + + return true; + }; + + auto m = std::make_shared(last, matcher_name); + this->register_matcher(m, callback); +} diff --git a/inference-engine/src/gna_plugin/transformations/substitute_softsign.hpp b/inference-engine/src/gna_plugin/transformations/substitute_softsign.hpp new file mode 100644 index 00000000000000..fe11241c04f003 --- /dev/null +++ b/inference-engine/src/gna_plugin/transformations/substitute_softsign.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +namespace GNAPluginNS { + +/** + * @brief Current version of ModelOptimizer substitutes SoftSign activation + * function with next subgraph + * a layer + * | \ + * abs \ + * | | + * add | + * | | + * power | + * \ / + * Divide + * + * See model-optimizer/extensions/front/softsign_replacer.py + * + * The ConvertDivide transformation from CommonOptimizations + * substitutes Divide with {-1} and add constant {1} + * - GNA supports Power [0, 2.8] + * - Add, Power, Divide layers are more perfomance expensive in GNA + * than SoftSign PWL + * + * Legacy SubstituteSoftSignPass supports irv7 model where SoftSign subgraph + * could have been without add layer. Current ModelOptimezer always generates + * SoftSign subgraph with that layer. + * + * SubstituteSoftsign transformation does backward substitution to SoftSign. + * TODO: remove that pass as soon as ModelOptimizer will not substitute SoftSign activation + */ +class SubstituteSoftsign : public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + SubstituteSoftsign(); +}; + +} // namespace GNAPluginNS diff --git a/inference-engine/src/hetero_plugin/CMakeLists.txt b/inference-engine/src/hetero_plugin/CMakeLists.txt index c7fbe6eecf8b65..39aa7191bd3fd0 100644 --- a/inference-engine/src/hetero_plugin/CMakeLists.txt +++ b/inference-engine/src/hetero_plugin/CMakeLists.txt @@ -16,7 +16,7 @@ ie_faster_build(${TARGET_NAME} UNITY ) -target_link_libraries(${TARGET_NAME} PRIVATE pugixml inference_engine +target_link_libraries(${TARGET_NAME} PRIVATE pugixml::static inference_engine ngraph inference_engine_transformations) ie_add_api_validator_post_build_step(TARGET ${TARGET_NAME}) diff --git a/inference-engine/src/inference_engine/CMakeLists.txt b/inference-engine/src/inference_engine/CMakeLists.txt index 4dc8fe70d705bf..0430c5336616cb 100644 --- a/inference-engine/src/inference_engine/CMakeLists.txt +++ b/inference-engine/src/inference_engine/CMakeLists.txt @@ -4,10 +4,16 @@ set (TARGET_NAME "inference_engine") -if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") +if(ENABLE_TBBBIND_2_5) + # try to find prebuilt version of tbbbind_2_5 find_package(TBBBIND_2_5 QUIET) - if (TBBBIND_2_5_FOUND) - message(STATUS "Static tbbbind_2_5 package was found") + if(TBBBIND_2_5_FOUND) + message(STATUS "Static tbbbind_2_5 package is found") + set_target_properties(${TBBBIND_2_5_IMPORTED_TARGETS} PROPERTIES + INTERFACE_COMPILE_DEFINITIONS TBBBIND_2_5_AVAILABLE) + if(NOT BUILD_SHARED_LIBS) + set(install_tbbbind ON) + endif() endif() endif() @@ -101,10 +107,10 @@ source_group("include" FILES ${LIBRARY_HEADERS} ${PUBLIC_HEADERS}) add_library(${TARGET_NAME}_plugin_api INTERFACE) target_include_directories(${TARGET_NAME}_plugin_api INTERFACE - "${IE_MAIN_SOURCE_DIR}/src/plugin_api" $ - ${PUBLIC_HEADERS_DIR} - ${PUBLIC_HEADERS_DIR}/ie) + $ + $ + $) target_link_libraries(${TARGET_NAME}_plugin_api INTERFACE pugixml::static openvino::itt openvino::util) @@ -137,7 +143,7 @@ target_include_directories(${TARGET_NAME}_obj SYSTEM PRIVATE $:$> # for ie_ir_version.hpp $ $ $) @@ -146,7 +152,6 @@ target_link_libraries(${TARGET_NAME}_obj PRIVATE ${TARGET_NAME}_reader_api openv set_ie_threading_interface_for(${TARGET_NAME}_obj) if (TBBBIND_2_5_FOUND) - target_compile_definitions(${TARGET_NAME}_obj PRIVATE -DTBBBIND_2_5_AVAILABLE) target_link_libraries(${TARGET_NAME}_obj PRIVATE ${TBBBIND_2_5_IMPORTED_TARGETS}) endif() @@ -171,7 +176,6 @@ ie_add_vs_version_file(NAME ${TARGET_NAME} set_ie_threading_interface_for(${TARGET_NAME}) if (TBBBIND_2_5_FOUND) - target_compile_definitions(${TARGET_NAME} PRIVATE -DTBBBIND_2_5_AVAILABLE) target_link_libraries(${TARGET_NAME} PRIVATE ${TBBBIND_2_5_IMPORTED_TARGETS}) endif() @@ -198,44 +202,33 @@ ie_add_api_validator_post_build_step(TARGET ${TARGET_NAME}) # Static library used for unit tests which are always built -if(BUILD_SHARED_LIBS) - add_library(${TARGET_NAME}_s STATIC EXCLUDE_FROM_ALL - $ - $ - ${IE_STATIC_DEPENDENT_FILES}) - - set_ie_threading_interface_for(${TARGET_NAME}_s) - if (TBBBIND_2_5_FOUND) - target_compile_definitions(${TARGET_NAME}_s PRIVATE -DTBBBIND_2_5_AVAILABLE) - target_link_libraries(${TARGET_NAME}_s PRIVATE ${TBBBIND_2_5_IMPORTED_TARGETS}) - endif() +add_library(${TARGET_NAME}_s STATIC EXCLUDE_FROM_ALL + $ + $ + ${IE_STATIC_DEPENDENT_FILES}) - target_include_directories(${TARGET_NAME}_s PUBLIC - $ - "${CMAKE_CURRENT_SOURCE_DIR}/src" - "${IE_MAIN_SOURCE_DIR}/src/legacy_api/src") +set_ie_threading_interface_for(${TARGET_NAME}_s) +if (TBBBIND_2_5_FOUND) + target_link_libraries(${TARGET_NAME}_s PRIVATE ${TBBBIND_2_5_IMPORTED_TARGETS}) +endif() - if(WIN32) - set_target_properties(${TARGET_NAME}_s PROPERTIES COMPILE_PDB_NAME ${TARGET_NAME}_s) - endif() +target_include_directories(${TARGET_NAME}_s PUBLIC + $ + $ + $/src>) - target_link_libraries(${TARGET_NAME}_s PRIVATE openvino::itt ${CMAKE_DL_LIBS} ngraph - frontend_manager::static inference_engine_transformations pugixml::static) +if(WIN32) + set_target_properties(${TARGET_NAME}_s PROPERTIES COMPILE_PDB_NAME ${TARGET_NAME}_s) +endif() - target_compile_definitions(${TARGET_NAME}_s PUBLIC USE_STATIC_IE) +target_link_libraries(${TARGET_NAME}_s PRIVATE openvino::itt ${CMAKE_DL_LIBS} ngraph + frontend_manager::static inference_engine_preproc_s inference_engine_transformations pugixml::static) - set_target_properties(${TARGET_NAME}_s PROPERTIES - EXCLUDE_FROM_ALL ON - INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) -else() - # for static OpenVINO build we can re-use inference_engine which is already static - add_library(${TARGET_NAME}_s ALIAS ${TARGET_NAME}) +target_compile_definitions(${TARGET_NAME}_s PUBLIC USE_STATIC_IE) - target_include_directories(${TARGET_NAME} PUBLIC - $ - "${CMAKE_CURRENT_SOURCE_DIR}/src" - "${IE_MAIN_SOURCE_DIR}/src/legacy_api/src") -endif() +set_target_properties(${TARGET_NAME}_s PROPERTIES + EXCLUDE_FROM_ALL ON + INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) # LTO @@ -263,6 +256,11 @@ if(THREADING MATCHES "^(TBB|TBB_AUTO)$") list(APPEND PATH_VARS "IE_TBB_DIR") endif() +if(install_tbbbind) + set(IE_TBBBIND_DIR "${TBBBIND_2_5}") + list(APPEND PATH_VARS "IE_TBBBIND_DIR") +endif() + # install only downloaded TBB, system one is not installed if(THREADING MATCHES "^(TBB|TBB_AUTO)$" AND TBBROOT MATCHES ${TEMP}) ie_cpack_add_component(tbb REQUIRED) @@ -285,13 +283,26 @@ if(THREADING MATCHES "^(TBB|TBB_AUTO)$" AND TBBROOT MATCHES ${TEMP}) COMPONENT tbb) set(IE_TBB_DIR_INSTALL "3rdparty/tbb/cmake") - install(FILES "${TBB}/cmake/TBBConfig.cmake" "${TBB}/cmake/TBBConfigVersion.cmake" DESTINATION runtime/${IE_TBB_DIR_INSTALL} COMPONENT tbb) endif() +if(install_tbbbind) + install(DIRECTORY "${TBBBIND_2_5}/lib" + DESTINATION runtime/3rdparty/tbb_bind_2_5 + COMPONENT tbb) + install(FILES "${TBBBIND_2_5}/LICENSE" + DESTINATION runtime/3rdparty/tbb_bind_2_5 + COMPONENT tbb) + + set(IE_TBBBIND_DIR_INSTALL "3rdparty/tbb_bind_2_5/cmake") + install(FILES "${TBBBIND_2_5}/cmake/TBBBIND_2_5Config.cmake" + DESTINATION runtime/${IE_TBBBIND_DIR_INSTALL} + COMPONENT tbb) +endif() + # Install Inference Engine ie_cpack_add_component(core REQUIRED DEPENDS ${core_components}) @@ -309,28 +320,32 @@ install(TARGETS ${TARGET_NAME} EXPORT OpenVINOTargets # TODO: remove later once samples are updated runtime/include/ie) -install(FILES $/plugins.xml - DESTINATION ${IE_CPACK_RUNTIME_PATH} - COMPONENT core) - -# for InferenceEngineUnitTest -if(WIN32) - install(FILES $/plugins.xml - DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL) -else() +if(BUILD_SHARED_LIBS) install(FILES $/plugins.xml - DESTINATION tests/lib COMPONENT tests EXCLUDE_FROM_ALL) + DESTINATION ${IE_CPACK_RUNTIME_PATH} + COMPONENT core) + + # for InferenceEngineUnitTest + if(WIN32) + install(FILES $/plugins.xml + DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL) + else() + install(FILES $/plugins.xml + DESTINATION tests/lib COMPONENT tests EXCLUDE_FROM_ALL) + endif() endif() +# Install static libraries for case BUILD_SHARED_LIBS=OFF + +ov_install_static_lib(${TARGET_NAME}_plugin_api core) + # Install cmake scripts -if(BUILD_SHARED_LIBS) - install(EXPORT OpenVINOTargets - FILE OpenVINOTargets.cmake - NAMESPACE openvino:: - DESTINATION runtime/cmake - COMPONENT core_dev) -endif() +install(EXPORT OpenVINOTargets + FILE OpenVINOTargets.cmake + NAMESPACE openvino:: + DESTINATION runtime/cmake + COMPONENT core_dev) set(IE_NGRAPH_DIR "${CMAKE_BINARY_DIR}/ngraph") set(IE_INCLUDE_DIR "${PUBLIC_HEADERS_DIR}/ie") @@ -349,6 +364,7 @@ configure_package_config_file("${OpenVINO_SOURCE_DIR}/cmake/templates/OpenVINOCo set(IE_INCLUDE_DIR "include/ie") set(IE_NGRAPH_DIR ".") set(IE_TBB_DIR "${IE_TBB_DIR_INSTALL}") +set(IE_TBBBIND_DIR "${IE_TBBBIND_DIR_INSTALL}") set(IE_PARALLEL_CMAKE "cmake/ie_parallel.cmake") configure_package_config_file("${OpenVINO_SOURCE_DIR}/cmake/templates/InferenceEngineConfig.cmake.in" diff --git a/inference-engine/src/inference_engine/include/ie/cpp/ie_executable_network.hpp b/inference-engine/src/inference_engine/include/ie/cpp/ie_executable_network.hpp index 6c8dab11542d78..fc205e966f65ab 100644 --- a/inference-engine/src/inference_engine/include/ie/cpp/ie_executable_network.hpp +++ b/inference-engine/src/inference_engine/include/ie/cpp/ie_executable_network.hpp @@ -190,18 +190,6 @@ class INFERENCE_ENGINE_API_CLASS(ExecutableNetwork) { */ INFERENCE_ENGINE_DEPRECATED("Use ExecutableNetwork::CreateInferRequest instead") InferRequest::Ptr CreateInferRequestPtr(); - - /** - * @deprecated Use InferRequest::QueryState instead - * @brief Gets state control interface for given executable network. - * - * State control essential for recurrent networks - * - * @return A vector of Memory State objects - */ - INFERENCE_ENGINE_DEPRECATED("Use InferRequest::QueryState instead") - std::vector QueryState(); - IE_SUPPRESS_DEPRECATED_END }; } // namespace InferenceEngine diff --git a/inference-engine/src/inference_engine/include/ie/details/ie_so_loader.h b/inference-engine/src/inference_engine/include/ie/details/ie_so_loader.h index 555f91542591a6..c0135cfc6983f0 100644 --- a/inference-engine/src/inference_engine/include/ie/details/ie_so_loader.h +++ b/inference-engine/src/inference_engine/include/ie/details/ie_so_loader.h @@ -20,14 +20,13 @@ namespace details { * @brief This class provides an OS shared module abstraction */ class INFERENCE_ENGINE_API_CLASS(SharedObjectLoader) { - class Impl; - std::shared_ptr _impl; + std::shared_ptr _so; public: /** * @brief Constructs from existing object */ - SharedObjectLoader(const std::shared_ptr& impl); + SharedObjectLoader(const std::shared_ptr& so); /** * @brief Default constructor diff --git a/inference-engine/src/inference_engine/include/ie/details/ie_so_pointer.hpp b/inference-engine/src/inference_engine/include/ie/details/ie_so_pointer.hpp index 87c5fbfdb0f616..9158d6f02cd4aa 100644 --- a/inference-engine/src/inference_engine/include/ie/details/ie_so_pointer.hpp +++ b/inference-engine/src/inference_engine/include/ie/details/ie_so_pointer.hpp @@ -77,8 +77,8 @@ class SOPointer { /** * @brief Constructs an object with existing reference - * @brief Constructs an object with existing loader - * @param soLoader Existing pointer to a library loader + * @param so Existing pointer to a library loader + * @param ptr Existing reference to an object */ SOPointer(const SharedObjectLoader& so, const std::shared_ptr& ptr) : _so{so}, _ptr{ptr} {} @@ -165,8 +165,6 @@ class SOPointer { using CreateF = void(std::shared_ptr&); reinterpret_cast(create)(_ptr); } - } catch (const std::runtime_error& ex) { - IE_THROW() << ex.what(); } catch (...) { details::Rethrow(); } @@ -179,8 +177,6 @@ class SOPointer { try { using CreateF = void(std::shared_ptr&); reinterpret_cast(_so.get_symbol(SOCreatorTrait::name))(_ptr); - } catch (const std::runtime_error& ex) { - IE_THROW() << ex.what(); } catch (...) { details::Rethrow(); } diff --git a/inference-engine/src/inference_engine/include/ie/gpu/gpu_params.hpp b/inference-engine/src/inference_engine/include/ie/gpu/gpu_params.hpp index 2ceff349214ba2..d7e36c95ac5df9 100644 --- a/inference-engine/src/inference_engine/include/ie/gpu/gpu_params.hpp +++ b/inference-engine/src/inference_engine/include/ie/gpu/gpu_params.hpp @@ -62,6 +62,12 @@ DECLARE_GPU_PARAM_VALUE(VA_SHARED); */ DECLARE_GPU_PARAM_KEY(OCL_CONTEXT, gpu_handle_param); +/** + * @brief This key identifies ID of device in OpenCL context + * if multiple devices are present in the context + */ +DECLARE_GPU_PARAM_KEY(OCL_CONTEXT_DEVICE_ID, int); + /** * @brief In case of multi-tile system, * this key identifies tile within given context diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/gpu/dx.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/dx.hpp similarity index 86% rename from inference-engine/src/inference_engine/include/openvino/runtime/gpu/dx.hpp rename to inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/dx.hpp index b43f1a780ae9b5..8da0821145a50b 100644 --- a/inference-engine/src/inference_engine/include/openvino/runtime/gpu/dx.hpp +++ b/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/dx.hpp @@ -7,20 +7,29 @@ * shared Video Acceleration device contexts * and shared memory tensors which contain Video Acceleration surfaces * - * @file openvino/runtime/gpu/dx.hpp + * @file openvino/runtime/gpu/ocl/dx.hpp */ #pragma once +#ifndef NOMINMAX +# define NOMINMAX +#endif + +#ifndef _WIN32 +# error "OpenCL DirectX interoperability is supported only on Windows platforms" +#endif + #include #include #include -#include "openvin/runtime/gpu/ocl.hpp" +#include "openvino/runtime/gpu/ocl/ocl.hpp" namespace ov { namespace runtime { namespace gpu { +namespace ocl { /** * @brief This class represents an abstraction for GPU plugin remote tensor @@ -62,10 +71,10 @@ class D3DSurface2DTensor : public ClImage2DTensor { * @param remote_tensor remote tensor to check */ static void type_check(const RemoteTensor& remote_tensor) { - remote_type_check(remote_context.get_params(), - {{GPU_PARAM_KEY(DEV_OBJECT_HANDLE), {}}, - {GPU_PARAM_KEY(VA_PLANE), {}}, - {GPU_PARAM_KEY(SHARED_MEM_TYPE), {GPU_PARAM_VALUE(VA_SURFACE)}}}); + RemoteTensor::type_check(remote_tensor, + {{GPU_PARAM_KEY(DEV_OBJECT_HANDLE), {}}, + {GPU_PARAM_KEY(VA_PLANE), {}}, + {GPU_PARAM_KEY(SHARED_MEM_TYPE), {GPU_PARAM_VALUE(VA_SURFACE)}}}); } /** @@ -94,7 +103,6 @@ class D3DSurface2DTensor : public ClImage2DTensor { */ class D3DContext : public ClContext { using RemoteContext::create_tensor; - static constexpr const char* device_name = "GPU"; public: /** @@ -102,8 +110,8 @@ class D3DContext : public ClContext { * @param remote_context remote context to check */ static void type_check(const RemoteContext& remote_context) { - remote_type_check( - remote_context.get_params(), + RemoteContext::type_check( + remote_context, {{GPU_PARAM_KEY(VA_DEVICE), {}}, {GPU_PARAM_KEY(CONTEXT_TYPE), {GPU_PARAM_VALUE(VA_SHARED)}}}); } @@ -119,12 +127,15 @@ class D3DContext : public ClContext { * @brief Constructs D3DContext remote context object from ID3D11Device * @param core OpenVINO Runtime Core object instance * @param device A pointer to ID3D11Device to be used to create a remote context + * @param target_tile_id Desired tile id within given context for multi-tile system. Default value (-1) means + * that root device should be used */ - D3DContext(Core& core, ID3D11Device* device) { + D3DContext(Core& core, ID3D11Device* device, int target_tile_id = -1) : ClContext(core, (cl_context) nullptr) { // clang-format off ParamMap context_params = { {GPU_PARAM_KEY(CONTEXT_TYPE), GPU_PARAM_VALUE(VA_SHARED)}, - {GPU_PARAM_KEY(VA_DEVICE), static_cast(device)} + {GPU_PARAM_KEY(VA_DEVICE), static_cast(device)}, + {GPU_PARAM_KEY(TILE_ID), target_tile_id} }; *this = core.create_context(device_name, context_params); } @@ -137,7 +148,7 @@ class D3DContext : public ClContext { * @param nv12_surf A ID3D11Texture2D instance to create NV12 tensor from * @return A pair of remote tensors for each plane */ - std::pair create_tensor_nv12(const size_t height, const size_t width, const ID3D11Texture2D* nv12_surf) { + std::pair create_tensor_nv12(const size_t height, const size_t width, ID3D11Texture2D* nv12_surf) { ParamMap tensor_params = {{GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(VA_SURFACE)}, {GPU_PARAM_KEY(DEV_OBJECT_HANDLE), static_cast(nv12_surf)}, {GPU_PARAM_KEY(VA_PLANE), uint32_t(0)}}; @@ -155,7 +166,7 @@ class D3DContext : public ClContext { * @param buffer A pointer to ID3D11Buffer instance to create remote tensor based on * @return A remote tensor instance */ - D3DBufferTensor create_tensor(const element::Type type, const Shape& shape, const ID3D11Buffer* buffer) { + D3DBufferTensor create_tensor(const element::Type type, const Shape& shape, ID3D11Buffer* buffer) { ParamMap params = {{GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(DX_BUFFER)}, {GPU_PARAM_KEY(DEV_OBJECT_HANDLE), static_cast(buffer)}}; create_tensor(type, shape, params); @@ -180,6 +191,7 @@ class D3DContext : public ClContext { return create_tensor(type, shape, params); } }; +} // namespace ocl } // namespace gpu } // namespace runtime } // namespace ov diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/ocl.hpp similarity index 95% rename from inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl.hpp rename to inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/ocl.hpp index 24ccf2ae9af3d9..d205b7f0548e0f 100644 --- a/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl.hpp +++ b/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/ocl.hpp @@ -6,7 +6,7 @@ * @brief a header that defines wrappers for internal GPU plugin-specific * OpenCL context and OpenCL shared memory tensors * - * @file openvino/runtime/gpu/ocl.hpp + * @file openvino/runtime/gpu/ocl/ocl.hpp */ #pragma once @@ -15,13 +15,14 @@ #include "gpu/gpu_params.hpp" #include "openvino/runtime/core.hpp" -#include "openvino/runtime/gpu/ocl_wrapper.hpp" +#include "openvino/runtime/gpu/ocl/ocl_wrapper.hpp" #include "openvino/runtime/remote_context.hpp" #include "openvino/runtime/remote_tensor.hpp" namespace ov { namespace runtime { namespace gpu { +namespace ocl { /** * @brief Shortcut for defining a handle parameter @@ -123,7 +124,12 @@ class ClImage2DTensor : public RemoteTensor { * ExecutableNetwork::get_context() or Core::create_context() calls. */ class ClContext : public RemoteContext { +protected: using RemoteContext::create_tensor; + + /** + * @brief GPU device name + */ static constexpr const char* device_name = "GPU"; public: @@ -141,10 +147,12 @@ class ClContext : public RemoteContext { * @brief Constructs context object from user-supplied OpenCL context handle * @param core A reference to OpenVINO Runtime Core object * @param ctx A OpenCL context to be used to create shared remote context + * @param ctx_device_id An ID of device to be used from ctx */ - ClContext(Core& core, cl_context ctx) { + ClContext(Core& core, cl_context ctx, int ctx_device_id = 0) { ParamMap context_params = {{GPU_PARAM_KEY(CONTEXT_TYPE), GPU_PARAM_VALUE(OCL)}, - {GPU_PARAM_KEY(OCL_CONTEXT), static_cast(ctx)}}; + {GPU_PARAM_KEY(OCL_CONTEXT), static_cast(ctx)}, + {GPU_PARAM_KEY(OCL_CONTEXT_DEVICE_ID), ctx_device_id}}; *this = core.create_context(device_name, context_params); } @@ -245,6 +253,7 @@ class ClContext : public RemoteContext { return create_tensor(type, shape, params); } }; +} // namespace ocl } // namespace gpu } // namespace runtime } // namespace ov diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl_wrapper.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/ocl_wrapper.hpp similarity index 100% rename from inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl_wrapper.hpp rename to inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/ocl_wrapper.hpp diff --git a/inference-engine/src/inference_engine/include/openvino/runtime/gpu/va.hpp b/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/va.hpp similarity index 89% rename from inference-engine/src/inference_engine/include/openvino/runtime/gpu/va.hpp rename to inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/va.hpp index fc82d0f5990ce0..91f6c037f694c9 100644 --- a/inference-engine/src/inference_engine/include/openvino/runtime/gpu/va.hpp +++ b/inference-engine/src/inference_engine/include/openvino/runtime/gpu/ocl/va.hpp @@ -7,14 +7,18 @@ * shared Video Acceleration device contexts * and shared memory tensors which contain Video Acceleration surfaces * - * @file openvino/runtime/gpu/va.hpp + * @file openvino/runtime/gpu/ocl/va.hpp */ #pragma once +#ifdef _WIN32 +# error "OpenCL VA-API interoperability is supported only on Linux-based platforms" +#endif + #include #include -#include "openvino/runtime/gpu/ocl.hpp" +#include "openvino/runtime/gpu/ocl/ocl.hpp" // clang-format off #include @@ -23,6 +27,7 @@ namespace ov { namespace runtime { namespace gpu { +namespace ocl { /** * @brief This class represents an abstraction for GPU plugin remote tensor @@ -68,7 +73,6 @@ class VASurfaceTensor : public ClImage2DTensor { */ class VAContext : public ClContext { using RemoteContext::create_tensor; - static constexpr const char* device_name = "GPU"; public: /** @@ -76,8 +80,8 @@ class VAContext : public ClContext { * @param remote_context remote context to check */ static void type_check(const RemoteContext& remote_context) { - remote_type_check( - remote_context.get_params(), + RemoteContext::type_check( + remote_context, {{GPU_PARAM_KEY(VA_DEVICE), {}}, {GPU_PARAM_KEY(CONTEXT_TYPE), {GPU_PARAM_VALUE(VA_SHARED)}}}); } @@ -93,10 +97,13 @@ class VAContext : public ClContext { * @brief Constructs remote context object from VA display handle * @param core OpenVINO Runtime Core object * @param device A `VADisplay` to create remote context from + * @param target_tile_id Desired tile id within given context for multi-tile system. Default value (-1) means + * that root device should be used */ - VAContext(Core& core, VADisplay device) { + VAContext(Core& core, VADisplay device, int target_tile_id = -1) : ClContext(core, (cl_context) nullptr) { ParamMap context_params = {{GPU_PARAM_KEY(CONTEXT_TYPE), GPU_PARAM_VALUE(VA_SHARED)}, - {GPU_PARAM_KEY(VA_DEVICE), static_cast(device)}}; + {GPU_PARAM_KEY(VA_DEVICE), static_cast(device)}, + {GPU_PARAM_KEY(TILE_ID), target_tile_id}}; *this = core.create_context(device_name, context_params); } @@ -138,6 +145,7 @@ class VAContext : public ClContext { return create_tensor(type, shape, params); } }; +} // namespace ocl } // namespace gpu } // namespace runtime } // namespace ov diff --git a/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp b/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp index d811b8378d4f88..24a6af02d64ced 100644 --- a/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp +++ b/inference-engine/src/inference_engine/src/cpp/ie_executable_network.cpp @@ -65,16 +65,6 @@ ExecutableNetwork::operator IExecutableNetwork::Ptr() { return std::make_shared(_impl); } -std::vector ExecutableNetwork::QueryState() { - std::vector controller; - EXEC_NET_CALL_STATEMENT({ - for (auto&& state : _impl->QueryState()) { - controller.emplace_back(VariableState{_so, state}); - } - }); - return controller; -} - InferRequest ExecutableNetwork::CreateInferRequest() { EXEC_NET_CALL_STATEMENT(return {_so, _impl->CreateInferRequest()}); } diff --git a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp index 9a8abf1eec13c6..47a9d7fab75867 100644 --- a/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp +++ b/inference-engine/src/inference_engine/src/cpp_interfaces/interface/ie_iexecutable_network_internal.cpp @@ -87,10 +87,6 @@ std::shared_ptr IExecutableNetworkInternal::GetExecGraphInfo() IE_THROW(NotImplemented); } -std::vector> IExecutableNetworkInternal::QueryState() { - IE_THROW(NotImplemented); -} - void IExecutableNetworkInternal::SetPointerToPlugin(const std::shared_ptr& plugin) { _plugin = plugin; } diff --git a/inference-engine/src/inference_engine/src/file_utils.cpp b/inference-engine/src/inference_engine/src/file_utils.cpp index a646a456d8edfd..ea962e2b679472 100644 --- a/inference-engine/src/inference_engine/src/file_utils.cpp +++ b/inference-engine/src/inference_engine/src/file_utils.cpp @@ -16,14 +16,12 @@ #include #include "ie_common.h" +#include "openvino/util/file_util.hpp" + #ifndef _WIN32 # include # include # include -# ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT -# include -# include -# endif #else # if defined(WINAPI_FAMILY) && !WINAPI_PARTITION_DESKTOP # error "Only WINAPI_PARTITION_DESKTOP is supported, because of GetModuleHandleEx[A|W]" @@ -34,90 +32,20 @@ # include #endif -#ifdef _WIN32 - -# include - -// Copied from linux libc sys/stat.h: -# define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) - -/// @brief Windows-specific 'mkdir' wrapper -# define makedir(dir) _mkdir(dir) - -/// @brief Max length of absolute file path -# define MAX_ABS_PATH _MAX_PATH -/// @brief Get absolute file path, returns NULL in case of error -# define get_absolute_path(result, path) _fullpath(result, path.c_str(), MAX_ABS_PATH) - -/// @brief Windows-specific 'stat' wrapper -# define stat _stat - -#else - -# include - -/// @brief mkdir wrapper -# define makedir(dir) mkdir(dir, 0755) - -/// @brief Max length of absolute file path -# define MAX_ABS_PATH PATH_MAX -/// @brief Get absolute file path, returns NULL in case of error -# define get_absolute_path(result, path) realpath(path.c_str(), result) - -#endif - long long FileUtils::fileSize(const char* charfilepath) { -#if defined(OPENVINO_ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) - std::wstring widefilename = ov::util::string_to_wstring(charfilepath); - const wchar_t* fileName = widefilename.c_str(); -#elif defined(__ANDROID__) || defined(ANDROID) - std::string fileName = charfilepath; - std::string::size_type pos = fileName.find('!'); - if (pos != std::string::npos) { - fileName = fileName.substr(0, pos); - } -#else - const char* fileName = charfilepath; -#endif - std::ifstream in(fileName, std::ios_base::binary | std::ios_base::ate); - return in.tellg(); + return ov::util::file_size(charfilepath); } std::string FileUtils::absoluteFilePath(const std::string& filePath) { - std::string absolutePath; - absolutePath.resize(MAX_ABS_PATH); - auto absPath = get_absolute_path(&absolutePath[0], filePath); - if (!absPath) { - IE_THROW() << "Can't get absolute file path for [" << filePath << "], err = " << strerror(errno); - } - absolutePath.resize(strlen(absPath)); - return absolutePath; + return ov::util::get_absolute_file_path(filePath); } bool FileUtils::directoryExists(const std::string& path) { - struct stat sb; - - if (stat(path.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) { - return true; - } - return false; + return ov::util::directory_exists(path); } void FileUtils::createDirectoryRecursive(const std::string& dirPath) { - if (dirPath.empty() || directoryExists(dirPath)) { - return; - } - - std::size_t pos = dirPath.rfind(ov::util::FileTraits::file_separator); - if (pos != std::string::npos) { - createDirectoryRecursive(dirPath.substr(0, pos)); - } - - int err = makedir(dirPath.c_str()); - if (err != 0 && errno != EEXIST) { - // TODO: in case of exception it may be needed to remove all created sub-directories - IE_THROW() << "Couldn't create directory [" << dirPath << "], err=" << strerror(errno) << ")"; - } + ov::util::create_directory_recursive(dirPath); } namespace InferenceEngine { @@ -148,11 +76,11 @@ static std::string getIELibraryPathA() { GetModuleFileNameA(hm, (LPSTR)ie_library_path, sizeof(ie_library_path)); return getPathName(std::string(ie_library_path)); #elif defined(__APPLE__) || defined(__linux__) -# if defined(OPENVINO_STATIC_LIBRARY) || defined(USE_STATIC_IE) +# ifdef USE_STATIC_IE # ifdef __APPLE__ Dl_info info; dladdr(reinterpret_cast(getIELibraryPath), &info); - std::string path = getPathName(std::string(info.dli_fname)).c_str(); + std::string path = getPathName(std::string(info.dli_fname)); # else char result[PATH_MAX]; ssize_t count = readlink("/proc/self/exe", result, PATH_MAX); @@ -162,8 +90,9 @@ static std::string getIELibraryPathA() { # else Dl_info info; dladdr(reinterpret_cast(getIELibraryPath), &info); - return getPathName(std::string(info.dli_fname)).c_str(); -# endif // OPENVINO_STATIC_LIBRARY || USE_STATIC_IE + std::string path = FileUtils::absoluteFilePath(info.dli_fname); + return getPathName(path); +# endif // USE_STATIC_IE #else # error "Unsupported OS" #endif // _WIN32 @@ -192,6 +121,7 @@ std::wstring getIELibraryPathW() { #endif // OPENVINO_ENABLE_UNICODE_PATH_SUPPORT std::string getIELibraryPath() { + (void)getIELibraryPathA; #ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT return ov::util::wstring_to_string(getIELibraryPathW()); #else diff --git a/inference-engine/src/inference_engine/src/ie_core.cpp b/inference-engine/src/inference_engine/src/ie_core.cpp index 104f1e40ceee5f..0004c48e462f9a 100644 --- a/inference-engine/src/inference_engine/src/ie_core.cpp +++ b/inference-engine/src/inference_engine/src/ie_core.cpp @@ -728,11 +728,11 @@ class CoreImpl : public ie::ICore, public std::enable_shared_from_this>(); - } catch (ie::Exception&) { + } catch (const ie::Exception&) { // plugin is not created by e.g. invalid env - } catch (ov::Exception&) { + } catch (const ov::Exception&) { // plugin is not created by e.g. invalid env - } catch (std::runtime_error&) { + } catch (const std::runtime_error&) { // plugin is not created by e.g. invalid env } catch (const std::exception& ex) { IE_THROW() << "An exception is thrown while trying to create the " << deviceName @@ -854,8 +854,7 @@ class CoreImpl : public ie::ICore, public std::enable_shared_from_thissecond; - return result; + return plugins.emplace(deviceName, plugin).first->second; } catch (const ie::Exception& ex) { IE_THROW() << "Failed to create plugin " << ov::util::from_file_path(desc.libraryLocation) << " for device " << deviceName << "\n" diff --git a/inference-engine/src/inference_engine/src/ie_data.cpp b/inference-engine/src/inference_engine/src/ie_data.cpp index 269d28fe8aeee7..70677970f65646 100644 --- a/inference-engine/src/inference_engine/src/ie_data.cpp +++ b/inference-engine/src/inference_engine/src/ie_data.cpp @@ -133,7 +133,13 @@ void Data::reshape(const ngraph::PartialShape& dims, Layout layout) { if (dims.is_static()) { reshape(SizeVector(dims.to_shape()), layout); } else { - tensorDesc = TensorDesc(tensorDesc.getPrecision(), layout); + SizeVector d; + if (dims.rank().is_static()) { + d = SizeVector(dims.rank().get_length(), 0); + } else { + d = SizeVector{0}; + } + tensorDesc = TensorDesc(tensorDesc.getPrecision(), d, layout); _impl->pShape = dims; } } diff --git a/inference-engine/src/inference_engine/src/ie_network_reader.cpp b/inference-engine/src/inference_engine/src/ie_network_reader.cpp index cb55c706c89f1c..a0c4c7b1b2d5aa 100644 --- a/inference-engine/src/inference_engine/src/ie_network_reader.cpp +++ b/inference-engine/src/inference_engine/src/ie_network_reader.cpp @@ -20,7 +20,9 @@ #include "ie_common.h" #include "ie_icnn_network.hpp" #include "ie_input_info.hpp" -#include "ie_ir_version.hpp" +#ifdef ENABLE_IR_V7_READER +# include "ie_ir_version.hpp" +#endif #include "ie_itt.hpp" #include "ie_reader.hpp" #include "ngraph/function.hpp" @@ -307,7 +309,7 @@ CNNNetwork convert_to_cnnnetwork(std::shared_ptr& function, // only for IR cases we need preprocessing or postprocessing steps if (is_ir) { using namespace ov::preprocess; - PrePostProcessor prepost; + PrePostProcessor prepost(function); auto ir_version_impl = std::dynamic_pointer_cast>(it->second); OPENVINO_ASSERT(ir_version_impl != nullptr, "Failed to extract IR version from 'version' attribute"); @@ -318,7 +320,7 @@ CNNNetwork convert_to_cnnnetwork(std::shared_ptr& function, for (size_t i = 0; i < inputs.size(); ++i) { const auto ngraph_type = inputs[i].get_element_type(); const auto legacy_type = details::toLegacyType(ngraph_type, true); - prepost.input(ov::preprocess::InputInfo(i).tensor(InputTensorInfo().set_element_type(legacy_type))); + prepost.input(i).tensor().set_element_type(legacy_type); } // in order to support the following scenarios for IR v10 cases: @@ -349,10 +351,10 @@ CNNNetwork convert_to_cnnnetwork(std::shared_ptr& function, const auto ngraph_type = outputs[i].get_element_type(); const auto legacy_type = details::toLegacyType(ngraph_type, false); - prepost.output(OutputInfo(i).tensor(OutputTensorInfo().set_element_type(legacy_type))); + prepost.output(i).tensor().set_element_type(legacy_type); } - function = prepost.build(function); + function = prepost.build(); // Set version to 10 rt_info["version"] = std::make_shared>(10); @@ -378,14 +380,14 @@ CNNNetwork convert_to_cnnnetwork(std::shared_ptr& function, if (old_api_type == ov::element::undefined) old_api_type = parameter->get_element_type(); - prepost.input(ov::preprocess::InputInfo(i) - .tensor(InputTensorInfo().set_element_type(old_api_type)) - .preprocess(PreProcessSteps().convert_layout(old_api_transpose_args))); + auto& pre_input = prepost.input(i); + pre_input.tensor().set_element_type(old_api_type); + pre_input.preprocess().convert_layout(old_api_transpose_args); } - auto& resuls = function->get_results(); - for (size_t i = 0; i < resuls.size(); ++i) { - const auto& result = resuls[i]; + auto& results = function->get_results(); + for (size_t i = 0; i < results.size(); ++i) { + const auto& result = results[i]; ov::RTMap& rtInfo = result->get_rt_info(); const auto it = rtInfo.find(old_api_map_key); if (it == rtInfo.end()) @@ -402,9 +404,9 @@ CNNNetwork convert_to_cnnnetwork(std::shared_ptr& function, if (old_api_type == ov::element::undefined) old_api_type = result->get_element_type(); - prepost.output(OutputInfo(i) - .postprocess(PostProcessSteps().convert_layout(old_api_transpose_args)) - .tensor(OutputTensorInfo().set_element_type(old_api_type))); + auto& post_output = prepost.output(i); + post_output.postprocess().convert_layout(old_api_transpose_args); + post_output.tensor().set_element_type(old_api_type); // remove old api once we applied it rtInfo.erase(it); @@ -413,7 +415,7 @@ CNNNetwork convert_to_cnnnetwork(std::shared_ptr& function, // Set version to 10 rt_info["version"] = std::make_shared>(10); - function = prepost.build(function); + function = prepost.build(); } } @@ -422,8 +424,8 @@ CNNNetwork convert_to_cnnnetwork(std::shared_ptr& function, OPENVINO_SUPPRESS_DEPRECATED_END } -ngraph::frontend::FrontEndManager& get_frontend_manager() { - static ngraph::frontend::FrontEndManager manager; +ov::frontend::FrontEndManager& get_frontend_manager() { + static ov::frontend::FrontEndManager manager; return manager; } @@ -471,8 +473,8 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath, // Try to load with FrontEndManager auto& manager = get_frontend_manager(); - ngraph::frontend::FrontEnd::Ptr FE; - ngraph::frontend::InputModel::Ptr inputModel; + ov::frontend::FrontEnd::Ptr FE; + ov::frontend::InputModel::Ptr inputModel; ov::VariantVector params{ov::make_variant(model_path)}; @@ -533,8 +535,8 @@ CNNNetwork details::ReadNetwork(const std::string& model, // Try to load with FrontEndManager auto& manager = get_frontend_manager(); - ngraph::frontend::FrontEnd::Ptr FE; - ngraph::frontend::InputModel::Ptr inputModel; + ov::frontend::FrontEnd::Ptr FE; + ov::frontend::InputModel::Ptr inputModel; ov::VariantVector params{ov::make_variant(&modelStream)}; if (weights) { diff --git a/inference-engine/src/inference_engine/src/shared_object_loader.cpp b/inference-engine/src/inference_engine/src/shared_object_loader.cpp index 5e794ac1d789f6..85fbbb636185fa 100644 --- a/inference-engine/src/inference_engine/src/shared_object_loader.cpp +++ b/inference-engine/src/inference_engine/src/shared_object_loader.cpp @@ -10,47 +10,33 @@ namespace InferenceEngine { namespace details { -struct SharedObjectLoader::Impl { - std::shared_ptr shared_object = nullptr; - - explicit Impl(const std::shared_ptr& shared_object_) : shared_object{shared_object_} {} - - explicit Impl(const char* pluginName) : shared_object{ov::util::load_shared_object(pluginName)} {} - -#ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT - explicit Impl(const wchar_t* pluginName) : Impl(ov::util::wstring_to_string(pluginName).c_str()) {} -#endif // OPENVINO_ENABLE_UNICODE_PATH_SUPPORT - - void* get_symbol(const char* symbolName) const { - return ov::util::get_symbol(shared_object, symbolName); - } -}; - -SharedObjectLoader::SharedObjectLoader(const std::shared_ptr& shared_object) { - _impl.reset(new Impl(shared_object)); -} +SharedObjectLoader::SharedObjectLoader(const std::shared_ptr& so) : _so(so) {} #ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT -SharedObjectLoader::SharedObjectLoader(const wchar_t* pluginName) { - _impl.reset(new Impl(pluginName)); -} +SharedObjectLoader::SharedObjectLoader(const wchar_t* pluginName) + : SharedObjectLoader(ov::util::wstring_to_string(pluginName).c_str()) {} #endif -SharedObjectLoader::SharedObjectLoader(const char* pluginName) { - _impl.reset(new Impl(pluginName)); +SharedObjectLoader::SharedObjectLoader(const char* pluginName) : _so{nullptr} { + try { + _so = ov::util::load_shared_object(pluginName); + } catch (const std::runtime_error& ex) { + IE_THROW(GeneralError) << ex.what(); + } } SharedObjectLoader::~SharedObjectLoader() {} void* SharedObjectLoader::get_symbol(const char* symbolName) const { - if (_impl == nullptr) { - IE_THROW(NotAllocated) << "SharedObjectLoader is not initialized"; + try { + return ov::util::get_symbol(_so, symbolName); + } catch (const std::runtime_error& ex) { + IE_THROW(NotFound) << ex.what(); } - return _impl->get_symbol(symbolName); } std::shared_ptr SharedObjectLoader::get() const { - return _impl->shared_object; + return _so; } } // namespace details diff --git a/inference-engine/src/legacy_api/CMakeLists.txt b/inference-engine/src/legacy_api/CMakeLists.txt index 1bf44deb97cc55..1acd566e5b314e 100644 --- a/inference-engine/src/legacy_api/CMakeLists.txt +++ b/inference-engine/src/legacy_api/CMakeLists.txt @@ -26,7 +26,7 @@ endif() file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp) -add_library(${TARGET_NAME}_obj OBJECT +add_library(${TARGET_NAME}_obj OBJECT EXCLUDE_FROM_ALL ${LIBRARY_SRC} ${PUBLIC_HEADERS}) @@ -39,7 +39,7 @@ target_compile_definitions(${TARGET_NAME}_obj PRIVATE IMPLEMENT_INFERENCE_ENGINE target_include_directories(${TARGET_NAME}_obj PRIVATE ${PUBLIC_HEADERS_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src - ${IE_MAIN_SOURCE_DIR}/src/inference_engine/src # For CNNNetworkNGraphImpl + $/src # For CNNNetworkNGraphImpl $ $ $ @@ -53,7 +53,7 @@ add_cpplint_target(${TARGET_NAME}_obj_cpplint FOR_TARGETS ${TARGET_NAME}_obj) # Create library -add_library(${TARGET_NAME} +add_library(${TARGET_NAME} EXCLUDE_FROM_ALL ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp $) @@ -64,7 +64,8 @@ target_link_libraries(${TARGET_NAME} PUBLIC inference_engine PRIVATE pugixml::static openvino::itt ngraph inference_engine_transformations) -target_include_directories(${TARGET_NAME} INTERFACE ${PUBLIC_HEADERS_DIR}) +target_include_directories(${TARGET_NAME} INTERFACE + $) ie_add_api_validator_post_build_step(TARGET ${TARGET_NAME}) @@ -79,6 +80,10 @@ openvino_developer_export_targets(COMPONENT inference_engine TARGETS ${TARGET_NA # install -install(TARGETS ${TARGET_NAME} - RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core - LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) +if(BUILD_SHARED_LIBS) + install(TARGETS ${TARGET_NAME} + RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core + LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) +else() + ov_install_static_lib(${TARGET_NAME} core) +endif() diff --git a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/pad_ie.hpp b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/pad_ie.hpp index b94af5ada5ddab..6a0d96287d5360 100644 --- a/inference-engine/src/legacy_api/include/legacy/ngraph_ops/pad_ie.hpp +++ b/inference-engine/src/legacy_api/include/legacy/ngraph_ops/pad_ie.hpp @@ -23,6 +23,8 @@ class INFERENCE_ENGINE_API_CLASS(PadIE) : public Op { explicit PadIE(const std::shared_ptr& pad); + PadIE(const Output& input, PadMode pad_mode, CoordinateDiff pads_begin, CoordinateDiff pads_end, Shape output_shape, float pad_value); + size_t get_version() const override { return 1; } void validate_and_infer_types() override; diff --git a/inference-engine/src/legacy_api/src/ngraph_ops/pad_ie.cpp b/inference-engine/src/legacy_api/src/ngraph_ops/pad_ie.cpp index e3cecc67214517..8d22a28f6f7770 100644 --- a/inference-engine/src/legacy_api/src/ngraph_ops/pad_ie.cpp +++ b/inference-engine/src/legacy_api/src/ngraph_ops/pad_ie.cpp @@ -37,12 +37,22 @@ op::PadIE::PadIE(const std::shared_ptr& pad) constructor_validate_and_infer_types(); } +op::PadIE::PadIE(const Output& input, PadMode pad_mode, CoordinateDiff pads_begin, CoordinateDiff pads_end, Shape output_shape, float pad_value) + : Op({input}) + , m_pad_mode(pad_mode) + , m_pads_begin(pads_begin) + , m_pads_end(pads_end) + , m_output_shape(output_shape) + , m_pad_value(pad_value) { + constructor_validate_and_infer_types(); +} + void op::PadIE::validate_and_infer_types() { set_output_type(0, get_input_element_type(0), m_output_shape); } shared_ptr op::PadIE::clone_with_new_inputs(const OutputVector& new_args) const { - return nullptr; + return std::make_shared(new_args.at(0), m_pad_mode, m_pads_begin, m_pads_end, m_output_shape, m_pad_value); } bool op::PadIE::visit_attributes(AttributeVisitor& visitor) { diff --git a/inference-engine/src/low_precision_transformations/CMakeLists.txt b/inference-engine/src/low_precision_transformations/CMakeLists.txt index 10c7162ecb7003..4cbb9c1b33ca0f 100644 --- a/inference-engine/src/low_precision_transformations/CMakeLists.txt +++ b/inference-engine/src/low_precision_transformations/CMakeLists.txt @@ -17,13 +17,11 @@ source_group("include" FILES ${PUBLIC_HEADERS}) # Create library -add_library(${TARGET_NAME} +add_library(${TARGET_NAME} EXCLUDE_FROM_ALL ${LIBRARY_SRC} ${PUBLIC_HEADERS}) -ie_faster_build(${TARGET_NAME} - UNITY -) +ie_faster_build(${TARGET_NAME} UNITY) ie_add_vs_version_file(NAME ${TARGET_NAME} FILEDESCRIPTION "Inference Engine LP transformations library") @@ -31,7 +29,8 @@ ie_add_vs_version_file(NAME ${TARGET_NAME} target_link_libraries(${TARGET_NAME} PUBLIC inference_engine_transformations PRIVATE openvino::itt) -target_include_directories(${TARGET_NAME} PUBLIC ${PUBLIC_HEADERS_DIR}) +target_include_directories(${TARGET_NAME} PUBLIC + $) add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME}) @@ -47,6 +46,10 @@ openvino_developer_export_targets(COMPONENT inference_engine TARGETS ${TARGET_NA # install -install(TARGETS ${TARGET_NAME} - RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core - LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) +if(BUILD_SHARED_LIBS) + install(TARGETS ${TARGET_NAME} + RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core + LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) +else() + ov_install_static_lib(${TARGET_NAME} core) +endif() diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/common/fake_quantize_dequantization.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/common/fake_quantize_dequantization.hpp index a9fba5234d1846..0da82810c972cd 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/common/fake_quantize_dequantization.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/common/fake_quantize_dequantization.hpp @@ -29,7 +29,7 @@ class LP_TRANSFORMATIONS_API FakeQuantizeDequantization { const std::shared_ptr& multiply, const std::shared_ptr& multiplyConstant); - bool empty() const; + bool empty() const noexcept; bool multiplyHasZeroOrDenormal() const; bool isShared() const; bool isLowPrecision() const; diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/convolution.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/convolution.hpp index 5542d04d70adb3..b49fcc89c4aee4 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/convolution.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/convolution.hpp @@ -16,8 +16,8 @@ class LP_TRANSFORMATIONS_API ConvolutionTransformation : public WeightableLayerT NGRAPH_RTTI_DECLARATION; ConvolutionTransformation(const Params& params = Params()); bool transform(TransformationContext& context, ngraph::pattern::Matcher &m) override; - bool isQuantized(const std::shared_ptr& layer) const noexcept override; - static bool isQuantizedStatic(const std::shared_ptr& layer) noexcept; + bool isQuantized(const std::shared_ptr& layer) const override; + static bool isQuantizedStatic(const std::shared_ptr& layer); }; } // namespace low_precision diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp index 35b5d806be1a7b..a1176e71efffc7 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/convolution_backprop_data.hpp @@ -16,8 +16,8 @@ class LP_TRANSFORMATIONS_API ConvolutionBackpropDataTransformation : public Weig ConvolutionBackpropDataTransformation(const Params& params = Params()); bool transform(TransformationContext& context, ngraph::pattern::Matcher &m) override; bool canBeTransformed(const TransformationContext& context, std::shared_ptr op) const override; - bool isQuantized(const std::shared_ptr& layer) const noexcept override; - static bool isQuantizedStatic(const std::shared_ptr& layer) noexcept; + bool isQuantized(const std::shared_ptr& layer) const override; + static bool isQuantizedStatic(const std::shared_ptr& layer); }; } // namespace low_precision diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/group_convolution.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/group_convolution.hpp index d53c37b8df93b8..b54921faf69a01 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/group_convolution.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/group_convolution.hpp @@ -16,8 +16,8 @@ class LP_TRANSFORMATIONS_API GroupConvolutionTransformation : public Convolution NGRAPH_RTTI_DECLARATION; GroupConvolutionTransformation(const Params& params = Params()); bool transform(TransformationContext& context, ngraph::pattern::Matcher &m) override; - bool isQuantized(const std::shared_ptr& layer) const noexcept override; - static bool isQuantizedStatic(const std::shared_ptr& layer) noexcept; + bool isQuantized(const std::shared_ptr& layer) const override; + static bool isQuantizedStatic(const std::shared_ptr& layer); }; } // namespace low_precision diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp index 17a5cf567e131e..81c25e7f28bef4 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/layer_transformation.hpp @@ -56,6 +56,10 @@ class LP_TRANSFORMATIONS_API DataPrecision { max(max), hasZeroPoint(hasZeroPoint) {} + bool empty() const noexcept { + return (precision == element::undefined) && (min == 0.f) && (max == 0.f) && (!hasZeroPoint); + } + static bool isSupported(const element::Type& precision) { static const std::set lowPrecision = { element::i8, element::u8, @@ -76,28 +80,17 @@ class LP_TRANSFORMATIONS_API DataPrecision { return -8.f; case element::i8: switch (levels) { + case 16: + return -8.f; case 255: return -127.f; - case 256: + default: return -128.f; } - break; case element::i16: - switch (levels) { - case 65536: - return -32768.f; - case 65535: - return -32767.f; - } - break; + return levels == 65535 ? -32767.f : -32768.f; case element::i32: - switch (levels) { - case static_cast(4294967296): - return -2147483648.f; - case 4294967295: - return -2147483647.f; - } - break; + return -2147483647.f; // -2147483647.f == -2147483648.f case element::f16: return -1.0e15f; case element::f32: @@ -113,19 +106,29 @@ class LP_TRANSFORMATIONS_API DataPrecision { case element::u4: return 15.f; case element::u8: - return 255.f; + switch (levels) { + case 16: + return 15.f; + default: + return 255.f; + } case element::u16: return 65535.f; case element::u32: - return 4294967296.f; + return 4294967296.f; // 4294967296.f == 4294967295.f case element::i4: return 7.f; case element::i8: - return 127.f; + switch (levels) { + case 16: + return 7.f; + default: + return 127.f; + } case element::i16: return 32767.f; case element::i32: - return 2147483647.f; + return 2147483648.f; // 2147483648.f == 2147483647.f case element::f16: return 1.0e15f; case element::f32: @@ -141,6 +144,10 @@ class LP_TRANSFORMATIONS_API DataPrecision { return 254.f; } else if (maxLevelsForPrecision == 256ul) { return 255.f; + } else if (maxLevelsForPrecision == 16ul) { + return 15.f; + } else if (maxLevelsForPrecision == 15ul) { + return 14.f; } else { THROW_TRANSFORMATION_EXCEPTION << "unexpected quantization level " << maxLevelsForPrecision; } @@ -249,7 +256,7 @@ class LP_TRANSFORMATIONS_API LayerTransformation : public ngraph::pass::MatcherP // return true if operation can be quantized and false otherwise // for example: if convolution operation weights are not quantized, then isQuantize returns false and true otherwise // note: dequantization operations on activations are absent during method execution - virtual bool isQuantized(const std::shared_ptr& layer) const noexcept; + virtual bool isQuantized(const std::shared_ptr& layer) const; // return true if operation can be preserved for precision // note: dequantization operations on activations are absent during method execution diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp index 1ca49a05d162ef..cb0f56e51fc17e 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/network_helper.hpp @@ -210,6 +210,11 @@ class LP_TRANSFORMATIONS_API NetworkHelper { static bool isPrecisionPreserved(const std::shared_ptr& node); + static void insertDequantizationAfter( + const std::shared_ptr& originalNode, + const std::shared_ptr& dequantization, + const std::shared_ptr& newNode); + static void replaceAttributeInNodes( std::shared_ptr f, const std::string& name, diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/quantization_details.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/quantization_details.hpp index a1c2f1ca4976b1..975dca8cc532ba 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/quantization_details.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/quantization_details.hpp @@ -51,6 +51,8 @@ class LP_TRANSFORMATIONS_API QuantizationDetails { float getOutputLowValue(const size_t channel) const; float getOutputHighValue(const size_t channel) const; + bool empty() const noexcept; + static bool isSupportedLevel(const size_t level); const size_t levels; diff --git a/inference-engine/src/low_precision_transformations/include/low_precision/reduce_sum.hpp b/inference-engine/src/low_precision_transformations/include/low_precision/reduce_sum.hpp index 5053545fbff5bb..82e8dd2888321f 100644 --- a/inference-engine/src/low_precision_transformations/include/low_precision/reduce_sum.hpp +++ b/inference-engine/src/low_precision_transformations/include/low_precision/reduce_sum.hpp @@ -17,7 +17,7 @@ namespace low_precision { class LP_TRANSFORMATIONS_API ReduceSumTransformation : public ReduceBaseTransformation { public: NGRAPH_RTTI_DECLARATION; - ReduceSumTransformation(const Params& params); + ReduceSumTransformation(const Params& params = Params()); bool isPrecisionPreserved(std::shared_ptr reduce) const noexcept override; bool canBeTransformed(const TransformationContext& context, std::shared_ptr reduce) const override; diff --git a/inference-engine/src/low_precision_transformations/src/add.cpp b/inference-engine/src/low_precision_transformations/src/add.cpp index 0928e355e14fd2..a56dc64a585d81 100644 --- a/inference-engine/src/low_precision_transformations/src/add.cpp +++ b/inference-engine/src/low_precision_transformations/src/add.cpp @@ -206,7 +206,9 @@ bool AddTransformation::transform(TransformationContext& context, ngraph::patter inputs[emptyPathIndex] = dequantizationEmptyPath.data; inputs[fullPathIndex] = std::make_shared( newSubtractFullPathValues == nullptr ? - fullPathInput : + (fullPathInput.get_element_type() != newMultiplyFullPathValues->get_element_type() ? + std::make_shared(fullPathInput, newMultiplyFullPathValues->get_element_type()) : + fullPathInput) : std::make_shared( // precision on branch with dequantization operations can be different with dequantization precision, // for example: FP16 model with FP32 dequantization @@ -225,7 +227,7 @@ bool AddTransformation::transform(TransformationContext& context, ngraph::patter ngraph::op::TemporaryReplaceOutputType(newAddOrSubtract, element::f32).get(), ngraph::op::TemporaryReplaceOutputType(multiplyEmptyPathValues, element::f32).get()); - replace_node(add, newMultiply); + NetworkHelper::insertDequantizationAfter(add, newMultiply, newAddOrSubtract); NetworkHelper::copyInfo(add, newAddOrSubtract); ngraph::copy_runtime_info({ add, newMultiply }, newMultiply); } diff --git a/inference-engine/src/low_precision_transformations/src/clamp.cpp b/inference-engine/src/low_precision_transformations/src/clamp.cpp index 4c1c10efadead8..c7c10619a8cd3f 100644 --- a/inference-engine/src/low_precision_transformations/src/clamp.cpp +++ b/inference-engine/src/low_precision_transformations/src/clamp.cpp @@ -70,8 +70,7 @@ bool ClampTransformation::transform(TransformationContext& context, ngraph::patt replacement = std::make_shared(newClamp->input_value(0), min, max); } - replace_node(newClamp, replacement); - replacement->set_friendly_name(newClamp->get_friendly_name()); + replace_node_update_name(newClamp, replacement); element::Type outputClampType = dequantization.multiply ? dequantization.multiply->get_output_element_type(0) : diff --git a/inference-engine/src/low_precision_transformations/src/concat.cpp b/inference-engine/src/low_precision_transformations/src/concat.cpp index 19d4f8daa3716e..cc5f933e1d0810 100644 --- a/inference-engine/src/low_precision_transformations/src/concat.cpp +++ b/inference-engine/src/low_precision_transformations/src/concat.cpp @@ -160,7 +160,7 @@ bool ConcatTransformation::transform(TransformationContext& context, ngraph::pat lastDequantization = multiply; } - replace_node(concat, lastDequantization); + NetworkHelper::insertDequantizationAfter(concat, lastDequantization, newConcat); NetworkHelper::copyInfo(concat, newConcat); updateOutput(context, lastDequantization, newConcat); return true; diff --git a/inference-engine/src/low_precision_transformations/src/convolution.cpp b/inference-engine/src/low_precision_transformations/src/convolution.cpp index 0884ccc847bf38..8a8ff7f29d5be3 100644 --- a/inference-engine/src/low_precision_transformations/src/convolution.cpp +++ b/inference-engine/src/low_precision_transformations/src/convolution.cpp @@ -43,11 +43,11 @@ ConvolutionTransformation::ConvolutionTransformation(const Params& params) : Wei this->register_matcher(m, callback); } -bool ConvolutionTransformation::isQuantized(const std::shared_ptr& layer) const noexcept { +bool ConvolutionTransformation::isQuantized(const std::shared_ptr& layer) const { return ConvolutionTransformation::isQuantizedStatic(layer); } -bool ConvolutionTransformation::isQuantizedStatic(const std::shared_ptr& layer) noexcept { +bool ConvolutionTransformation::isQuantizedStatic(const std::shared_ptr& layer) { return WeightableLayerTransformation::isQuantizedStatic(layer, false); } @@ -81,6 +81,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph convolution = NetworkHelper::separateInStandaloneBranch(convolution); FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(convolution); + std::shared_ptr newMultiplyAfter; { std::shared_ptr subtract; if (dequantization.subtract != nullptr) { @@ -172,13 +173,13 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph } NetworkHelper::copyInfo(convolution, relaxedNewConvolution); - std::shared_ptr newMultiplyAfter = std::make_shared>( + newMultiplyAfter = std::make_shared>( std::vector{ deqPrecision, deqPrecision }, std::vector{ dequantization.multiply->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(relaxedNewConvolution, deqPrecision).get(), ngraph::op::TemporaryReplaceOutputType(newMultiplyAfterConst, deqPrecision).get()); - replace_node(convolution, newMultiplyAfter); + NetworkHelper::insertDequantizationAfter(convolution, newMultiplyAfter, relaxedNewConvolution); convolution = newMultiplyAfter->input_value(0).get_node_shared_ptr(); if (ov::is_type(convolution->get_input_node_ptr(0))) { @@ -242,7 +243,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph }); NetworkHelper::copyInfo(convolution, newConvolution); - auto newMultiplyAfter = std::make_shared( + newMultiplyAfter = std::make_shared( newConvolution, foldConvert( fold_reshape( @@ -250,7 +251,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph std::make_shared(element::u64, Shape{ newScaleShape.size() }, newScaleShape), false), convolution->get_output_element_type(0))); - replace_node(convolution, newMultiplyAfter); + NetworkHelper::insertDequantizationAfter(convolution, newMultiplyAfter, newConvolution); convolution = newMultiplyAfter->input_value(0).get_node_shared_ptr(); } @@ -308,8 +309,7 @@ bool ConvolutionTransformation::transform(TransformationContext &context, ngraph } } - std::shared_ptr finalDequantization = NetworkHelper::optimizeMultipliesAfter( - convolution->output(0).get_target_inputs().begin()->get_node()->shared_from_this()); + const auto finalDequantization = NetworkHelper::optimizeMultipliesAfter(newMultiplyAfter); ngraph::copy_runtime_info({ convolution, finalDequantization }, finalDequantization); updateOutput(context, finalDequantization, convolution); diff --git a/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp b/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp index 2e71e77ac8fb99..288c897de45c04 100644 --- a/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp +++ b/inference-engine/src/low_precision_transformations/src/convolution_backprop_data.cpp @@ -53,11 +53,11 @@ ConvolutionBackpropDataTransformation::ConvolutionBackpropDataTransformation(con this->register_matcher(m, callback); } -bool ConvolutionBackpropDataTransformation::isQuantized(const std::shared_ptr& layer) const noexcept { +bool ConvolutionBackpropDataTransformation::isQuantized(const std::shared_ptr& layer) const { return ConvolutionBackpropDataTransformation::isQuantizedStatic(layer); } -bool ConvolutionBackpropDataTransformation::isQuantizedStatic(const std::shared_ptr& layer) noexcept { +bool ConvolutionBackpropDataTransformation::isQuantizedStatic(const std::shared_ptr& layer) { return WeightableLayerTransformation::isQuantizedStatic(layer, false); } @@ -98,6 +98,7 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con convolutionBackpropData = NetworkHelper::separateInStandaloneBranch(convolutionBackpropData); FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(convolutionBackpropData); + std::shared_ptr newMultiplyAfter; { if (dequantization.subtract != nullptr) { NetworkHelper::optimizeSubtract(dequantization.subtract); @@ -116,13 +117,13 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con std::vector{deqPrecision, deqPrecision}, std::vector{deqPrecision}); - const auto newMultiplyAfter = std::make_shared>( + newMultiplyAfter = std::make_shared>( std::vector{ deqPrecision, deqPrecision }, std::vector{ dequantization.multiply->get_output_element_type(0) }, ngraph::op::TemporaryReplaceOutputType(relaxedConvolutionBackpropData, deqPrecision).get(), ngraph::op::TemporaryReplaceOutputType(newMultiplyAfterConst, deqPrecision).get()); + NetworkHelper::insertDequantizationAfter(convolutionBackpropData, newMultiplyAfter, relaxedConvolutionBackpropData); - replace_node(convolutionBackpropData, newMultiplyAfter); convolutionBackpropData = newMultiplyAfter->get_input_node_shared_ptr(0); inputs[0] = convolutionBackpropData->get_input_node_ptr(0)->input_value(0); if (ov::is_type(convolutionBackpropData->get_input_node_ptr(0))) { @@ -154,15 +155,17 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con auto inputs = convolutionBackpropData->input_values(); inputs[1] = multiplyFromWeights->input_value(0); - auto newMultiplyAfter = std::make_shared( - convolutionBackpropData->clone_with_new_inputs(inputs), + + const auto newconvolutionBackpropData = convolutionBackpropData->copy_with_new_inputs(inputs); + newMultiplyAfter = std::make_shared( + newconvolutionBackpropData, foldConvert( fold_reshape( multiplyFromWeights->input_value(1), std::make_shared(element::u64, Shape{ newScaleShape.size() }, newScaleShape), false), convolutionBackpropData->get_output_element_type(0))); - replace_node(convolutionBackpropData, newMultiplyAfter); + NetworkHelper::insertDequantizationAfter(convolutionBackpropData, newMultiplyAfter, newconvolutionBackpropData); convolutionBackpropData = newMultiplyAfter->get_input_node_shared_ptr(0); } @@ -202,8 +205,8 @@ bool ConvolutionBackpropDataTransformation::transform(TransformationContext &con convolutionBackpropData = newConvolution; } } - std::shared_ptr finalDequantization = NetworkHelper::optimizeMultipliesAfter( - convolutionBackpropData->output(0).get_target_inputs().begin()->get_node()->shared_from_this()); + + const auto finalDequantization = NetworkHelper::optimizeMultipliesAfter(newMultiplyAfter); ngraph::copy_runtime_info({ convolutionBackpropData, finalDequantization }, finalDequantization); updateOutput(context, finalDequantization, convolutionBackpropData); diff --git a/inference-engine/src/low_precision_transformations/src/fake_quantize_decomposition.cpp b/inference-engine/src/low_precision_transformations/src/fake_quantize_decomposition.cpp index 18429587d18518..d13d3b54f2e5c2 100644 --- a/inference-engine/src/low_precision_transformations/src/fake_quantize_decomposition.cpp +++ b/inference-engine/src/low_precision_transformations/src/fake_quantize_decomposition.cpp @@ -29,6 +29,7 @@ FakeQuantizeDecompositionTransformation::FakeQuantizeDecompositionTransformation if (transformation_callback(op)) { return false; } + return transform(*context, m); }; @@ -230,7 +231,7 @@ std::tuple, std::shared_ptr> decomposeFakeQuantize( deqPrecision, newFakeQuantizeLayer); - replace_node(layer, dequantization.multiply); + NetworkHelper::insertDequantizationAfter(layer, dequantization.multiply, newFakeQuantizeLayer); std::vector> sourceNodes{ layer }; std::vector> targetNodes{ newFakeQuantizeLayer, dequantization.multiply }; diff --git a/inference-engine/src/low_precision_transformations/src/fake_quantize_dequantization.cpp b/inference-engine/src/low_precision_transformations/src/fake_quantize_dequantization.cpp index 52e651b6ca0576..46b56716081cb0 100644 --- a/inference-engine/src/low_precision_transformations/src/fake_quantize_dequantization.cpp +++ b/inference-engine/src/low_precision_transformations/src/fake_quantize_dequantization.cpp @@ -34,7 +34,7 @@ FakeQuantizeDequantization::FakeQuantizeDequantization( multiplyConstant(multiplyConstant) { } -bool FakeQuantizeDequantization::empty() const { +bool FakeQuantizeDequantization::empty() const noexcept { return (subtract == nullptr) && (multiply == nullptr); } diff --git a/inference-engine/src/low_precision_transformations/src/group_convolution.cpp b/inference-engine/src/low_precision_transformations/src/group_convolution.cpp index 42d9600d13c7a0..5eacede1bf3224 100644 --- a/inference-engine/src/low_precision_transformations/src/group_convolution.cpp +++ b/inference-engine/src/low_precision_transformations/src/group_convolution.cpp @@ -32,7 +32,7 @@ GroupConvolutionTransformation::GroupConvolutionTransformation(const Params& par this->register_matcher(m, callback); } -bool GroupConvolutionTransformation::isQuantized(const std::shared_ptr& layer) const noexcept { +bool GroupConvolutionTransformation::isQuantized(const std::shared_ptr& layer) const { return GroupConvolutionTransformation::isQuantizedStatic(layer); } @@ -47,7 +47,7 @@ bool GroupConvolutionTransformation::transform(TransformationContext &context, n return true; } -bool GroupConvolutionTransformation::isQuantizedStatic(const std::shared_ptr& layer) noexcept { +bool GroupConvolutionTransformation::isQuantizedStatic(const std::shared_ptr& layer) { return WeightableLayerTransformation::isQuantizedStatic(layer, true); } diff --git a/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp b/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp index 64363ace33ca0e..028e5ee4cbc57d 100644 --- a/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp +++ b/inference-engine/src/low_precision_transformations/src/layer_transformation.cpp @@ -199,8 +199,8 @@ LayerTransformation::PrecisionDetails LayerTransformation::getPrecisionDetails( const size_t quantizationLevels, const std::vector& outputLowValues, const std::vector& outputHighValues) { - const float zeroThreshold = std::numeric_limits::denorm_min(); // TODO: workaround: hardcoded values + const float zeroThreshold = 1.e-6f; const float quantizationIntervalAsymmetryThreshold = 0.002f; float asymmetricIntervalSideRatio = -static_cast(quantizationLevels) / (quantizationLevels - 2.f); @@ -209,7 +209,15 @@ LayerTransformation::PrecisionDetails LayerTransformation::getPrecisionDetails( bool unsignedPrecision = true; bool hasZeroPoint = false; + bool thereIsAtLeastOneNormalValue = false; for (size_t i = 0; i < outputLowValues.size(); ++i) { + if ((std::fabs(outputLowValues[i]) < zeroThreshold) && (std::fabs(outputHighValues[i]) < zeroThreshold)) { + // both values are too small to identify preferable precision + continue; + } + + thereIsAtLeastOneNormalValue = true; + const bool signedInterval = std::signbit(outputLowValues[i]) != std::signbit(outputHighValues[i]); const bool outputLowValueIsNotZero = std::fabs(outputLowValues[i]) >= zeroThreshold; if (signedInterval && outputLowValueIsNotZero) { @@ -218,8 +226,9 @@ LayerTransformation::PrecisionDetails LayerTransformation::getPrecisionDetails( hasNegative = true; if (outputHighValues[i] != 0.f) { - const float expectedRatio = (quantizationLevels == 256 || quantizationLevels == 65536 || quantizationLevels == 4294967296) ? - asymmetricIntervalSideRatio : -1.f; + const float expectedRatio = + (quantizationLevels == 16 || quantizationLevels == 256 || + quantizationLevels == 65536 || quantizationLevels == 4294967296) ? asymmetricIntervalSideRatio : -1.f; const float actualRatio = outputLowValues[i] / outputHighValues[i]; const float actual = std::fabs((actualRatio - expectedRatio) / std::min(actualRatio, expectedRatio)); if (actual > quantizationIntervalAsymmetryThreshold) { @@ -253,16 +262,11 @@ LayerTransformation::PrecisionDetails LayerTransformation::getPrecisionDetails( } } - // TODO: use this implementation after merge <= not aligned with master -// if (signedPrecision && (!unsignedPrecision)) { -// return LayerTransformation::PrecisionDetails(element::i8, hasNegative, hasZeroPoint); -// } -// -// if ((!signedPrecision) && unsignedPrecision) { -// return LayerTransformation::PrecisionDetails(element::u8, hasNegative, hasZeroPoint); -// } -// -// THROW_TRANSFORMATION_EXCEPTION << "unexpected interval"; + if (!thereIsAtLeastOneNormalValue) { + // all values are small and didn't define 'signedPrecision' + signedPrecision = std::any_of(outputLowValues.begin(), outputLowValues.end(), [](const float& value) { return value < 0.f; }); + unsignedPrecision = !signedPrecision; + } element::Type resultPrecision = element::undefined; if (!hasZeroPoint) { @@ -270,6 +274,7 @@ LayerTransformation::PrecisionDetails LayerTransformation::getPrecisionDetails( switch (quantizationLevels) { case 256: case 255: + case 16: resultPrecision = element::i8; break; case 65536: @@ -287,6 +292,7 @@ LayerTransformation::PrecisionDetails LayerTransformation::getPrecisionDetails( switch (quantizationLevels) { case 256: case 255: + case 16: resultPrecision = element::u8; break; case 65536: @@ -311,10 +317,13 @@ LayerTransformation::PrecisionDetails LayerTransformation::getPrecisionDetails(c bool LayerTransformation::isAsymmetricQuantization(const std::shared_ptr& layer) { const auto nonConstNode = const_cast(layer.get())->shared_from_this(); const auto dequantization = NetworkHelper::getDequantization(nonConstNode); + if (dequantization.empty()) { + return false; + } return dequantization.subtract != nullptr; } -bool LayerTransformation::isQuantized(const std::shared_ptr& layer) const noexcept { +bool LayerTransformation::isQuantized(const std::shared_ptr& layer) const { return true; } diff --git a/inference-engine/src/low_precision_transformations/src/mat_mul.cpp b/inference-engine/src/low_precision_transformations/src/mat_mul.cpp index ad27caab8b4e6a..1ced4c45188e7e 100644 --- a/inference-engine/src/low_precision_transformations/src/mat_mul.cpp +++ b/inference-engine/src/low_precision_transformations/src/mat_mul.cpp @@ -167,7 +167,7 @@ bool MatMulTransformation::transform(TransformationContext &context, ngraph::pat newMultiply->set_friendly_name(newMatMul->get_friendly_name() + "/DequantizationMultiply"); - replace_node(matMul, newMultiply); + NetworkHelper::insertDequantizationAfter(matMul, newMultiply, newMatMul); copy_runtime_info({ newMultiply, matMul }, newMultiply); updateOutput(context, newMultiply, newMatMul); diff --git a/inference-engine/src/low_precision_transformations/src/mvn.cpp b/inference-engine/src/low_precision_transformations/src/mvn.cpp index 428d293810266c..a30c6859470246 100644 --- a/inference-engine/src/low_precision_transformations/src/mvn.cpp +++ b/inference-engine/src/low_precision_transformations/src/mvn.cpp @@ -159,7 +159,7 @@ bool MVNTransformation::transform(TransformationContext &context, ngraph::patter mvn->get_output_element_type(0)); ngraph::copy_runtime_info({ mvn, newMultiply }, newMultiply); - replace_node(mvn, newMultiply); + NetworkHelper::insertDequantizationAfter(mvn, newMultiply, newMVN); updateOutput(context, newMultiply, newMVN); return true; diff --git a/inference-engine/src/low_precision_transformations/src/network_helper.cpp b/inference-engine/src/low_precision_transformations/src/network_helper.cpp index 31d39ddae419c5..50d6da8fc1b38c 100644 --- a/inference-engine/src/low_precision_transformations/src/network_helper.cpp +++ b/inference-engine/src/low_precision_transformations/src/network_helper.cpp @@ -1108,7 +1108,7 @@ std::tuple, std::shared_ptr> NetworkHelper::decompos dequantize->set_friendly_name(newFQ->get_friendly_name() + "/DequantizationMultiply"); ngraph::copy_runtime_info({ newFQ, dequantize }, dequantize); - replace_node(fq, dequantize); + insertDequantizationAfter(fq, dequantize, newFQ); return std::make_tuple(newFQ, dequantize); } @@ -1516,12 +1516,24 @@ std::shared_ptr NetworkHelper::optimizeSubtract(std::shared_ptrinput_value(0); - const auto subtractParent = subtract->get_input_node_shared_ptr(1); - if (ov::is_type(subtractParent)) { + // check if shift is a constant + std::shared_ptr shift = subtract->get_input_node_shared_ptr(1); + bool isShiftConstant = ov::is_type(shift); + if (!isShiftConstant && ov::is_type(shift)) { + // if not - we're dealing with shift->Convert (to high precision) -> Subtract + shift = shift->get_input_node_shared_ptr(0); + isShiftConstant = ov::is_type(shift); + } + if (isShiftConstant) { std::shared_ptr replacement; - auto shift = subtract->input_value(1).get_node_shared_ptr(); - auto roundedShift = NetworkHelper::round(shift, convertInputType); + auto shiftConst = ov::as_type_ptr(shift); + std::shared_ptr roundedShift; + if (shiftConst->get_element_type() != convertInputType) { + roundedShift = NetworkHelper::round(shiftConst, convertInputType); + } else { + roundedShift = shiftConst; + } if (isScalarLike(roundedShift)) { roundedShift = toScalar(roundedShift); @@ -1532,7 +1544,7 @@ std::shared_ptr NetworkHelper::optimizeSubtract(std::shared_ptr>(data, roundedShift->output(0)); @@ -1541,12 +1553,6 @@ std::shared_ptr NetworkHelper::optimizeSubtract(std::shared_ptr(subtractParent) && ov::is_type(subtractParent->get_input_node_shared_ptr(0))) { - auto replacement = std::make_shared>(data, subtractParent->input_value(0)); - NetworkHelper::copyInfo(subtract, replacement); - NetworkHelper::setOutDataPrecisionForTypeRelaxed(replacement, convertOutputType); - replace_node(subtract, replacement); return replacement; } @@ -1568,36 +1574,32 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter assert(operation->get_output_size() == 1); + // we must have dequantization multiply + assert(dequantization.multiply != nullptr); + OutputVector inputs = operation->input_values(); const size_t dequantizationIndex = getChildInputIndex(dequantization.multiply, operation); - inputs[dequantizationIndex] = moveSubtract ? - dequantization.data : - (dequantization.subtract == nullptr ? dequantization.data : dequantization.subtract); + inputs[dequantizationIndex] = (!moveSubtract && dequantization.subtract != nullptr) ? + dequantization.subtract : + dequantization.data; - const std::shared_ptr newOperation = operation->clone_with_new_inputs(inputs); + const auto newOperation = operation->clone_with_new_inputs(inputs); newOperation->set_friendly_name(operation->get_friendly_name()); ngraph::copy_runtime_info(operation, newOperation); - auto op = std::dynamic_pointer_cast(newOperation); - if (op != nullptr) { - if (updatePrecision) { - op->set_overridden_output_type(newOperation->get_input_element_type(0)); - } else if (dequantization.multiply) { - op->set_overridden_output_type(dequantization.multiplyConstant->get_element_type()); - } else if (dequantization.subtract) { - op->set_overridden_output_type(dequantization.subtractConstant->get_element_type()); - } - std::dynamic_pointer_cast(newOperation)->validate_and_infer_types(); + if (const auto op = std::dynamic_pointer_cast(newOperation)) { + op->set_overridden_output_type(updatePrecision ? + newOperation->get_input_element_type(0) : + dequantization.multiplyConstant->get_element_type()); + newOperation->validate_and_infer_types(); } + std::shared_ptr parent = newOperation; + const element::Type deqPrecision = dequantization.multiplyConstant->get_element_type(); const bool shouldConvert = (newOperation->get_output_element_type(0) != deqPrecision); - - auto parent = newOperation; if (shouldConvert) { - const auto convertOutputPrecision = dequantization.convert != nullptr ? - dequantization.convert->get_output_element_type(0) : - deqPrecision; + const auto convertOutputPrecision = dequantization.convert ? dequantization.convert->get_element_type() : deqPrecision; parent = std::make_shared(parent, convertOutputPrecision); ngraph::copy_runtime_info({ newOperation, parent }, parent); } @@ -1613,12 +1615,9 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter } parent = std::make_shared>( - std::vector{element::f32, element::f32}, std::vector{ element::f32 }, - ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(), - ngraph::op::TemporaryReplaceOutputType( - dequantization.subtractConstant->output(0).get_element_type() == parentPrecision ? - dequantization.subtractConstant : - foldConvert(dequantization.subtractConstant->output(0), parentPrecision), element::f32).get()); + element::TypeVector{ element::f32, element::f32 }, element::TypeVector{ element::f32 }, + op::TemporaryReplaceOutputType(parent, element::f32).get(), + op::TemporaryReplaceOutputType(foldConvert(dequantization.subtractConstant, parentPrecision), element::f32).get()); ngraph::copy_runtime_info({ newOperation, parent }, parent); } else { parent = std::make_shared(parent, dequantization.subtractConvert); @@ -1627,23 +1626,21 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter } if (dequantization.multiply != nullptr) { - auto multiplyConstant = dequantization.multiplyConstant; const element::Type parentPrecision = parent->get_output_element_type(0); - if (parentPrecision.bitwidth() < multiplyConstant->get_element_type().bitwidth()) { + if (parentPrecision.bitwidth() < dequantization.multiplyConstant->get_element_type().bitwidth()) { THROW_IE_LPT_EXCEPTION(*parent) << "unexpected precisions: on data " << parent->get_friendly_name() << ":" << parentPrecision << - ", multiply dequantization constant " << multiplyConstant->get_friendly_name() << ":" << multiplyConstant->get_element_type(); + ", multiply dequantization constant " << dequantization.multiplyConstant->get_friendly_name() << ":" << + dequantization.multiplyConstant->get_element_type(); } parent = std::make_shared>( - opset1::Multiply(parent, - multiplyConstant->output(0).get_element_type() == parentPrecision ? - multiplyConstant : - foldConvert(multiplyConstant->output(0), parentPrecision)), + opset1::Multiply(parent, foldConvert(dequantization.multiplyConstant, parentPrecision)), dequantization.multiply->get_output_element_type(0)); ngraph::copy_runtime_info({ newOperation, parent }, parent); } - replace_node(operation, parent); + + insertDequantizationAfter(operation, parent, newOperation); if ((!moveSubtract) && (dequantization.convert != nullptr) && (dequantization.subtract != nullptr)) { // issue #43088 @@ -1872,6 +1869,21 @@ bool isDisabled(const std::shared_ptr& node) { } return false; } + +void NetworkHelper::insertDequantizationAfter( + const std::shared_ptr& originalNode, + const std::shared_ptr& dequantization, + const std::shared_ptr& newNode) { + replace_node(originalNode, dequantization); + + // We do it to avoid dequantization propagation to the shapeOf subgraphs + for (const auto& input : dequantization->get_output_target_inputs(0)) { + if (const auto shapeOf = as_type_ptr(input.get_node()->shared_from_this())) { + const auto newShapeOf = shapeOf->clone_with_new_inputs({ newNode }); + replace_node_update_name(shapeOf, newShapeOf); + } + } +} } // namespace low_precision } // namespace pass } // namespace ngraph diff --git a/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp b/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp index 9cc1086c393c4a..7d2a894580084b 100644 --- a/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp +++ b/inference-engine/src/low_precision_transformations/src/normalize_l2.cpp @@ -140,7 +140,7 @@ bool NormalizeL2Transformation::transform(TransformationContext &context, ngraph ngraph::op::TemporaryReplaceOutputType(newNormalize, element::f32).get(), ngraph::op::TemporaryReplaceOutputType(newScalesConst, element::f32).get()); - replace_node(normalize, newMultiply); + NetworkHelper::insertDequantizationAfter(normalize, newMultiply, newNormalize); ngraph::copy_runtime_info({ normalize, newMultiply }, newMultiply); updateOutput(context, newMultiply, newNormalize); diff --git a/inference-engine/src/low_precision_transformations/src/quantization_details.cpp b/inference-engine/src/low_precision_transformations/src/quantization_details.cpp index 84028c99a15682..ee5ed04ad267a5 100644 --- a/inference-engine/src/low_precision_transformations/src/quantization_details.cpp +++ b/inference-engine/src/low_precision_transformations/src/quantization_details.cpp @@ -91,6 +91,10 @@ void QuantizationDetails::getOutputIntervals( } QuantizationDetails QuantizationDetails::getDetails(std::shared_ptr quantize) { + if (!QuantizationDetails::outputLayoutIsSupported(quantize)) { + return QuantizationDetails(); + } + const std::vector inputLowValues = ov::as_type_ptr(quantize->get_input_node_shared_ptr(1))->cast_vector(); const std::vector inputHighValues = ov::as_type_ptr(quantize->get_input_node_shared_ptr(2))->cast_vector(); @@ -153,8 +157,12 @@ std::vector QuantizationDetails::getBlobValue(std::shared_ptr const return ov::as_type_ptr(constantLayer)->cast_vector(); } +bool QuantizationDetails::empty() const noexcept { + return (levels == 0ul) && inputLowValues.empty() && inputHighValues.empty() && outputLowValues.empty() && outputHighValues.empty(); +} + bool QuantizationDetails::isSupportedLevel(const size_t level) { - static const std::unordered_set supported_levels = { 255, 256, 65536, 65535, static_cast(4294967296), 4294967295 }; + static const std::unordered_set supported_levels = { 16, 255, 256, 65536, 65535, static_cast(4294967296), 4294967295 }; return supported_levels.find(level) != supported_levels.end(); } diff --git a/inference-engine/src/low_precision_transformations/src/rt_info/intervals_alignment_attribute.cpp b/inference-engine/src/low_precision_transformations/src/rt_info/intervals_alignment_attribute.cpp index cb8b650bac8611..7beb4722459a8e 100644 --- a/inference-engine/src/low_precision_transformations/src/rt_info/intervals_alignment_attribute.cpp +++ b/inference-engine/src/low_precision_transformations/src/rt_info/intervals_alignment_attribute.cpp @@ -166,25 +166,26 @@ void VariantWrapper::merge( const auto size = std::abs(sharedValue->minInterval.high - sharedValue->minInterval.low); if (resultSize > size) { resultSharedValue->minInterval = sharedValue->minInterval; - - float dequantizationMul; - float dequantizationSub; - float updatedOutputLowValue; - float updatedOutputHighValue; - - const size_t minLevels = NetworkHelper::calculateLevels( - 0.f, - DataPrecision::getMaxValue(resultAttribute->levels), - resultSharedValue->combinedInterval.low, - resultSharedValue->combinedInterval.high, - resultSharedValue->minInterval.low, - resultSharedValue->minInterval.high, - dequantizationMul, - dequantizationSub, - updatedOutputLowValue, - updatedOutputHighValue); - - resultSharedValue->minLevels = minLevels; + if (resultAttribute->levels != 0ul) { + float dequantizationMul; + float dequantizationSub; + float updatedOutputLowValue; + float updatedOutputHighValue; + + const size_t minLevels = NetworkHelper::calculateLevels( + 0.f, + DataPrecision::getMaxValue(resultAttribute->levels), + resultSharedValue->combinedInterval.low, + resultSharedValue->combinedInterval.high, + resultSharedValue->minInterval.low, + resultSharedValue->minInterval.high, + dequantizationMul, + dequantizationSub, + updatedOutputLowValue, + updatedOutputHighValue); + + resultSharedValue->minLevels = minLevels; + } #ifdef LPT_DEBUG resultSharedValue->minLevelsOperation = sharedValue->minLevelsOperation; diff --git a/inference-engine/src/low_precision_transformations/src/split.cpp b/inference-engine/src/low_precision_transformations/src/split.cpp index 141549dd582859..70c0be993d2d70 100644 --- a/inference-engine/src/low_precision_transformations/src/split.cpp +++ b/inference-engine/src/low_precision_transformations/src/split.cpp @@ -109,6 +109,16 @@ bool SplitTransformation::transform(TransformationContext& context, ngraph::patt } } + // We do it to avoid dequantization propagation to the shapeOf subgraphs + for (size_t i = 0; i < replacement.size(); ++i) { + for (const auto& input : replacement[i].get_target_inputs()) { + if (const auto shapeOf = as_type_ptr(input.get_node()->shared_from_this())) { + const auto newShapeOf = shapeOf->clone_with_new_inputs({ newSplit->output(i) }); + replace_node_update_name(shapeOf, newShapeOf); + } + } + } + updateOutputs(context, lastNodes, newSplit); return true; } diff --git a/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp b/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp index a8aee81aca6ebf..bc5ee3706baeac 100644 --- a/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp +++ b/inference-engine/src/low_precision_transformations/src/weightable_layer_transformation.cpp @@ -42,7 +42,7 @@ bool WeightableLayerTransformation::canConvolutionBeTransformed(const Transforma if (dequantization.empty()) { const auto fqOnWeights = getFakeQuantizeOnWeights(layer); const auto dataPrecision = getDataPrecisionOnWeights(layer); - if (!NetworkHelper::checkZeroPoint(fqOnWeights, dataPrecision)) { + if ((dataPrecision.precision == ngraph::element::undefined) || (!NetworkHelper::checkZeroPoint(fqOnWeights, dataPrecision))) { return false; } } else { @@ -361,6 +361,9 @@ std::shared_ptr WeightableLayerTransformation::getFakeQuan DataPrecision WeightableLayerTransformation::getDataPrecisionOnWeights(const std::shared_ptr& node) { const auto fq = getFakeQuantizeOnWeights(node); const QuantizationDetails quantizationDetails = QuantizationDetails::getDetails(fq); + if (quantizationDetails.empty()) { + return DataPrecision(); + } const auto precisionsAttribute = getAttributeFromOutput(fq); const auto precisions = precisionsAttribute == nullptr ? @@ -380,11 +383,15 @@ bool WeightableLayerTransformation::isAsymmetricOnWeights(const std::shared_ptr< if (dequantization.empty()) { const auto dataPrecision = WeightableLayerTransformation::getDataPrecisionOnWeights(n); + if (dataPrecision.empty()) { + return false; + } + if (dataPrecision.hasZeroPoint) { return true; } } else { - if (dequantization.subtract != nullptr) { + if ((dequantization.subtract != nullptr) && (NetworkHelper::optimizeSubtract(dequantization.subtract) != nullptr)) { return true; } } diff --git a/inference-engine/src/mkldnn_plugin/cpu_types.cpp b/inference-engine/src/mkldnn_plugin/cpu_types.cpp index 00b22d9093740e..a475c660fddb45 100644 --- a/inference-engine/src/mkldnn_plugin/cpu_types.cpp +++ b/inference-engine/src/mkldnn_plugin/cpu_types.cpp @@ -66,6 +66,7 @@ const InferenceEngine::details::caseless_unordered_map type_t { "Squeeze", Reshape }, { "Unsqueeze", Reshape }, { "ShapeOf", ShapeOf }, + { "NonZero", NonZero }, { "Softmax", Softmax }, { "Reorder", Reorder }, { "BatchToSpace", BatchToSpace }, @@ -228,6 +229,8 @@ std::string NameFromType(const Type type) { return "Reshape"; case ShapeOf: return "ShapeOf"; + case NonZero: + return "NonZero"; case Tile: return "Tile"; case ROIAlign: diff --git a/inference-engine/src/mkldnn_plugin/cpu_types.h b/inference-engine/src/mkldnn_plugin/cpu_types.h index 0062c034c5bdb2..8052b73fe9de50 100644 --- a/inference-engine/src/mkldnn_plugin/cpu_types.h +++ b/inference-engine/src/mkldnn_plugin/cpu_types.h @@ -34,6 +34,7 @@ enum Type { MatMul, Reshape, ShapeOf, + NonZero, Tile, ROIAlign, ROIPooling, diff --git a/inference-engine/src/mkldnn_plugin/memory_desc/blocked_memory_desc.cpp b/inference-engine/src/mkldnn_plugin/memory_desc/blocked_memory_desc.cpp index a7b231c37af35e..873ee413a58fbf 100644 --- a/inference-engine/src/mkldnn_plugin/memory_desc/blocked_memory_desc.cpp +++ b/inference-engine/src/mkldnn_plugin/memory_desc/blocked_memory_desc.cpp @@ -19,10 +19,7 @@ bool BlockedMemoryDesc::isCompatible(const BlockedMemoryDesc &rhs) const { return false; } - // this check needed to avoid inserting unnecessary reorders if the memory is used in place and the batch size is equal to 1 - size_t skipAxis = this->getShape().getRank() > 0 && this->getShape().getDims().front() == 1 ? 0 : - Shape::UNDEFINED_DIM; //ignore batch axis if batch size == 1 - if (!dimsEqualWeak(this->getStrides(), rhs.getStrides(), skipAxis)) { + if (!dimsEqualWeak(this->getStrides(), rhs.getStrides())) { return false; } diff --git a/inference-engine/src/mkldnn_plugin/memory_desc/dnnl_blocked_memory_desc.cpp b/inference-engine/src/mkldnn_plugin/memory_desc/dnnl_blocked_memory_desc.cpp index b9caab749dd120..bdb5d5bb77bf56 100644 --- a/inference-engine/src/mkldnn_plugin/memory_desc/dnnl_blocked_memory_desc.cpp +++ b/inference-engine/src/mkldnn_plugin/memory_desc/dnnl_blocked_memory_desc.cpp @@ -236,7 +236,7 @@ bool DnnlBlockedMemoryDesc::isCompatible(const DnnlBlockedMemoryDesc& rhs) const if (one_of(wrappedThis.format_kind(), format_kind::undef, format_kind::any)) return false; - int stride_start = wrappedThis.ndims() > 0 && wrappedThis.dims()[0] == 1 ? 1 : 0; // ignore batch axis stride if batch size == 1 + int stride_start = 0; const auto thisExtra = this->desc.data.extra; const auto rhsExtra = rhs.desc.data.extra; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_edge.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_edge.cpp index ad45a5d39adedb..5c433a607775b3 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_edge.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_edge.cpp @@ -65,12 +65,7 @@ void MKLDNNEdge::drop() { _drop_from(getChild()->parentEdges); } - -bool MKLDNNEdge::needReorder() { - if (!getInputDesc().isCompatible(getOutputDesc())) { - return true; - } - +bool MKLDNNEdge::enforceReorder() { bool canBeInPlaceConflicts = false; auto parentNode = getParent(); auto parentSPD = parentNode->getSelectedPrimitiveDescriptor(); @@ -142,6 +137,107 @@ bool MKLDNNEdge::needReorder() { return false; } +static inline bool isPhycicalMemCompatible(const MemoryDesc& lhsMemDesc, const MemoryDesc& rhsMemDesc) { + if (!lhsMemDesc.isDefined() || !rhsMemDesc.isDefined() || + !(lhsMemDesc.getType() & MemoryDescType::Blocked) || !(rhsMemDesc.getType() & MemoryDescType::Blocked) || + (lhsMemDesc.getType() == DnnlBlocked && !lhsMemDesc.as()->hasEmptyExtraData()) || + (rhsMemDesc.getType() == DnnlBlocked && !rhsMemDesc.as()->hasEmptyExtraData())) + return false; + + const auto lhsBlockMemDesc = lhsMemDesc.as(); + const auto rhsBlockMemDesc = rhsMemDesc.as(); + + if (lhsBlockMemDesc->getShape() != rhsBlockMemDesc->getShape() || lhsBlockMemDesc->getPrecision() != rhsBlockMemDesc->getPrecision()) + return false; + + // dims padding check + bool isZeroDimsPaddings = + std::all_of(lhsBlockMemDesc->getOffsetPaddingToData().begin(), lhsBlockMemDesc->getOffsetPaddingToData().end(), [](size_t x){ return x == 0; }) && + std::all_of(rhsBlockMemDesc->getOffsetPaddingToData().begin(), rhsBlockMemDesc->getOffsetPaddingToData().end(), [](size_t x){ return x == 0; }); + bool isSameElementsCount = lhsBlockMemDesc->getPaddedElementsCount() == rhsBlockMemDesc->getPaddedElementsCount(); + if (!isZeroDimsPaddings || !isSameElementsCount) + return false; + + // tensor padding check + if (lhsBlockMemDesc->getOffsetPadding() != rhsBlockMemDesc->getOffsetPadding()) { + return false; + } + + // stride check + const auto lhsBlockDims = lhsBlockMemDesc->getBlockDims(); + std::vector lhsStridesDefault(lhsBlockDims.size()); + lhsStridesDefault[lhsBlockDims.size() - 1] = 1; + for (size_t i = 2; i <= lhsBlockDims.size(); i++) { + lhsStridesDefault[lhsBlockDims.size() - i] = lhsStridesDefault[lhsBlockDims.size() - (i - 1)] * lhsBlockDims[lhsBlockDims.size() - (i - 1)]; + } + + auto rhsBlockDims = rhsBlockMemDesc->getBlockDims(); + std::vector rhsStridesDefault(rhsBlockDims.size()); + rhsStridesDefault[rhsBlockDims.size() - 1] = 1; + for (size_t i = 2; i <= rhsBlockDims.size(); i++) { + rhsStridesDefault[rhsBlockDims.size() - i] = + rhsStridesDefault[rhsBlockDims.size() - (i - 1)] * rhsBlockDims[rhsBlockDims.size() - (i - 1)]; + } + + // this check needed to avoid inserting unnecessary reorders if the memory is used in place and the batch size is equal to 1 + // in nodes like concate and split + size_t lhsSkipAxis = lhsBlockDims.size() > 0 && lhsBlockDims[0] == 1 ? 0 : Shape::UNDEFINED_DIM; + size_t rhsSkipAxis = rhsBlockDims.size() > 0 && rhsBlockDims[0] == 1 ? 0 : Shape::UNDEFINED_DIM; + + bool isDenseTensor = dimsEqualStrong(lhsStridesDefault, lhsBlockMemDesc->getStrides(), lhsSkipAxis) && + dimsEqualStrong(rhsStridesDefault, rhsBlockMemDesc->getStrides(), rhsSkipAxis); + if (!isDenseTensor) + return false; + + auto getCleanDim = [&](const VectorDims& dims, const VectorDims& flag) { + if (dims.size() != flag.size()) + return dims; + std::vector ret; + for (int i = 0; i < dims.size(); i++) { + if (flag[i] != 1) { + ret.push_back(dims[i]); + } + } + return ret; + }; + + // block dim check + auto lhsBlockDimsClean = getCleanDim(lhsBlockDims, lhsBlockDims); + auto rhsBlockDimsClean = getCleanDim(rhsBlockDims, rhsBlockDims); + if (!dimsEqualStrong(lhsBlockDimsClean, rhsBlockDimsClean)) + return false; + + // order check + auto lhsOrderClean = getCleanDim(lhsBlockMemDesc->getOrder(), lhsBlockDims); + auto rhsOrderClean = getCleanDim(rhsBlockMemDesc->getOrder(), rhsBlockDims); + if (!dimsEqualStrong(lhsOrderClean, rhsOrderClean)) + return false; + + return true; +} + +MKLDNNEdge::ReorderStatus MKLDNNEdge::needReorder() { + bool optimized = false; + if (!getInputDesc().isCompatible(getOutputDesc())) { + if (isPhycicalMemCompatible(getInputDesc(), getOutputDesc()) && !getParent()->isConstant()) { + optimized = true; + } else { + return ReorderStatus::Regular; + } + } + + // put here as more costly than compatible check + if (enforceReorder()) { + return ReorderStatus::Regular; + } + + if (optimized) { + return ReorderStatus::Optimized; + } + + return ReorderStatus::No; +} + void MKLDNNEdge::reuse(MKLDNNMemoryPtr ptr) { if (status != Status::NeedAllocation) return; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_edge.h b/inference-engine/src/mkldnn_plugin/mkldnn_edge.h index 9c6a4f92506b51..e997f67894378a 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_edge.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_edge.h @@ -35,6 +35,12 @@ class MKLDNNEdge { Validated }; + enum class ReorderStatus { + Regular = 0, + Optimized = 1, + No = 2 + }; + inline Status getStatus() const noexcept { return status; } @@ -54,7 +60,7 @@ class MKLDNNEdge { const MKLDNNMemory& getMemory(); MKLDNNMemoryPtr& getMemoryPtr(); - bool needReorder(); + ReorderStatus needReorder(); bool isDropped() const; bool isUseExternalMemory() const; @@ -87,6 +93,7 @@ class MKLDNNEdge { const MemoryDesc& getInputDesc() const; const MemoryDesc& getOutputDesc() const; const MemoryDesc& getDesc() const; + bool enforceReorder(); enum LOOK { LOOK_UP = 1, LOOK_DOWN = 2, LOOK_BOTH = LOOK_UP | LOOK_DOWN, LOOK_NO_RECURRENT = 4 }; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp index fdcdf37996fac7..747a2968e73d7a 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.cpp @@ -283,12 +283,6 @@ bool MKLDNNExecNetwork::CanProcessDynBatch(const InferenceEngine::CNNNetwork &ne return true; } -IE_SUPPRESS_DEPRECATED_START -std::vector MKLDNNExecNetwork::QueryState() { - return memoryStates; -} -IE_SUPPRESS_DEPRECATED_END - void MKLDNNExecNetwork::Export(std::ostream& modelStream) { CNNNetworkSerializer serializer(modelStream, extensionManager); serializer <<_network; diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h index 1fab2d16ebb7ce..cbaa419abae1cc 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_exec_network.h @@ -44,9 +44,6 @@ class MKLDNNExecNetwork: public InferenceEngine::ExecutableNetworkThreadSafeDefa std::shared_ptr GetExecGraphInfo() override; - INFERENCE_ENGINE_DEPRECATED("Use InferRequest::QueryState instead") - std::vector QueryState() override; - void Export(std::ostream& modelStream) override; protected: diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp index c2a5cd739488a1..d56c81ce79cb07 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph.cpp @@ -470,12 +470,34 @@ void MKLDNNGraph::InitEdges() { uniqueLayerNames.insert(node->getName()); } - for (auto i = 0; i < numberOfEdges; i++) { - if (graphEdges[i]->needReorder()) { - auto edge = graphEdges[i]; - bool insertReorder = true; + auto insertReorder = [&](MKLDNNEdgePtr& edge, bool isOptimized) { + std::string basicLayerName = edge->getParent()->getName() + "_" + + MKLDNNReorderNode::getReorderArgs(edge->getInputDesc(), edge->getOutputDesc()) + "_" + + edge->getChild()->getName(); + std::string layerName = basicLayerName; + int idx = 0; + while (uniqueLayerNames.find(layerName) != uniqueLayerNames.end()) { + idx++; + layerName = basicLayerName + "_" + std::to_string(idx); + } + uniqueLayerNames.insert(layerName); + + // optimized flag indicate that just desc update w/o actual physical memory movement. + InsertReorder(edge, layerName, edge->getInputDesc(), edge->getOutputDesc(), isOptimized); + }; - // Check if there is a reorder that supports the type conversion + auto updateEdge = [&](int& i) { + graphEdges.erase(graphEdges.begin() + i); + i--; + numberOfEdges--; + }; + + for (auto i = 0; i < numberOfEdges; i++) { + auto edge = graphEdges[i]; + auto reorderStatus = graphEdges[i]->needReorder(); + if (reorderStatus == MKLDNNEdge::ReorderStatus::Regular) { + MKLDNNEdge::ReorderStatus reorderStatusInternal = MKLDNNEdge::ReorderStatus::Regular; + // Check if there is a reorder that needs the precision conversion if (edge->getInputDesc().getPrecision() != edge->getOutputDesc().getPrecision() && !isReorderAvailable(edge->getInputDesc(), edge->getOutputDesc(), this->getEngine())) { // If we are here, then we need to insert Convert, because there are no reorders that support such type conversion @@ -491,29 +513,17 @@ void MKLDNNGraph::InitEdges() { InsertNode(edge, convertNode, true); //Check if reorder is still needed - if (convertNode->getChildEdgeAt(0)->needReorder()) { + reorderStatusInternal = convertNode->getChildEdgeAt(0)->needReorder(); + if (reorderStatusInternal != MKLDNNEdge::ReorderStatus::No) edge = convertNode->getChildEdgeAt(0); - } else { - insertReorder = false; - } } - - if (insertReorder) { - std::string basicLayerName = edge->getParent()->getName() + "_" + - MKLDNNReorderNode::getReorderArgs(edge->getInputDesc(), edge->getOutputDesc()) + "_" + - edge->getChild()->getName(); - std::string layerName = basicLayerName; - int idx = 0; - while (uniqueLayerNames.find(layerName) != uniqueLayerNames.end()) { - idx++; - layerName = basicLayerName + "_" + std::to_string(idx); - } - uniqueLayerNames.insert(layerName); - InsertReorder(edge, layerName, edge->getInputDesc(), edge->getOutputDesc()); + if (reorderStatusInternal != MKLDNNEdge::ReorderStatus::No) { + insertReorder(edge, reorderStatusInternal == MKLDNNEdge::ReorderStatus::Optimized); } - graphEdges.erase(graphEdges.begin() + i); - i--; - numberOfEdges--; + updateEdge(i); + } else if (reorderStatus == MKLDNNEdge::ReorderStatus::Optimized) { + insertReorder(edge, true); + updateEdge(i); } } } @@ -769,13 +779,19 @@ void MKLDNNGraph::PullOutputData(BlobMap &out) { std::accumulate(actualDesc.getDims().begin(), actualDesc.getDims().end(), (size_t)1, std::multiplies()) == 1); } - if (out[name]->getTensorDesc().getDims() != intr_blob.getStaticDims() && !isScalarOutput) { + const auto &outDims = intr_blob.getStaticDims(); + if (out[name]->getTensorDesc().getDims() != outDims && !isScalarOutput) { // WA: because input/output info initially contains non empty dims, order etc. // and setDims (called inside setShape) can't correct modify blocked desc for desc with blocked layout if (expectedDesc.getLayout() == Layout::BLOCKED) { expectedDesc = TensorDesc(expectedDesc.getPrecision(), expectedDesc.getLayout()); } - out[name]->setShape(intr_blob.getStaticDims()); + out[name]->setShape(outDims); + } + + // check for empty output blob + if (std::any_of(outDims.begin(), outDims.end(), [](const Dim dim) {return dim == 0;})) { + return; } auto srcPrec = actualDesc.getPrecision(); @@ -791,7 +807,6 @@ void MKLDNNGraph::PullOutputData(BlobMap &out) { // That is the same memory. No need to copy if (ext_blob_ptr == intr_blob_ptr) continue; - const auto &outDims = intr_blob.getStaticDims(); size_t size_to_copy = intr_blob.GetDescWithType()->getPaddedElementsCount(); // TODO: Should we support InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_LIMIT??? // TODO [DS]: phase 2: should we support this behaviour? Looks obsolete in the dynamic shapes paradigm @@ -1249,7 +1264,11 @@ void MKLDNNGraph::EnforceBF16() { if (node->getType() != Input && node->getType() != Output) { for (size_t i = 0; i < node->getOriginalInputsNumber(); i++) { const auto &parent = node->getParentEdgesAtPort(i)[0]->getParent(); - if (!(parent->getType() == Input && parent->isConstant()) && // exclude skipNodes after Constant Inputs + /* Skip BF16 enforcement for nodes after Constant Inputs for maintaining precision for fusing. + * Precision conversion to BF16 does automatically, if convolution follows up after Constant Inputs + * and if activation is BF16 */ + if (!(parent->getType() == Input && parent->isConstant() && + node->getType() != Concatenation) && // Concatenation node is exception because it doesn't change an accuracy for BF16 activation !(parent->getType() == Input && node->getType() == Eltwise) && // exclude Eltwise after Input since it supports conversion to BF16 node->getOriginalInputPrecisionAtPort(i) == Precision::FP32) node->setOriginalInputPrecisionAtPort(i, Precision::BF16); diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp index 639932348f0fdd..8b83701f0779e4 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_graph_optimizer.cpp @@ -11,6 +11,7 @@ #include "nodes/mkldnn_concat_node.h" #include "nodes/mkldnn_reorder_node.h" #include "nodes/mkldnn_conv_node.h" +#include "nodes/mkldnn_deconv_node.h" #include "nodes/mkldnn_bin_conv_node.h" #include "nodes/mkldnn_fake_quantize_node.h" #include "nodes/mkldnn_mvn_node.h" @@ -277,7 +278,25 @@ void MKLDNNGraphOptimizer::FuseDeconvolutionAndSimpleOperation(MKLDNNGraph &grap auto& graphNodes = graph.GetNodes(); auto isSuitableParentNode = [](MKLDNNNodePtr node) { - return node->getType() == Deconvolution && node->getChildEdges().size() == 1; + if (node->getType() != Deconvolution || node->getChildEdges().size() != 1) + return false; + const auto deconv = std::dynamic_pointer_cast(node); + if (deconv == nullptr) + IE_THROW() << "Cannot cast to deconvolution node " << node->getName(); + + if (deconv->getAlgorithm() != DeconvolutionCommon) { + return true; + } + + const auto& strides = deconv->getStride(); + const auto& kernel = deconv->getWeightDims(); + // WA oneDNN doesn't support fusing post ops after deconvolution with strides over kernel size + bool isSupportedParams = strides[strides.size() - 1] <= kernel[kernel.size() - 1]; + if (strides.size() > 1) + isSupportedParams &= strides[strides.size() - 2] <= kernel[kernel.size() - 2]; + if (strides.size() > 2) + isSupportedParams &= strides[strides.size() - 3] <= kernel[kernel.size() - 3]; + return isSupportedParams; }; auto parent = graphNodes.begin(); diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp index af900f7170db91..0498eeefd63824 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_infer_request.cpp @@ -60,26 +60,20 @@ void MKLDNNPlugin::MKLDNNInferRequest::CreateInferRequest() { // Save all MemoryLayer data tensors. Will use insight about mechanics // of MemoryLayer implementation. It uses output edge of MemoryLayer // producer as storage for tensor to keep it between infer calls. - IE_SUPPRESS_DEPRECATED_START - if (execNetwork->_numRequests > 1 || execNetwork->QueryState().size() == 0) { - for (auto &node : graph->GetNodes()) { - if (node->getType() == MemoryInput) { - auto memoryNode = dynamic_cast(node.get()); - auto state_store = memoryNode->getStore(); - auto state_name = memoryNode->getId(); - - // Remove suffix with pair ID. Internal information. - auto suffix_idx = state_name.find("/id="); - if (suffix_idx != std::string::npos) - state_name = state_name.substr(0, suffix_idx); - - memoryStates.emplace_back(new MKLDNNVariableState(state_name, state_store)); - } + for (auto& node : graph->GetNodes()) { + if (node->getType() == MemoryInput) { + auto memoryNode = dynamic_cast(node.get()); + auto state_store = memoryNode->getStore(); + auto state_name = memoryNode->getId(); + + // Remove suffix with pair ID. Internal information. + auto suffix_idx = state_name.find("/id="); + if (suffix_idx != std::string::npos) + state_name = state_name.substr(0, suffix_idx); + + memoryStates.emplace_back(new MKLDNNVariableState(state_name, state_store)); } - } else { - memoryStates = execNetwork->QueryState(); } - IE_SUPPRESS_DEPRECATED_END } MKLDNNPlugin::MKLDNNInferRequest::~MKLDNNInferRequest() { @@ -305,7 +299,7 @@ InferenceEngine::Blob::Ptr MKLDNNPlugin::MKLDNNInferRequest::GetBlob(const std:: desc.getShape().getRank())) : MemoryDescUtils::convertToTensorDesc(desc); const auto &tensorDesc = data->getTensorDesc(); - if (expectedTensorDesc.getPrecision() != tensorDesc.getPrecision()) { + if (expectedTensorDesc.getPrecision() != normalizeToSupportedPrecision(tensorDesc.getPrecision())) { IE_THROW(ParameterMismatch) << "Network input and output use the same name: " << name << " but expect blobs with different precision: " << tensorDesc.getPrecision() << " for input and " << expectedTensorDesc.getPrecision() @@ -431,10 +425,18 @@ void MKLDNNPlugin::MKLDNNInferRequest::SetBlob(const std::string& name, const In IE_THROW(ParameterMismatch) << "Failed to set input blob. Blocking descriptor mismatch."; } - const auto &actualDesc = graph->getInputNodeByName(name)->getChildEdgesAtPort(0)[0]->getMemory().getDesc(); - if (blobDesc.getLayout() != InferenceEngine::Layout::ANY && - actualDesc.isCompatible(MemoryDescUtils::convertToCpuBlockedMemoryDesc(blobDesc)) && - graph->_normalizePreprocMap.find(name) == graph->_normalizePreprocMap.end() && !graph->getProperty().batchLimit) { + MemoryDescPtr actualDesc = graph->getInputNodeByName(name)->getBaseMemDescAtOutputPort(0); + bool blobHasAnyLayout = blobDesc.getLayout() == InferenceEngine::Layout::ANY; + if (!blobHasAnyLayout && !actualDesc->isDefined()) { + // we must define desc for dynamic case + // otherwise we got incorrect check on shape compatibility inside isCompatible + // because lower and upper bound will be compared + actualDesc = actualDesc->cloneWithNewDims(blobDesc.getLayout() == InferenceEngine::Layout::SCALAR ? InferenceEngine::SizeVector{1} : + blobDesc.getDims()); + } + if (!blobHasAnyLayout && + actualDesc->isCompatible(MemoryDescUtils::convertToCpuBlockedMemoryDesc(blobDesc)) && + graph->_normalizePreprocMap.find(name) == graph->_normalizePreprocMap.end() && !graph->getProperty().batchLimit) { externalPtr[name] = data->buffer(); } else if (externalPtr.find(name) != externalPtr.end()) { externalPtr.erase(name); diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_node.h b/inference-engine/src/mkldnn_plugin/mkldnn_node.h index 65e175b32a8939..7aad502bd092b7 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_node.h +++ b/inference-engine/src/mkldnn_plugin/mkldnn_node.h @@ -725,7 +725,6 @@ class MKLDNNNode { } std::vector lastInputDims = {}; - std::shared_ptr opToShapeInfer; private: @@ -782,8 +781,7 @@ class MKLDNNNode::NodesFactory : public openvino::cc::Factory { public: - NodesFactory() - : Factory("NodesFactory") {} + NodesFactory(); MKLDNNNode* create(const std::shared_ptr& op, const mkldnn::engine& eng, const MKLDNNExtensionManager::Ptr& extMgr, MKLDNNWeightsSharing::Ptr &w_cache); @@ -797,15 +795,6 @@ struct MKLDNNNodeImpl : public MKLDNNNodeType { } }; -#define REG_MKLDNN_CONCAT3_(X, Y, Z) X ## Y ## Z -#define REG_MKLDNN_CONCAT3(X, Y, Z) REG_MKLDNN_CONCAT3_(X, Y, Z) - -#define REG_MKLDNN_PRIM_FOR(__prim, __type) \ -static struct REG_MKLDNN_CONCAT3(Registrar4, __prim, __LINE__) { \ - REG_MKLDNN_CONCAT3(Registrar4, __prim, __LINE__)() { \ - MKLDNNNode::factory() \ - .registerNodeIfRequired(MKLDNNPlugin, __prim, __type, MKLDNNNodeImpl<__prim>); \ - } \ -} REG_MKLDNN_CONCAT3(_reg_, __prim, __LINE__); - } // namespace MKLDNNPlugin + +#define REG_MKLDNN_PRIM_FOR(__prim, __type) diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_nodes_factory.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_nodes_factory.cpp new file mode 100644 index 00000000000000..f7f8aa2c7c7b3d --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/mkldnn_nodes_factory.cpp @@ -0,0 +1,171 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "nodes/mkldnn_reference_node.h" +#include "nodes/mkldnn_shapeof.h" +#include "nodes/mkldnn_batch_to_space_node.h" +#include "nodes/mkldnn_multiclass_nms.hpp" +#include "nodes/mkldnn_adaptive_pooling.h" +#include "nodes/mkldnn_conv_node.h" +#include "nodes/mkldnn_roi_align_node.h" +#include "nodes/mkldnn_lrn_node.h" +#include "nodes/mkldnn_generic_node.h" +#include "nodes/mkldnn_experimental_detectron_roifeatureextractor_node.h" +#include "nodes/mkldnn_eltwise_node.h" +#include "nodes/mkldnn_reorg_yolo_node.h" +#include "nodes/mkldnn_pooling_node.h" +#include "nodes/mkldnn_transpose_node.h" +#include "nodes/mkldnn_grn_node.h" +#include "nodes/mkldnn_interpolate_node.h" +#include "nodes/mkldnn_experimental_detectron_detection_output_node.h" +#include "nodes/mkldnn_roll_node.h" +#include "nodes/mkldnn_fake_quantize_node.h" +#include "nodes/mkldnn_embedding_segments_sum_node.h" +#include "nodes/mkldnn_region_yolo_node.h" +#include "nodes/mkldnn_matmul_node.h" +#include "nodes/mkldnn_detection_output_node.h" +#include "nodes/mkldnn_reverse_sequence_node.h" +#include "nodes/mkldnn_pad_node.h" +#include "nodes/mkldnn_ctc_greedy_decoder_seq_len_node.h" +#include "nodes/mkldnn_reshape_node.h" +#include "nodes/mkldnn_psroi_pooling_node.h" +#include "nodes/mkldnn_memory_node.hpp" +#include "nodes/mkldnn_bin_conv_node.h" +#include "nodes/mkldnn_gather_elements_node.h" +#include "nodes/mkldnn_experimental_detectron_priorgridgenerator_node.h" +#include "nodes/mkldnn_tile_node.h" +#include "nodes/mkldnn_math_node.h" +#include "nodes/mkldnn_normalize_node.h" +#include "nodes/mkldnn_proposal_node.h" +#include "nodes/mkldnn_tensoriterator_node.h" +#include "nodes/mkldnn_fullyconnected_node.h" +#include "nodes/mkldnn_extract_image_patches_node.h" +#include "nodes/mkldnn_ctc_loss_node.h" +#include "nodes/mkldnn_reorder_node.h" +#include "nodes/mkldnn_gather_nd_node.h" +#include "nodes/mkldnn_shuffle_channels_node.h" +#include "nodes/mkldnn_bucketize_node.h" +#include "nodes/mkldnn_space_to_depth_node.h" +#include "nodes/mkldnn_concat_node.h" +#include "nodes/mkldnn_softmax_node.h" +#include "nodes/mkldnn_space_to_batch_node.h" +#include "nodes/mkldnn_select_node.h" +#include "nodes/mkldnn_topk_node.h" +#include "nodes/mkldnn_broadcast_node.h" +#include "nodes/mkldnn_matrix_nms_node.h" +#include "nodes/mkldnn_mvn_node.h" +#include "nodes/mkldnn_gather_node.h" +#include "nodes/mkldnn_scatter_update_node.h" +#include "nodes/mkldnn_gather_tree_node.h" +#include "nodes/mkldnn_def_conv_node.h" +#include "nodes/mkldnn_embedding_bag_offset_sum_node.h" +#include "nodes/mkldnn_deconv_node.h" +#include "nodes/mkldnn_roi_pooling_node.h" +#include "nodes/mkldnn_range_node.h" +#include "nodes/mkldnn_split_node.h" +#include "nodes/mkldnn_one_hot_node.h" +#include "nodes/mkldnn_log_softmax_node.h" +#include "nodes/mkldnn_strided_slice_node.h" +#include "nodes/mkldnn_dft_node.h" +#include "nodes/mkldnn_non_max_suppression_node.h" +#include "nodes/mkldnn_convert_node.h" +#include "nodes/mkldnn_rnn.h" +#include "nodes/mkldnn_experimental_detectron_topkrois_node.h" +#include "nodes/mkldnn_cum_sum_node.h" +#include "nodes/mkldnn_depth_to_space_node.h" +#include "nodes/mkldnn_input_node.h" +#include "nodes/mkldnn_experimental_detectron_generate_proposals_single_image_node.h" +#include "nodes/mkldnn_embedding_bag_packed_sum_node.h" +#include "nodes/mkldnn_reduce_node.h" +#include "nodes/mkldnn_if_node.h" +#include "nodes/mkldnn_ctc_greedy_decoder_node.h" + +#define MKLDNN_NODE(__prim, __type) \ + registerNodeIfRequired(MKLDNNPlugin, __prim, __type, MKLDNNNodeImpl<__prim>) + +MKLDNNPlugin::MKLDNNNode::NodesFactory::NodesFactory() + : Factory("NodesFactory") { + MKLDNN_NODE(MKLDNNGenericNode, Generic); + MKLDNN_NODE(MKLDNNCumSumNode, CumSum); + MKLDNN_NODE(MKLDNNConvolutionNode, Convolution); + MKLDNN_NODE(MKLDNNSpaceToBatchNode, SpaceToBatch); + MKLDNN_NODE(MKLDNNLrnNode, Lrn); + MKLDNN_NODE(MKLDNNBatchToSpaceNode, BatchToSpace); + MKLDNN_NODE(MKLDNNNormalizeL2Node, NormalizeL2); + MKLDNN_NODE(MKLDNNIfNode, If); + MKLDNN_NODE(MKLDNNProposalNode, Proposal); + MKLDNN_NODE(MKLDNNBroadcastNode, Broadcast); + MKLDNN_NODE(MKLDNNExperimentalDetectronTopKROIsNode, ExperimentalDetectronTopKROIs); + MKLDNN_NODE(MKLDNNReorderNode, Reorder); + MKLDNN_NODE(MKLDNNBinaryConvolutionNode, BinaryConvolution); + MKLDNN_NODE(MKLDNNMatrixNmsNode, MatrixNms); + MKLDNN_NODE(MKLDNNAdaptivePoolingNode, AdaptivePooling); + MKLDNN_NODE(MKLDNNPoolingNode, Pooling); + MKLDNN_NODE(MKLDNNReduceNode, Reduce); + MKLDNN_NODE(MKLDNNEltwiseNode, Eltwise); + MKLDNN_NODE(MKLDNNSoftMaxNode, Softmax); + MKLDNN_NODE(MKLDNNEmbeddingBagPackedSumNode, EmbeddingBagPackedSum); + MKLDNN_NODE(MKLDNNInputNode, Input); + MKLDNN_NODE(MKLDNNInputNode, Output); + MKLDNN_NODE(MKLDNNMemoryInputNode, MemoryInput); + MKLDNN_NODE(MKLDNNMemoryOutputNode, MemoryOutput); + MKLDNN_NODE(MKLDNNTileNode, Tile); + MKLDNN_NODE(MKLDNNDFTNode, DFT); + MKLDNN_NODE(MKLDNNGatherTreeNode, GatherTree); + MKLDNN_NODE(MKLDNNSpaceToDepthNode, SpaceToDepth); + MKLDNN_NODE(MKLDNNFullyConnectedNode, FullyConnected); + MKLDNN_NODE(MKLDNNCTCGreedyDecoderNode, CTCGreedyDecoder); + MKLDNN_NODE(MKLDNNTransposeNode, Transpose); + MKLDNN_NODE(MKLDNNDeformableConvolutionNode, DeformableConvolution); + MKLDNN_NODE(MKLDNNReorgYoloNode, ReorgYolo); + MKLDNN_NODE(MKLDNNEmbeddingSegmentsSumNode, EmbeddingSegmentsSum); + MKLDNN_NODE(MKLDNNSelectNode, Select); + MKLDNN_NODE(MKLDNNShapeOfNode, ShapeOf); + MKLDNN_NODE(MKLDNNExperimentalDetectronGenerateProposalsSingleImageNode, ExperimentalDetectronGenerateProposalsSingleImage); + MKLDNN_NODE(MKLDNNReverseSequenceNode, ReverseSequence); + MKLDNN_NODE(MKLDNNFakeQuantizeNode, FakeQuantize); + MKLDNN_NODE(MKLDNNNonMaxSuppressionNode, NonMaxSuppression); + MKLDNN_NODE(MKLDNNExperimentalDetectronPriorGridGeneratorNode, ExperimentalDetectronPriorGridGenerator); + MKLDNN_NODE(MKLDNNGatherNDNode, GatherND); + MKLDNN_NODE(MKLDNNLogSoftmaxNode, LogSoftmax); + MKLDNN_NODE(MKLDNNPSROIPoolingNode, PSROIPooling); + MKLDNN_NODE(MKLDNNRNN, RNNCell); + MKLDNN_NODE(MKLDNNRNN, RNNSeq); + MKLDNN_NODE(MKLDNNCTCLossNode, CTCLoss); + MKLDNN_NODE(MKLDNNSplitNode, Split); + MKLDNN_NODE(MKLDNNDetectionOutputNode, DetectionOutput); + MKLDNN_NODE(MKLDNNGatherElementsNode, GatherElements); + MKLDNN_NODE(MKLDNNCTCGreedyDecoderSeqLenNode, CTCGreedyDecoderSeqLen); + MKLDNN_NODE(MKLDNNBucketizeNode, Bucketize); + MKLDNN_NODE(MKLDNNExperimentalDetectronROIFeatureExtractorNode, ExperimentalDetectronROIFeatureExtractor); + MKLDNN_NODE(MKLDNNMathNode, Math); + MKLDNN_NODE(MKLDNNMultiClassNmsNode, MulticlassNms); + MKLDNN_NODE(MKLDNNConvertNode, Convert); + MKLDNN_NODE(MKLDNNEmbeddingBagOffsetSumNode, EmbeddingBagOffsetsSum); + MKLDNN_NODE(MKLDNNRollNode, Roll); + MKLDNN_NODE(MKLDNNPadNode, Pad); + MKLDNN_NODE(MKLDNNReshapeNode, Reshape); + MKLDNN_NODE(MKLDNNMVNNode, MVN); + MKLDNN_NODE(MKLDNNMatMulNode, MatMul); + MKLDNN_NODE(MKLDNNScatterUpdateNode, ScatterUpdate); + MKLDNN_NODE(MKLDNNScatterUpdateNode, ScatterElementsUpdate); + MKLDNN_NODE(MKLDNNScatterUpdateNode, ScatterNDUpdate); + MKLDNN_NODE(MKLDNNInterpolateNode, Interpolate); + MKLDNN_NODE(MKLDNNROIPoolingNode, ROIPooling); + MKLDNN_NODE(MKLDNNTensorIteratorNode, TensorIterator); + MKLDNN_NODE(MKLDNNConcatNode, Concatenation); + MKLDNN_NODE(MKLDNNExtractImagePatchesNode, ExtractImagePatches); + MKLDNN_NODE(MKLDNNOneHotNode, OneHot); + MKLDNN_NODE(MKLDNNExperimentalDetectronDetectionOutputNode, ExperimentalDetectronDetectionOutput); + MKLDNN_NODE(MKLDNNROIAlignNode, ROIAlign); + MKLDNN_NODE(MKLDNNShuffleChannelsNode, ShuffleChannels); + MKLDNN_NODE(MKLDNNDepthToSpaceNode, DepthToSpace); + MKLDNN_NODE(MKLDNNDeconvolutionNode, Deconvolution); + MKLDNN_NODE(MKLDNNGatherNode, Gather); + MKLDNN_NODE(MKLDNNRegionYoloNode, RegionYolo); + MKLDNN_NODE(MKLDNNRangeNode, Range); + MKLDNN_NODE(MKLDNNTopKNode, TopK); + MKLDNN_NODE(MKLDNNStridedSliceNode, StridedSlice); + MKLDNN_NODE(MKLDNNGRNNode, GRN); +} diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index e78257b8b089b4..a9005f628f64a8 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -6,6 +6,7 @@ #include "mkldnn_plugin.h" #include "mkldnn_extension_mngr.h" #include "mkldnn_weights_cache.hpp" +#include "mkldnn_extension.h" #include "mkldnn_itt.h" #include "mkldnn_serialize.h" @@ -29,6 +30,8 @@ #include #include "transformations/common_optimizations/convert_quantize_dequantize.hpp" #include +#include +#include #include #include #include @@ -115,7 +118,7 @@ using namespace InferenceEngine; Engine::Engine() { _pluginName = "CPU"; - extensionManager->AddExtension(std::make_shared()); + extensionManager->AddExtension(std::make_shared()); } Engine::~Engine() { @@ -135,7 +138,6 @@ static void TransformationUpToCPUSpecificOpSet(std::shared_ptr manager.register_pass( std::vector{ ngraph::element::i8, ngraph::element::u8, ngraph::element::i4, ngraph::element::u4 }); } - auto get_convert_precisions = []() { precisions_array array = { {ngraph::element::i64, ngraph::element::i32}, @@ -159,6 +161,8 @@ static void TransformationUpToCPUSpecificOpSet(std::shared_ptr static const auto precisions = get_convert_precisions(); manager.register_pass(); + manager.register_pass(); + manager.register_pass(); manager.register_pass(); manager.register_pass(); manager.register_pass(); @@ -298,6 +302,7 @@ static void TransformationUpToCPUSpecificOpSet(std::shared_ptr return node->input_value(0).get_partial_shape().rank().get_length() <= 5; }); + // TODO [DS NMS]: remove when nodes from models where nms is not last node in model supports DS pass_config->set_callback( [](const_node_ptr &node) -> bool { for (size_t i = 0; i < node->get_output_size(); i++) { @@ -441,8 +446,10 @@ Engine::LoadExeNetworkImpl(const InferenceEngine::CNNNetwork &network, const std InferenceEngine::InputsDataMap _networkInputs = network.getInputsInfo(); for (const auto &ii : _networkInputs) { auto input_precision = ii.second->getPrecision(); - if (input_precision != InferenceEngine::Precision::FP32 && + if (input_precision != InferenceEngine::Precision::FP64 && + input_precision != InferenceEngine::Precision::FP32 && input_precision != InferenceEngine::Precision::I32 && + input_precision != InferenceEngine::Precision::U32 && input_precision != InferenceEngine::Precision::U16 && input_precision != InferenceEngine::Precision::I16 && input_precision != InferenceEngine::Precision::I8 && diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_serialize.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_serialize.cpp index ae4044279a3732..36729dfb17d8a6 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_serialize.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_serialize.cpp @@ -118,7 +118,9 @@ void CNNNetworkSerializer::operator << (const CNNNetwork & network) { }; // Serialize to old representation in case of old API + OPENVINO_SUPPRESS_DEPRECATED_START ov::pass::StreamSerialize serializer(_ostream, getCustomOpSets(), serializeInputsAndOutputs); + OPENVINO_SUPPRESS_DEPRECATED_END serializer.run_on_function(std::const_pointer_cast(network.getFunction())); } diff --git a/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.cpp b/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.cpp index 3affd3ab47e7a2..7467f9103d63db 100644 --- a/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.cpp +++ b/inference-engine/src/mkldnn_plugin/ngraph_transformations/op/fully_connected.cpp @@ -9,7 +9,7 @@ MKLDNNPlugin::FullyConnectedNode::FullyConnectedNode(const ngraph::Output& const ngraph::Rank& output_rank, const ngraph::element::Type output_type) : Op({A, B}), m_output_rank(output_rank), m_output_type(output_type) { - constructor_validate_and_infer_types(); + validate_and_infer_types(); } MKLDNNPlugin::FullyConnectedNode::FullyConnectedNode(const ngraph::Output& A, @@ -18,7 +18,7 @@ MKLDNNPlugin::FullyConnectedNode::FullyConnectedNode(const ngraph::Output& const ngraph::Rank& output_rank, const ngraph::element::Type output_type) : Op({A, B, C}), m_output_rank(output_rank), m_output_type(output_type) { - constructor_validate_and_infer_types(); + validate_and_infer_types(); } std::shared_ptr MKLDNNPlugin::FullyConnectedNode::clone_with_new_inputs(const ngraph::OutputVector& new_args) const { @@ -40,13 +40,6 @@ void MKLDNNPlugin::FullyConnectedNode::validate_and_infer_types() { input_size, ", expected: 2 or 3."); - const auto output_size = get_output_size(); - NODE_VALIDATION_CHECK(this, - output_size == 1, - "Number of outputs is incorrect. Current value is: ", - output_size, - ", expected: 1."); - // Weights shape: [O, I1, ..., Im]; // O - output channels dimensions, Ik - input channels dimensions const auto weights_pshape = get_input_partial_shape(1); @@ -101,10 +94,7 @@ void MKLDNNPlugin::FullyConnectedNode::validate_and_infer_types() { } bool MKLDNNPlugin::FullyConnectedNode::visit_attributes(ngraph::AttributeVisitor &visitor) { - if (m_output_rank.is_static()) { - std::int64_t value = m_output_rank.get_length(); - visitor.on_attribute("out-rank", value); - } + visitor.on_attribute("out-rank", m_output_rank); visitor.on_attribute("out-type", m_output_type); return true; } diff --git a/inference-engine/src/mkldnn_plugin/nodes/common/cpu_convert.cpp b/inference-engine/src/mkldnn_plugin/nodes/common/cpu_convert.cpp index 5b47b476b0a565..8763b551af9597 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/common/cpu_convert.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/common/cpu_convert.cpp @@ -103,7 +103,13 @@ void cpu_convert(const void *srcPtr, void *dstPtr, Precision srcPrc, Precision d MKLDNN_CVT(BF16, I64), MKLDNN_CVT(BF16, FP32), MKLDNN_CVT(BF16, BOOL), MKLDNN_CVT(BOOL, U8), MKLDNN_CVT(BOOL, I8), MKLDNN_CVT(BOOL, U16), MKLDNN_CVT(BOOL, I16), MKLDNN_CVT(BOOL, I32), MKLDNN_CVT(BOOL, U64), - MKLDNN_CVT(BOOL, I64), MKLDNN_CVT(BOOL, FP32), MKLDNN_CVT(BOOL, BF16)); + MKLDNN_CVT(BOOL, I64), MKLDNN_CVT(BOOL, FP32), MKLDNN_CVT(BOOL, BF16), + MKLDNN_CVT(FP64, U8), MKLDNN_CVT(FP64, I8), MKLDNN_CVT(FP64, U16), + MKLDNN_CVT(FP64, I16), MKLDNN_CVT(FP64, I32), MKLDNN_CVT(FP64, U64), + MKLDNN_CVT(FP64, I64), MKLDNN_CVT(FP64, FP32), MKLDNN_CVT(FP64, BF16), MKLDNN_CVT(FP64, BOOL), + MKLDNN_CVT(U32, U8), MKLDNN_CVT(U32, I8), MKLDNN_CVT(U32, U16), + MKLDNN_CVT(U32, I16), MKLDNN_CVT(U32, I32), MKLDNN_CVT(U32, U64), + MKLDNN_CVT(U32, I64), MKLDNN_CVT(U32, FP32), MKLDNN_CVT(U32, BF16), MKLDNN_CVT(U32, BOOL)); if (!ctx.converted) IE_THROW() << "cpu_convert can't convert from: " << srcPrc << " precision to: " << dstPrc; diff --git a/inference-engine/src/mkldnn_plugin/nodes/list.cpp b/inference-engine/src/mkldnn_plugin/nodes/list.cpp deleted file mode 100644 index c4d7ce8970e01a..00000000000000 --- a/inference-engine/src/mkldnn_plugin/nodes/list.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "nodes/list.hpp" - -namespace InferenceEngine { -namespace Extensions { -namespace Cpu { - -#define FACTORY_DECLARATION(__prim, __type) \ - void __prim ## __type(MKLDNNExtensions * extInstance) - -#define FACTORY_CALL(__prim, __type) \ - __prim ## __type(this) - -#define MKLDNN_EXTENSION_NODE(__prim, __type) FACTORY_DECLARATION(__prim, __type) -# include "list_tbl.hpp" -#undef MKLDNN_EXTENSION_NODE - -MKLDNNExtensions::MKLDNNExtensions() - : layersFactory("LayersFactory") { - #define MKLDNN_EXTENSION_NODE(__prim, __type) FACTORY_CALL(__prim, __type) - # include "list_tbl.hpp" - #undef MKLDNN_EXTENSION_NODE -} - -} // namespace Cpu -} // namespace Extensions -} // namespace InferenceEngine diff --git a/inference-engine/src/mkldnn_plugin/nodes/list.hpp b/inference-engine/src/mkldnn_plugin/nodes/list.hpp index 8cbe1db6ab38af..ffb0743e0a3cf2 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/list.hpp +++ b/inference-engine/src/mkldnn_plugin/nodes/list.hpp @@ -43,32 +43,14 @@ class ILayerImplFactory { namespace Extensions { namespace Cpu { -using ext_factory = std::function& op)>; - -struct ExtensionsHolder { - std::map list; -}; - +// TODO: remove this class MKLDNNExtensions : public IExtension { public: MKLDNNExtensions(); - virtual StatusCode - getPrimitiveTypes(char**& types, unsigned int& size, ResponseDesc* resp) noexcept { - collectTypes(types, size); - return OK; - } - virtual StatusCode getFactoryFor(ILayerImplFactory*& factory, const std::shared_ptr& op, ResponseDesc* resp) noexcept { - using namespace MKLDNNPlugin; - factory = layersFactory.createNodeIfRegistered(MKLDNNPlugin, op->get_type_name(), op); - if (!factory) { - std::string errorMsg = std::string("Factory for ") + op->get_type_name() + " wasn't found!"; - errorMsg.copy(resp->msg, sizeof(resp->msg) - 1); - return NOT_FOUND; - } - return OK; + return NOT_FOUND; } void GetVersion(const InferenceEngine::Version*& versionInfo) const noexcept override { @@ -82,24 +64,6 @@ class MKLDNNExtensions : public IExtension { } void Unload() noexcept override {} - - using LayersFactory = openvino::cc::Factory< - std::string, - InferenceEngine::ILayerImplFactory*(const std::shared_ptr& op)>; - - LayersFactory layersFactory; - -private: - void collectTypes(char**& types, unsigned int& size) const { - types = new char *[layersFactory.size()]; - unsigned count = 0; - layersFactory.foreach([&](std::pair const &builder) { - types[count] = new char[builder.first.size() + 1]; - std::copy(builder.first.begin(), builder.first.end(), types[count]); - types[count][builder.first.size() ] = '\0'; - }); - size = count; - } }; } // namespace Cpu diff --git a/inference-engine/src/mkldnn_plugin/nodes/list_tbl.hpp b/inference-engine/src/mkldnn_plugin/nodes/list_tbl.hpp deleted file mode 100644 index d005c1e16b630d..00000000000000 --- a/inference-engine/src/mkldnn_plugin/nodes/list_tbl.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#ifndef MKLDNN_EXTENSION_NODE -# warning "MKLDNN_EXTENSION_NODE is not defined" -# define MKLDNN_EXTENSION_NODE(__prim, __type) -#endif - diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.cpp index 43b8fa708ad589..a4811c30affdf4 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.cpp @@ -2,12 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include #include #include #include "ie_parallel.hpp" -#include "utils/bfloat16.hpp" #include #include "mkldnn_batch_to_space_node.h" #include @@ -18,10 +16,6 @@ using namespace InferenceEngine; bool MKLDNNBatchToSpaceNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } const auto batchToSpace = std::dynamic_pointer_cast(op); if (!batchToSpace) { errorMessage = "Only opset2 BatchToSpace operation is supported"; @@ -48,11 +42,11 @@ MKLDNNBatchToSpaceNode::MKLDNNBatchToSpaceNode(const std::shared_ptrget_friendly_name() + "'"; - if (op->get_input_size() != 4 || op->get_output_size() != 1) + if (inputShapes.size() != 4 || outputShapes.size() != 1) IE_THROW() << errorPrefix << " has incorrect number of input or output edges!"; - inDims = getInputShapeAtPort(0).getStaticDims(); - outDims = getOutputShapeAtPort(0).getStaticDims(); + const auto &inDims = getInputShapeAtPort(0).getDims(); + const auto &outDims = getOutputShapeAtPort(0).getDims(); if (inDims.size() < 4 || inDims.size() > 5) IE_THROW() << errorPrefix << " has unsupported 'data' input rank: " << inDims.size(); if (inDims.size() != outDims.size()) @@ -66,6 +60,7 @@ void MKLDNNBatchToSpaceNode::initSupportedPrimitiveDescriptors() { if (!supportedPrimitiveDescriptors.empty()) return; + const auto &inDims = getInputShapeAtPort(0).getDims(); const auto precision = getOriginalInputPrecisionAtPort(0); const std::set supported_precision_sizes = {1, 2, 4, 8}; if (supported_precision_sizes.find(precision.size()) == supported_precision_sizes.end()) @@ -83,7 +78,7 @@ void MKLDNNBatchToSpaceNode::initSupportedPrimitiveDescriptors() { {LayoutType::ncsp}}, {{LayoutType::ncsp, precision}}, impl_desc_type::ref_any); - if (inDims[1] % 8 == 0) { + if (inDims[1] != Shape::UNDEFINED_DIM && inDims[1] % 8 == 0) { addSupportedPrimDesc({{LayoutType::nCsp8c, precision}, {LayoutType::ncsp}, {LayoutType::ncsp}, @@ -91,7 +86,7 @@ void MKLDNNBatchToSpaceNode::initSupportedPrimitiveDescriptors() { {{LayoutType::nCsp8c, precision}}, impl_desc_type::ref_any); } - if (inDims[1] % 16 == 0) { + if (inDims[1] != Shape::UNDEFINED_DIM && inDims[1] % 16 == 0) { addSupportedPrimDesc({{LayoutType::nCsp16c, precision}, {LayoutType::ncsp}, {LayoutType::ncsp}, @@ -116,6 +111,9 @@ void MKLDNNBatchToSpaceNode::batchToSpaceKernel() { const auto *srcData = reinterpret_cast(getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); auto *dstData = reinterpret_cast(getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); + const auto &inDims = getParentEdgesAtPort(0)[0]->getMemory().getStaticDims(); + const auto &outDims = getChildEdgesAtPort(0)[0]->getMemory().getStaticDims(); + auto srcDesc = getParentEdgeAt(0)->getMemory().GetDescWithType(); const bool blocked = srcDesc->hasLayoutType(LayoutType::nCsp8c) || srcDesc->hasLayoutType(LayoutType::nCsp16c); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h index e262108ded04d7..0c0ef5ee06c486 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_batch_to_space_node.h @@ -22,6 +22,9 @@ class MKLDNNBatchToSpaceNode : public MKLDNNNode { void execute(mkldnn::stream strm) override; bool created() const override; + bool needPrepareParams() const override { return false; }; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); }; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: @@ -29,8 +32,6 @@ class MKLDNNBatchToSpaceNode : public MKLDNNNode { void batchToSpaceKernel(); private: - InferenceEngine::SizeVector inDims; - InferenceEngine::SizeVector outDims; std::vector blockShapeIn; std::vector cropsBeginIn; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp index e03c006fe63587..3b0e1e481c8282 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.cpp @@ -33,11 +33,6 @@ namespace { bool MKLDNNConcatNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } - const auto concatOp = ngraph::as_type_ptr(op); if (!concatOp) { errorMessage = "Node is not an instance of the Concat operation."; @@ -66,14 +61,14 @@ MKLDNNConcatNode::MKLDNNConcatNode(const std::shared_ptr& op, cons } void MKLDNNConcatNode::getSupportedDescriptors() { - auto& firstParentDims = getInputShapeAtPort(0).getStaticDims(); + const auto& firstParentDims = getInputShapeAtPort(0).getDims(); for (size_t i = 1; i < getParentEdges().size(); i++) { - auto& dims = getInputShapeAtPort(i).getStaticDims(); + const auto& dims = getInputShapeAtPort(i).getDims(); bool incorrectDims = false; for (size_t j = 0; j < firstParentDims.size(); j++) { if (j == axis) continue; - if (dims.size() != firstParentDims.size() || firstParentDims[j] != dims[j]) { + if (dims.size() != firstParentDims.size() || !dimsEqualWeak(firstParentDims[j], dims[j])) { incorrectDims = true; break; } @@ -84,9 +79,12 @@ void MKLDNNConcatNode::getSupportedDescriptors() { } // we need the first dims before axis to be 1 to avoid the reorder in the edge between the first parent and this concat - const auto& childDims = outputShapes[0].getStaticDims(); - if (std::all_of(childDims.begin(), childDims.begin() + axis, [](size_t dim) { return dim == 1; })) - canBeInPlace = true; + // TODO [DS]: inplace + if (!isDynamicNode()) { + const auto& childDims = outputShapes[0].getStaticDims(); + if (std::all_of(childDims.begin(), childDims.begin() + axis, [](size_t dim) { return dim == 1; })) + canBeInPlace = true; + } } void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() { @@ -116,14 +114,14 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() { // check if blocked layouts are available the channels size should be evenly divided by the block size to avoid slow oneDNN ref implementation if (dstShape.getRank() > channelAxis) { for (auto item : { std::make_pair(8lu, LayoutType::nCsp8c), std::make_pair(16lu, LayoutType::nCsp16c)}) { - const VectorDims &blkDims = dstShape.getStaticDims(); - if (blkDims[channelAxis] % item.first) + const VectorDims &blkDims = dstShape.getDims(); + if (blkDims[channelAxis] == Shape::UNDEFINED_DIM || blkDims[channelAxis] % item.first != 0) continue; bool blocked = true; for (size_t i = 0; i < getParentEdges().size(); i++) { - auto& srcDims = getInputShapeAtPort(i).getStaticDims(); - if (srcDims[channelAxis] % item.first) { + auto& srcDims = getInputShapeAtPort(i).getDims(); + if (srcDims[channelAxis] == Shape::UNDEFINED_DIM || srcDims[channelAxis] % item.first != 0) { blocked = false; break; } @@ -153,7 +151,13 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() { for (size_t i = 0; i < getParentEdges().size(); ++i) { config.inConfs[i].inPlace = -1; config.inConfs[i].constant = false; - config.inConfs[i].desc = itr->second->createDesc(inputPrecision, getInputShapeAtPort(i)).cloneWithUndefStridesAndOffset(); + auto desc = itr->second->createSharedDesc(inputPrecision, getInputShapeAtPort(i)); + // TODO [DS]: inplace + if (isDynamicNode()) { + config.inConfs[i].desc = desc; + } else { + config.inConfs[i].desc = desc->cloneWithUndefStridesAndOffset(); + } } supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::ref); if (itr->first != LayoutType::nspc) { @@ -167,11 +171,12 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() { return; } } + + // TODO [DS]: inplace if (!canBeInPlace) return; // Optimized inplace case - for (auto refPdIndex : pdIndexesToReuse) { const auto& refConfig = supportedPrimitiveDescriptors[refPdIndex].getConfig(); auto config = refConfig; @@ -259,7 +264,7 @@ void MKLDNNConcatNode::selectOptimalPrimitiveDescriptor() { } size_t maxCount = 0; - auto outDims = getOutputShapeAtPort(0).getStaticDims(); + const auto &outDims = getOutputShapeAtPort(0).getDims(); LayoutType convertTo = LayoutType::ncsp; for (auto &it : formatFrequency) { if (it.second > maxCount) { @@ -276,13 +281,13 @@ void MKLDNNConcatNode::selectOptimalPrimitiveDescriptor() { for (auto& item : { std::make_pair(8lu, LayoutType::nCsp8c), std::make_pair(16lu, LayoutType::nCsp16c) }) { if (convertTo == item.second) { - if (outDims[1] % item.first != 0) { + if (outDims[channelAxis] == Shape::UNDEFINED_DIM || outDims[1] % item.first != 0) { convertTo = LayoutType::ncsp; break; } for (size_t i = 0; i < getParentEdges().size(); i++) { - auto& inpDims = getInputShapeAtPort(i).getStaticDims(); - if (inpDims[1] % item.first != 0) { + const auto& inpDims = getInputShapeAtPort(i).getDims(); + if (inpDims[channelAxis] == Shape::UNDEFINED_DIM || inpDims[1] % item.first != 0) { convertTo = LayoutType::ncsp; break; } @@ -330,26 +335,27 @@ bool MKLDNNConcatNode::isOptimized() const { return getSelectedPrimitiveDescriptor() && getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].inPlace >= 0; } -void MKLDNNConcatNode::createPrimitive() { - if (prim || isOptimized()) +bool MKLDNNConcatNode::needPrepareParams() const { + if (canOptimizeNspc) { + return false; + } + return inputShapesModified(); +} + +void MKLDNNConcatNode::prepareParams() { + if (canOptimizeNspc || isOptimized()) return; - auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); + const auto& dstMemPtr = getChildEdgesAtPort(0)[0]->getMemoryPtr(); if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr()) IE_THROW() << "Destination memory didn't allocate."; if (getSelectedPrimitiveDescriptor() == nullptr) IE_THROW() << "Preferable primitive descriptor is not set."; - //check if selected Tensor descriptor has nspc layout and concat axis is C - if (axis == channelAxis && getChildEdgeAt(0)->getMemory().getDesc().hasLayoutType(LayoutType::nspc)) { - canOptimizeNspc = true; - return; - } - std::vector srcs_d; for (size_t i = 0; i < getParentEdges().size(); i++) { - auto& srcMemPtr = getParentEdgeAt(i)->getMemoryPtr(); + const auto& srcMemPtr = getParentEdgesAtPort(i)[0]->getMemoryPtr(); if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) { auto parent = getParentEdgeAt(i)->getParent(); IE_THROW() << "Source memory from " << parent->getName() << " didn't allocate for node " @@ -357,7 +363,7 @@ void MKLDNNConcatNode::createPrimitive() { } auto desc = srcMemPtr->GetDescWithType()->getDnnlDesc(); - auto& dims = getInputShapeAtPort(i).getStaticDims(); + const auto& dims = srcMemPtr->getStaticDims(); for (size_t j = 0; j < dims.size(); j++) { desc.data.dims[j] = dims[j]; } @@ -365,8 +371,8 @@ void MKLDNNConcatNode::createPrimitive() { srcs_d.emplace_back(desc); } - auto desc = getChildEdgeAt(0)->getMemory().GetDescWithType()->getDnnlDesc(); - auto& dims = getOutputShapeAtPort(0).getStaticDims(); + auto desc = dstMemPtr->GetDescWithType()->getDnnlDesc(); + const auto& dims = dstMemPtr->getStaticDims(); for (size_t i = 0; i < dims.size(); i++) { desc.data.dims[i] = dims[i]; desc.data.padded_dims[i] = dims[i]; @@ -376,6 +382,14 @@ void MKLDNNConcatNode::createPrimitive() { prim.reset(new concat(primitive_desc)); } +void MKLDNNConcatNode::createPrimitive() { + if (inputShapesDefined()) { + if (needPrepareParams()) + prepareParams(); + updateLastInputDims(); + } +} + size_t MKLDNNConcatNode::inverseOrder(const SizeVector& order, size_t axis) { for (size_t i = 0; i < order.size(); i++) { if (axis == order[i]) { @@ -408,64 +422,66 @@ void MKLDNNConcatNode::initOptimalPrimitiveDescriptor() { } auto config = selected_pd->getConfig(); - if (isConfigDefined(config)) - return; - - for (size_t i = 0; i < config.outConfs.size(); i++) { - if (config.outConfs[i].desc->isDefined()) - continue; + if (!isDynamicNode() && !isConfigDefined(config)) { + for (size_t i = 0; i < config.outConfs.size(); i++) { + if (config.outConfs[i].desc->isDefined()) + continue; - int num = getChildEdgeAt(i)->getOutputNum(); - if (num >= 0) { - auto childConf = getChildEdgeAt(i)->getChild()->getSelectedPrimitiveDescriptor()->getConfig().inConfs[num]; - childConf.desc = childConf.desc->cloneWithNewPrecision(config.outConfs[i].desc->getPrecision()); + int num = getChildEdgeAt(i)->getOutputNum(); + if (num >= 0) { + auto childConf = getChildEdgeAt(i)->getChild()->getSelectedPrimitiveDescriptor()->getConfig().inConfs[num]; + childConf.desc = childConf.desc->cloneWithNewPrecision(config.outConfs[i].desc->getPrecision()); - if (getChildEdgeAt(i)->getChild()->getSelectedPrimitiveDescriptor()) { - if (!childConf.desc->isDefined() && childConf.inPlace >= 0) - getChildEdgeAt(i)->getChild()->initOptimalPrimitiveDescriptor(); + if (getChildEdgeAt(i)->getChild()->getSelectedPrimitiveDescriptor()) { + if (!childConf.desc->isDefined() && childConf.inPlace >= 0) + getChildEdgeAt(i)->getChild()->initOptimalPrimitiveDescriptor(); - if (childConf.desc->isDefined() && childConf.desc->isCompatible(*config.outConfs[i].desc)) { - config.outConfs[i].desc = childConf.desc; - continue; + if (childConf.desc->isDefined() && childConf.desc->isCompatible(*config.outConfs[i].desc)) { + config.outConfs[i].desc = childConf.desc; + continue; + } } } - } - // reset undefined offsets - config.outConfs[i].desc = config.outConfs[i].desc->as()->cloneWithDefaultStridesAndOffset(); - } - auto firstOutBlockingDesc = config.outConfs[0].desc->as(); - size_t offset = 0; - for (size_t i = 0; i < config.inConfs.size(); i++) { - auto oldDesc = config.inConfs[i].desc; - auto inpBlockingDesc = oldDesc->as(); - - config.inConfs[i].desc = std::make_shared(inpBlockingDesc->getPrecision(), - inpBlockingDesc->getShape(), - inpBlockingDesc->getBlockDims(), - inpBlockingDesc->getOrder(), - firstOutBlockingDesc->getOffsetPadding() + offset, - firstOutBlockingDesc->getOffsetPaddingToData(), - firstOutBlockingDesc->getStrides()); - size_t axisSize = 1; - - auto firstInpBlockingDesc = config.inConfs[0].desc->as(); - if (firstInpBlockingDesc->hasLayoutType(LayoutType::nspc)) { - // This is more general and works for any "direct" Layout (such as nchw or nhwc), but it doesn't work for blocked - size_t realAxis = inverseOrder(firstInpBlockingDesc->getOrder(), axis); - for (size_t j = realAxis; j < inpBlockingDesc->getBlockDims().size(); j++) { - size_t jj = firstInpBlockingDesc->getOrder()[j]; - axisSize *= inpBlockingDesc->getBlockDims()[jj]; - } - } else { - // This works for nchw and nchw8c/nchw16c - for (size_t j = axis; j < inpBlockingDesc->getBlockDims().size(); j++) { - axisSize *= inpBlockingDesc->getBlockDims()[j]; + // reset undefined offsets + config.outConfs[i].desc = config.outConfs[i].desc->as()->cloneWithDefaultStridesAndOffset(); + } + auto firstOutBlockingDesc = config.outConfs[0].desc->as(); + size_t offset = 0; + for (size_t i = 0; i < config.inConfs.size(); i++) { + auto oldDesc = config.inConfs[i].desc; + auto inpBlockingDesc = oldDesc->as(); + + config.inConfs[i].desc = std::make_shared(inpBlockingDesc->getPrecision(), + inpBlockingDesc->getShape(), + inpBlockingDesc->getBlockDims(), + inpBlockingDesc->getOrder(), + firstOutBlockingDesc->getOffsetPadding() + offset, + firstOutBlockingDesc->getOffsetPaddingToData(), + firstOutBlockingDesc->getStrides()); + size_t axisSize = 1; + + auto firstInpBlockingDesc = config.inConfs[0].desc->as(); + if (firstInpBlockingDesc->hasLayoutType(LayoutType::nspc)) { + // This is more general and works for any "direct" Layout (such as nchw or nhwc), but it doesn't work for blocked + size_t realAxis = inverseOrder(firstInpBlockingDesc->getOrder(), axis); + for (size_t j = realAxis; j < inpBlockingDesc->getBlockDims().size(); j++) { + size_t jj = firstInpBlockingDesc->getOrder()[j]; + axisSize *= inpBlockingDesc->getBlockDims()[jj]; + } + } else { + // This works for nchw and nchw8c/nchw16c + for (size_t j = axis; j < inpBlockingDesc->getBlockDims().size(); j++) { + axisSize *= inpBlockingDesc->getBlockDims()[j]; + } } + offset += axisSize; } - offset += axisSize; + initDescriptor(config); } - initDescriptor(config); + + // check if selected Tensor descriptor has nspc layout and concat axis is C + canOptimizeNspc = axis == channelAxis && getSelectedPrimitiveDescriptor()->getConfig().outConfs.front().desc->hasLayoutType(LayoutType::nspc); } void MKLDNNConcatNode::execute(mkldnn::stream strm) { diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h index e9f60b4dec2654..09686ca5f24917 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_concat_node.h @@ -23,6 +23,7 @@ class MKLDNNConcatNode : public MKLDNNNode { void selectOptimalPrimitiveDescriptor() override; bool created() const override; void execute(mkldnn::stream strm) override; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); } bool isOptimized() const; @@ -31,6 +32,9 @@ class MKLDNNConcatNode : public MKLDNNNode { return !isOptimized(); } + bool needPrepareParams() const override; + void prepareParams() override; + private: size_t axis = 0; bool canBeInPlace = false; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.cpp index 5b764d6ce0cc30..68fd40d9a56bcb 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.cpp @@ -18,10 +18,6 @@ using namespace InferenceEngine; bool MKLDNNCumSumNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } const auto cumsum = std::dynamic_pointer_cast(op); if (!cumsum) { errorMessage = "Only opset3 CumSum operation is supported"; @@ -45,11 +41,11 @@ MKLDNNCumSumNode::MKLDNNCumSumNode(const std::shared_ptr& op, cons if ((getOriginalInputsNumber() != numOfInputs && getOriginalInputsNumber() != (numOfInputs - 1)) || getOriginalOutputsNumber() != 1) IE_THROW() << errorPrefix << " has incorrect number of input/output edges!"; - const auto &dataShape = op->get_input_shape(CUM_SUM_DATA); - if (dataShape.size() < 1) { - IE_THROW() << errorPrefix << " doesn't support 'data' input tensor with rank: " << dataShape.size(); + const auto &dataShape = getInputShapeAtPort(CUM_SUM_DATA); + numOfDims = dataShape.getRank(); + if (numOfDims < 1) { + IE_THROW() << errorPrefix << " doesn't support 'data' input tensor with rank: " << numOfDims; } - numOfDims = dataShape.size(); const auto cumsum = std::dynamic_pointer_cast(op); if (cumsum == nullptr) @@ -60,14 +56,13 @@ MKLDNNCumSumNode::MKLDNNCumSumNode(const std::shared_ptr& op, cons reverse = cumsum->is_reverse(); if (getOriginalInputsNumber() == numOfInputs) { - if (!ngraph::is_scalar(cumsum->get_input_shape(AXIS))) + const auto axis_shape = cumsum->get_input_partial_shape(AXIS); + if (axis_shape.is_dynamic() || !ngraph::is_scalar(axis_shape.to_shape())) IE_THROW() << errorPrefix << " doesn't support 'axis' input tensor with non scalar rank"; } - if (dataShape != cumsum->get_output_shape(0)) + if (dataShape != getOutputShapeAtPort(0)) IE_THROW() << errorPrefix << " has different 'data' input and output dimensions"; - - shape = dataShape; } void MKLDNNCumSumNode::initSupportedPrimitiveDescriptors() { @@ -162,6 +157,7 @@ template void MKLDNNCumSumNode::cumSum(const dataType *input, dataType *output, const VectorDims &strides) { SizeVector iterationRange(numOfDims - 1); size_t j = 0; + const auto &shape = getParentEdgesAtPort(CUM_SUM_DATA)[0]->getMemory().getStaticDims(); for (size_t i = 0; i < shape.size(); i++) { if (i == axis) continue; @@ -283,4 +279,18 @@ bool MKLDNNCumSumNode::created() const { return getType() == CumSum; } +bool MKLDNNCumSumNode::needPrepareParams() const { + return false; +} + +void MKLDNNCumSumNode::executeDynamicImpl(mkldnn::stream strm) { + return execute(strm); +} + +void MKLDNNCumSumNode::createPrimitive() { + if (inputShapesDefined()) { + updateLastInputDims(); + } +} + REG_MKLDNN_PRIM_FOR(MKLDNNCumSumNode, CumSum) diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.h index 2836af15660519..2e5ebfaf7d866d 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_cum_sum_node.h @@ -15,10 +15,13 @@ class MKLDNNCumSumNode : public MKLDNNNode { void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; - void createPrimitive() override {}; + void createPrimitive() override; void execute(mkldnn::stream strm) override; bool created() const override; + bool needPrepareParams() const override; + void executeDynamicImpl(mkldnn::stream strm) override; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: @@ -41,7 +44,6 @@ class MKLDNNCumSumNode : public MKLDNNNode { bool reverse; size_t numOfDims; size_t axis = 0; - std::vector shape; InferenceEngine::Precision dataPrecision; std::string errorPrefix; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h index a01941b9ef7f64..3d054d5e8b25d9 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_deconv_node.h @@ -39,6 +39,9 @@ class MKLDNNDeconvolutionNode : public MKLDNNNode { static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; bool canFuse(const MKLDNNNodePtr& node) const override; + const InferenceEngine::SizeVector& getWeightDims() { return weightDims; } + const std::vector& getStride() { return stride; } + private: bool withGroups = false; bool isDW = false; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp index c341e98a78bcf4..41b8983d362b5d 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.cpp @@ -17,17 +17,11 @@ using namespace MKLDNNPlugin; using namespace InferenceEngine; -using namespace mkldnn; using namespace mkldnn::impl; -using namespace mkldnn::impl::cpu::x64; bool MKLDNNDepthToSpaceNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } - const auto depthToSpace = std::dynamic_pointer_cast(op); + auto depthToSpace = ov::as_type_ptr(op); if (!depthToSpace) { errorMessage = "Only opset1 DepthToSpace operation is supported"; return false; @@ -46,75 +40,58 @@ bool MKLDNNDepthToSpaceNode::isSupportedOperation(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache) : MKLDNNNode(op, eng, cache) { std::string errorMessage; - if (isSupportedOperation(op, errorMessage)) { - const auto depthToSpace = std::dynamic_pointer_cast(op); - - const auto modeNgraph = depthToSpace->get_mode(); - if (modeNgraph == ngraph::op::v0::DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST) { - mode = Mode::BLOCKS_FIRST; - } else if (modeNgraph == ngraph::op::v0::DepthToSpace::DepthToSpaceMode::DEPTH_FIRST) { - mode = Mode::DEPTH_FIRST; - } else { - THROW_ERROR << "doesn't support mode: " << ngraph::as_string(modeNgraph); - } - - blockSize = depthToSpace->get_block_size(); - if (blockSize == 0) - THROW_ERROR << "has incorrect block_size parameter is zero!"; - - size_t nSpatialDims = inputShapes[0].getRank() - 2; - blockStep = static_cast(std::pow(blockSize, nSpatialDims)); - } else { + if (!isSupportedOperation(op, errorMessage)) { IE_THROW(NotImplemented) << errorMessage; } -} + if (inputShapes.size() != 1 || outputShapes.size() != 1) + THROW_ERROR << "has incorrect number of input/output edges!"; + + auto depthToSpace = ov::as_type_ptr(op); + if (!depthToSpace) + THROW_ERROR << "supports only opset1"; + + const auto modeNgraph = depthToSpace->get_mode(); + if (modeNgraph == ngraph::op::v0::DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST) { + attrs.mode = Mode::BLOCKS_FIRST; + } else if (modeNgraph == ngraph::op::v0::DepthToSpace::DepthToSpaceMode::DEPTH_FIRST) { + attrs.mode = Mode::DEPTH_FIRST; + } else { + THROW_ERROR << "doesn't support mode: " << ngraph::as_string(modeNgraph); + } + + attrs.blockSize = depthToSpace->get_block_size(); + if (attrs.blockSize == 0) + THROW_ERROR << "has incorrect block_size parameter is zero!"; -void MKLDNNDepthToSpaceNode::getSupportedDescriptors() { - SizeVector srcDims = inputShapes[0].getStaticDims(); - if (srcDims.size() < 3) + const size_t srcRank = getInputShapeAtPort(0).getRank(); + const size_t dstRank = getOutputShapeAtPort(0).getRank(); + + if (srcRank < 3) THROW_ERROR << "has incorrect number of input dimensions"; - if (srcDims.size() > 5) + if (srcRank > 5) THROW_ERROR << "doesn't support dimensions with rank greater than 5"; - - SizeVector dstDims = outputShapes[0].getStaticDims(); - if (srcDims.size() != dstDims.size()) + if (srcRank != dstRank) THROW_ERROR << "has incorrect number of input/output dimensions"; - if (srcDims[1] % blockStep) - THROW_ERROR << "has block_size parameter which is incompatible with input tensor channels dimension size"; - - if (srcDims[1] / blockStep != dstDims[1]) - THROW_ERROR << "has incompatible input/output channels"; - - size_t nSpatialDims = srcDims.size() - 2; - for (size_t i = 0; i < nSpatialDims; ++i) { - if (srcDims[i + 2] * blockSize != dstDims[i + 2]) - THROW_ERROR << "has incompatible spatial dims"; - } - - if (getParentEdges().size() != 1) - THROW_ERROR << "has incorrect number of input edges"; - if (getChildEdges().empty()) - THROW_ERROR << "has incorrect number of output edges"; + const size_t nSpatialDims = srcRank - 2; + attrs.blockStep = static_cast(std::pow(attrs.blockSize, nSpatialDims)); } +void MKLDNNDepthToSpaceNode::getSupportedDescriptors() {} + void MKLDNNDepthToSpaceNode::initSupportedPrimitiveDescriptors() { if (!supportedPrimitiveDescriptors.empty()) return; InferenceEngine::Precision precision = getOriginalInputPrecisionAtPort(0); - auto srcDims = getInputShapeAtPort(0).getStaticDims(); - const size_t nDims = srcDims.size(); - impl_desc_type impl_type; - if (mayiuse(impl::cpu::x64::avx512_common)) { + impl_desc_type impl_type = impl_desc_type::ref; + if (cpu::x64::mayiuse(cpu::x64::avx512_common)) { impl_type = impl_desc_type::jit_avx512; - } else if (mayiuse(cpu::x64::avx2)) { + } else if (cpu::x64::mayiuse(cpu::x64::avx2)) { impl_type = impl_desc_type::jit_avx2; - } else if (mayiuse(cpu::x64::sse41)) { + } else if (cpu::x64::mayiuse(cpu::x64::sse41)) { impl_type = impl_desc_type::jit_sse42; - } else { - impl_type = impl_desc_type::ref; } NodeConfig config; @@ -126,11 +103,15 @@ void MKLDNNDepthToSpaceNode::initSupportedPrimitiveDescriptors() { config.outConfs[0].inPlace = -1; config.outConfs[0].constant = false; + const auto& inputDataShape = getInputShapeAtPort(0); + const auto& outputDataShape = getOutputShapeAtPort(0); + std::vector supportedTypes; - if (nDims > 2) { + if (inputDataShape.getRank() > 2) { + const auto& srcDims = inputDataShape.getDims(); auto canUseBlocked = [=](const size_t block) { - return srcDims[1] % block == 0 && (srcDims[1] / block) % blockStep == 0 && - (mode == Mode::DEPTH_FIRST ? block % blockStep == 0 : true); + return srcDims[1] != Shape::UNDEFINED_DIM && srcDims[1] % block == 0 && (srcDims[1] / block) % attrs.blockStep == 0 && + (attrs.mode == Mode::DEPTH_FIRST ? block % attrs.blockStep == 0 : true); }; supportedTypes.push_back(LayoutType::nspc); @@ -141,18 +122,18 @@ void MKLDNNDepthToSpaceNode::initSupportedPrimitiveDescriptors() { } supportedTypes.push_back(LayoutType::ncsp); auto creators = BlockedDescCreator::getCommonCreators(); - auto range = BlockedDescCreator::makeFilteredRange(creators, nDims, supportedTypes); + auto range = BlockedDescCreator::makeFilteredRange(creators, inputDataShape.getRank(), supportedTypes); for (auto itr = range.first; itr != range.second; ++itr) { - config.inConfs[0].desc = itr->second->createSharedDesc(precision, getInputShapeAtPort(0)); - config.outConfs[0].desc = itr->second->createSharedDesc(precision, getOutputShapeAtPort(0)); + config.inConfs[0].desc = itr->second->createSharedDesc(precision, inputDataShape); + config.outConfs[0].desc = itr->second->createSharedDesc(precision, outputDataShape); supportedPrimitiveDescriptors.emplace_back(config, impl_type); } } void MKLDNNDepthToSpaceNode::createPrimitive() { - auto &dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); - auto &srcMemPtr = getParentEdgeAt(0)->getMemoryPtr(); + auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); + auto& srcMemPtr = getParentEdgeAt(0)->getMemoryPtr(); if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr()) THROW_ERROR << "has not allocated destination memory"; if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) @@ -160,24 +141,44 @@ void MKLDNNDepthToSpaceNode::createPrimitive() { if (getSelectedPrimitiveDescriptor() == nullptr) THROW_ERROR << "has unidentified preferable primitive descriptor"; - VectorDims srcDims = srcMemPtr->getStaticDims(); + const auto& memoryDesc = srcMemPtr->getDesc(); + attrs.dataSize = memoryDesc.getPrecision().size(); + attrs.nSpatialDims = memoryDesc.getShape().getRank() - 2; + attrs.layoutType = memoryDesc.hasLayoutType(LayoutType::nCsp16c) ? LayoutType::nCsp16c : + memoryDesc.hasLayoutType(LayoutType::nCsp8c) ? LayoutType::nCsp8c : + memoryDesc.hasLayoutType(LayoutType::nspc) ? LayoutType::nspc : LayoutType::ncsp; + + if (inputShapesDefined()) { + if (needPrepareParams()) + prepareParams(); + updateLastInputDims(); + } +} + +void MKLDNNDepthToSpaceNode::prepareParams() { + attrs.srcBlockedDims = getParentEdgeAt(0)->getMemoryPtr()->GetDescWithType()->getBlockDims(); + execPtr = std::make_shared(attrs); +} + +MKLDNNDepthToSpaceNode::DepthToSpaceExecutor::DepthToSpaceExecutor(const DepthToSpaceAttrs& attrs) { + if (!MKLDNNPlugin::one_of(attrs.layoutType, LayoutType::nCsp16c, LayoutType::nCsp8c, LayoutType::nspc, LayoutType::ncsp)) + IE_THROW() << "DepthToSpace executor supports only 'nCsp16c', 'nCsp8c', 'nspc' or 'ncsp' layouts."; - size_t nDims = srcDims.size(); - const size_t nSpatialDims = nDims - 2; - const bool isBlocked = getParentEdgeAt(0)->getMemory().getDesc().hasLayoutType(LayoutType::nCsp8c) || - getParentEdgeAt(0)->getMemory().getDesc().hasLayoutType(LayoutType::nCsp16c); - const size_t reshapedRank = nDims + nSpatialDims + static_cast(isBlocked) + static_cast(isBlocked && mode == Mode::DEPTH_FIRST); + const bool isBlocked = MKLDNNPlugin::one_of(attrs.layoutType, LayoutType::nCsp16c, LayoutType::nCsp8c); + const bool isChannelsFirst = attrs.layoutType == LayoutType::nspc; + const size_t nDims = attrs.srcBlockedDims.size(); + const size_t reshapedRank = nDims + attrs.nSpatialDims + static_cast(isBlocked && attrs.mode == Mode::DEPTH_FIRST); const size_t lastIdx = reshapedRank - 1; size_t firstSpatialOrder = 2; PermuteParams params; - params.data_size = getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc->getPrecision().size(); + params.data_size = attrs.dataSize; params.order.resize(reshapedRank, 0); params.src_block_order.resize(reshapedRank); params.dst_block_order.resize(reshapedRank); params.dst_block_dims.resize(reshapedRank); params.src_block_dims.resize(reshapedRank); - params.src_block_dims[0] = srcDims[0]; + params.src_block_dims[0] = attrs.srcBlockedDims[0]; // reshaping of src dimensions and creating the permutation order for each layout: // new shape: mode = blocks_first [N, block_size, block_size, ..., block_size, C / (block_size ^ K), D1, D2, ..., DK] @@ -186,62 +187,58 @@ void MKLDNNDepthToSpaceNode::createPrimitive() { // mode = depth_first : [0, 1, K + 2, 2, K + 3, 3, K + 4, 4, ..., K + (K + 1), K + 1] // where `k` is number of spatial dimensions - auto reshapeAndSetPermOrder = [&](const size_t idx1, const size_t idx2, const size_t shift, const SizeVector& dims) { - for (size_t i = 0; i < nSpatialDims; i++) { + auto reshapeAndSetPermOrder = [&](const size_t idx1, const size_t idx2, const size_t shift, const VectorDims& dims) { + for (size_t i = 0; i < attrs.nSpatialDims; i++) { params.order[i * 2 + shift] = i + idx1; params.order[i * 2 + shift + 1] = i + idx2; params.src_block_dims[params.order[i * 2 + shift]] = dims[i + shift]; - params.src_block_dims[params.order[i * 2 + shift + 1]] = blockSize; + params.src_block_dims[params.order[i * 2 + shift + 1]] = attrs.blockSize; } }; if (isBlocked) { - VectorDims srcBlockedDims = getParentEdgeAt(0)->getMemory().GetDescWithType()->getBlockDims(); - size_t orderShiftForBlocks, orderShiftForDims; - if (mode == Mode::BLOCKS_FIRST) { + if (attrs.mode == Mode::BLOCKS_FIRST) { orderShiftForBlocks = 1; - orderShiftForDims = nSpatialDims + 2; + orderShiftForDims = attrs.nSpatialDims + 2; - params.src_block_dims[nSpatialDims + 1] = srcBlockedDims[1] / blockStep; - params.src_block_dims[lastIdx] = srcBlockedDims.back(); + params.src_block_dims[attrs.nSpatialDims + 1] = attrs.srcBlockedDims[1] / attrs.blockStep; + params.src_block_dims[lastIdx] = attrs.srcBlockedDims.back(); - params.order[1] = nSpatialDims + 1; + params.order[1] = attrs.nSpatialDims + 1; params.order[lastIdx] = lastIdx; } else { - orderShiftForBlocks = nSpatialDims + 4; + orderShiftForBlocks = attrs.nSpatialDims + 4; orderShiftForDims = 3; - size_t newBlockSize = srcBlockedDims.back() / blockStep; - size_t newBlocksCount = srcBlockedDims[1] / blockStep; + size_t newBlockSize = attrs.srcBlockedDims.back() / attrs.blockStep; + size_t newBlocksCount = attrs.srcBlockedDims[1] / attrs.blockStep; params.src_block_dims[1] = newBlocksCount; - params.src_block_dims[2] = srcBlockedDims[1] / newBlocksCount; - params.src_block_dims[lastIdx - nSpatialDims] = newBlockSize; + params.src_block_dims[2] = attrs.srcBlockedDims[1] / newBlocksCount; + params.src_block_dims[lastIdx - attrs.nSpatialDims] = newBlockSize; params.order[1] = 1; params.order[2] = 3; params.order[lastIdx - 1] = 2; - params.order[lastIdx] = lastIdx - nSpatialDims; + params.order[lastIdx] = lastIdx - attrs.nSpatialDims; } - reshapeAndSetPermOrder(orderShiftForDims, orderShiftForBlocks, firstSpatialOrder, srcBlockedDims); - } else if (getParentEdgeAt(0)->getMemory().getDesc().hasLayoutType(LayoutType::nspc)) { - srcDims.push_back(srcDims[1]); - srcDims.erase(srcDims.begin() + 1); + reshapeAndSetPermOrder(orderShiftForDims, orderShiftForBlocks, firstSpatialOrder, attrs.srcBlockedDims); + } else if (isChannelsFirst) { firstSpatialOrder = 1; - size_t shift = static_cast(mode == DEPTH_FIRST) + nSpatialDims + 1; - params.order[lastIdx] = mode == Mode::DEPTH_FIRST ? nSpatialDims + 1 : lastIdx; - params.src_block_dims[params.order[lastIdx]] = srcDims.back() / blockStep; + size_t shift = static_cast(attrs.mode == DEPTH_FIRST) + attrs.nSpatialDims + 1; + params.order[lastIdx] = attrs.mode == Mode::DEPTH_FIRST ? attrs.nSpatialDims + 1 : lastIdx; + params.src_block_dims[params.order[lastIdx]] = attrs.srcBlockedDims.back() / attrs.blockStep; - reshapeAndSetPermOrder(firstSpatialOrder, shift, firstSpatialOrder, srcDims); + reshapeAndSetPermOrder(firstSpatialOrder, shift, firstSpatialOrder, attrs.srcBlockedDims); } else { - size_t shift = static_cast(mode == DEPTH_FIRST) + 1; - params.order[1] = mode == DEPTH_FIRST ? 1 : nSpatialDims + 1; - params.src_block_dims[params.order[1]] = srcDims[1] / blockStep; + size_t shift = static_cast(attrs.mode == DEPTH_FIRST) + 1; + params.order[1] = attrs.mode == DEPTH_FIRST ? 1 : attrs.nSpatialDims + 1; + params.src_block_dims[params.order[1]] = attrs.srcBlockedDims[1] / attrs.blockStep; - reshapeAndSetPermOrder(nSpatialDims + firstSpatialOrder, shift, firstSpatialOrder, srcDims); + reshapeAndSetPermOrder(attrs.nSpatialDims + firstSpatialOrder, shift, firstSpatialOrder, attrs.srcBlockedDims); } std::iota(params.src_block_order.begin(), params.src_block_order.end(), 0); @@ -252,11 +249,27 @@ void MKLDNNDepthToSpaceNode::createPrimitive() { permuteKernel = std::unique_ptr(new PermuteKernel(params)); } +void MKLDNNDepthToSpaceNode::DepthToSpaceExecutor::exec(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr, const int MB) { + if (!permuteKernel) + IE_THROW() << "Could not execute. Kernel for Transpose node was not compiled."; + + const uint8_t* srcData = reinterpret_cast(srcMemPtr->GetPtr()); + uint8_t* dstData = reinterpret_cast(dstMemPtr->GetPtr()); + + permuteKernel->execute(srcData, dstData, MB); +} + void MKLDNNDepthToSpaceNode::execute(mkldnn::stream strm) { - const uint8_t* srcData = reinterpret_cast(this->getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); - uint8_t* dstData = reinterpret_cast(this->getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); + if (!execPtr) { + THROW_ERROR << "doesn't have a compiled executor."; + } + + int MB = isDynamicNode() ? getParentEdgeAt(0)->getMemoryPtr()->getStaticDims()[0] : batchToProcess(); + execPtr->exec(getParentEdgeAt(0)->getMemoryPtr(), getChildEdgeAt(0)->getMemoryPtr(), MB); +} - permuteKernel->execute(srcData, dstData, batchToProcess()); +void MKLDNNDepthToSpaceNode::executeDynamicImpl(mkldnn::stream strm) { + execute(strm); } bool MKLDNNDepthToSpaceNode::created() const { diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h index 0ab0b3bd940b06..f32a540cdc9ca3 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_depth_to_space_node.h @@ -15,13 +15,17 @@ class MKLDNNDepthToSpaceNode : public MKLDNNNode { public: MKLDNNDepthToSpaceNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; void createPrimitive() override; void execute(mkldnn::stream strm) override; bool created() const override; - static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; + void prepareParams() override; + +protected: + void executeDynamicImpl(mkldnn::stream strm) override; private: enum Mode { @@ -29,11 +33,26 @@ class MKLDNNDepthToSpaceNode : public MKLDNNNode { DEPTH_FIRST = 1 }; - Mode mode; - size_t blockSize; - size_t blockStep; - - std::unique_ptr permuteKernel; + struct DepthToSpaceAttrs { + LayoutType layoutType; + Mode mode; + size_t blockSize = 0lu; + size_t blockStep = 0lu; + size_t dataSize = 1lu; + size_t nSpatialDims = 0lu; + VectorDims srcBlockedDims; + } attrs; + + struct DepthToSpaceExecutor { + DepthToSpaceExecutor(const DepthToSpaceAttrs& attrs); + void exec(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr, const int MB); + ~DepthToSpaceExecutor() = default; + + private: + std::unique_ptr permuteKernel; + }; + using executorPtr = std::shared_ptr; + executorPtr execPtr = nullptr; }; } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_detection_output_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_detection_output_node.cpp index a2822931efd6ac..24b0269e8cff25 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_detection_output_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_detection_output_node.cpp @@ -15,6 +15,8 @@ using namespace mkldnn; using namespace MKLDNNPlugin; using namespace InferenceEngine; +namespace { + template bool SortScorePairDescend(const std::pair& pair1, const std::pair& pair2) { @@ -27,6 +29,8 @@ bool SortScorePairDescend>(const std::pair pair2.first) || (pair1.first == pair2.first && pair1.second.second < pair2.second.second); } +} // namespace + bool MKLDNNDetectionOutputNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { if (isDynamicNgraphNode(op)) { 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 cccf7afa988dca..bb9f21f1d4bfa4 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_eltwise_node.cpp @@ -1181,7 +1181,20 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() { portConfig.inPlace = (!i && canBeInPlace() && inputPrecisions[i] == outputPrecision) ? 0 : -1; portConfig.constant = false; - portConfig.desc = createMemoryDesc(getInputShapeAtPort(i), inputPrecisions[i], offset); + const auto &srcShape = getInputShapeAtPort(i); + portConfig.desc = createMemoryDesc(srcShape, inputPrecisions[i], offset); + if (!isDynamicNode() && srcShape.getDims()[0] == 1) { + const auto denseDesc = portConfig.desc->as(); + auto strides = denseDesc->getStrides(); + strides[0] = Shape::UNDEFINED_DIM; + portConfig.desc = std::make_shared(denseDesc->getPrecision(), + denseDesc->getShape(), + denseDesc->getBlockDims(), + denseDesc->getOrder(), + denseDesc->getOffsetPadding(), + denseDesc->getOffsetPaddingToData(), + strides); + } config.inConfs.push_back(portConfig); } @@ -1190,7 +1203,20 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() { portConfig.inPlace = -1; portConfig.constant = false; - portConfig.desc = createMemoryDesc(getOutputShapeAtPort(0), outputPrecision, offset); + const auto &dstShape = getOutputShapeAtPort(0); + portConfig.desc = createMemoryDesc(dstShape, outputPrecision, offset); + if (!isDynamicNode() && dstShape.getDims()[0] == 1) { + const auto denseDesc = portConfig.desc->as(); + auto strides = denseDesc->getStrides(); + strides[0] = Shape::UNDEFINED_DIM; + portConfig.desc = std::make_shared(denseDesc->getPrecision(), + denseDesc->getShape(), + denseDesc->getBlockDims(), + denseDesc->getOrder(), + denseDesc->getOffsetPadding(), + denseDesc->getOffsetPaddingToData(), + strides); + } config.outConfs.push_back(portConfig); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.cpp index 2d841ef9d085b5..4a1c30e16b163e 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.cpp @@ -311,10 +311,6 @@ void reorder_rois(const float *rois, const int* ids, int* mapping, const int roi bool MKLDNNExperimentalDetectronROIFeatureExtractorNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } const auto roiFeatureExtractor = std::dynamic_pointer_cast(op); if (!roiFeatureExtractor) { errorMessage = "Only opset6 ExperimentalDetectronROIFeatureExtractor operation is supported"; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.h index cb17ee2cadd621..aceba74e694f81 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_experimental_detectron_roifeatureextractor_node.h @@ -19,6 +19,9 @@ class MKLDNNExperimentalDetectronROIFeatureExtractorNode : public MKLDNNNode { void execute(mkldnn::stream strm) override; bool created() const override; + bool needPrepareParams() const override { return false; }; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); }; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.cpp index 66e6877034f465..6226ef03bfbf36 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_fullyconnected_node.cpp @@ -296,13 +296,16 @@ void MKLDNNFullyConnectedNode::createDescriptorInternal(const mkldnn::memory::de if (in_candidate.dims().size() == 3) { auto inDims = in_candidate.dims(); - auto outDims = out_candidate.dims(); auto normalizedInDims = {inDims[0] * inDims[1], inDims[2]}; - auto normalizedOutDims = {outDims[0] * outDims[1], outDims[2]}; in_candidate = mkldnn::memory::desc(normalizedInDims, in_candidate.data_type(), MKLDNNExtensionUtils::GetPlainFormatByRank(normalizedInDims.size())); + } + + if (out_candidate.dims().size() == 3) { + auto outDims = out_candidate.dims(); + auto normalizedOutDims = { outDims[0] * outDims[1], outDims[2] }; out_candidate = mkldnn::memory::desc(normalizedOutDims, out_candidate.data_type(), - MKLDNNExtensionUtils::GetPlainFormatByRank(normalizedOutDims.size())); + MKLDNNExtensionUtils::GetPlainFormatByRank(normalizedOutDims.size())); } mkldnn::memory::desc wgh_candidate(MKLDNNExtensionUtils::convertToDnnlDims(weightsDims), wdt, mkldnn::memory::format_tag::any); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.cpp index 4ca5fe84ecfb3f..a4045e233e6b82 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.cpp @@ -8,7 +8,7 @@ #include #include "ie_parallel.hpp" #include "mkldnn_gather_nd_node.h" -#include +#include #include #include #include "common/cpu_memcpy.h" @@ -16,15 +16,12 @@ using namespace MKLDNNPlugin; using namespace InferenceEngine; +#define THROW_ERROR IE_THROW() << "GatherND layer with name '" << getName() << "' " + bool MKLDNNGatherNDNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } - const auto gatherElementsOp = ngraph::as_type_ptr(op); - if (!gatherElementsOp) { - errorMessage = "Node is not an instance of the GatherND operation from operation set v5."; + if (!MKLDNNPlugin::one_of(op->get_type_info(), ngraph::op::v5::GatherND::get_type_info_static(), ngraph::op::v8::GatherND::get_type_info_static())) { + errorMessage = "Node is not an instance of the GatherND operation from operation set v5 and v8."; return false; } } catch (...) { @@ -40,58 +37,36 @@ MKLDNNGatherNDNode::MKLDNNGatherNDNode(const std::shared_ptr& op, if (!isSupportedOperation(op, errorMessage)) { IE_THROW(NotImplemented) << errorMessage; } - _errorPrefix = std::string("Layer GatherND with name '") + op->get_friendly_name() + "'"; - - if (op->get_input_size() != 2 || op->get_output_size() != 1) - IE_THROW() << _errorPrefix << " has invalid number of input/output edges."; - const auto& dataDims = op->get_input_shape(_dataIndex); - const auto& indicesDims = op->get_input_shape(_indicesIndex); + if (inputShapes.size() != 2 && outputShapes.size() != 1) + THROW_ERROR << "has invalid number of input/output edges."; - auto gatherNdOp = ngraph::as_type_ptr(op); - _batchDims = gatherNdOp->get_batch_dims(); - if (_batchDims >= std::min(dataDims.size(), indicesDims.size())) - IE_THROW() << _errorPrefix << " has invalid batch_dims attribute: " << _batchDims; + const size_t inputDataRank = getInputShapeAtPort(GATHERND_DATA).getRank(); + const size_t indicesDimsRank = getInputShapeAtPort(GATHERND_INDEXES).getRank(); - _batchNum = 1lu; - for (size_t i = 0; i < _batchDims; i++) { - _batchNum *= indicesDims[i]; + if (auto gatherNdOp = ngraph::as_type_ptr(op)) { + attrs.batchDims = gatherNdOp->get_batch_dims(); + } else if (auto gatherNdOp = ngraph::as_type_ptr(op)) { + attrs.batchDims = gatherNdOp->get_batch_dims(); + } else { + THROW_ERROR << "has support only opset5."; } - _sliceRank = indicesDims[indicesDims.size() - 1]; - _dataRank = dataDims.size() - _batchDims; - if (_sliceRank > _dataRank) - IE_THROW() << _errorPrefix << " has invalid inputs shapes."; - - _blockSize = 1; - for (size_t i = _sliceRank + _batchDims; i < dataDims.size(); i++) { - _blockSize *= dataDims[i]; - } - _batchStep = 1; - for (size_t i = _batchDims; i < dataDims.size(); i++) { - _batchStep *= dataDims[i]; - } + if (attrs.batchDims >= std::min(inputDataRank, indicesDimsRank)) + THROW_ERROR << "has invalid batch_dims attribute: " << attrs.batchDims; } void MKLDNNGatherNDNode::initSupportedPrimitiveDescriptors() { if (!supportedPrimitiveDescriptors.empty()) return; - Precision inDataPrecision = getOriginalInputPrecisionAtPort(_dataIndex); - if (!MKLDNNPlugin::one_of(inDataPrecision.size(), - sizeof(PrecisionTrait::value_type), - sizeof(PrecisionTrait::value_type), - sizeof(PrecisionTrait::value_type))) { - IE_THROW() << _errorPrefix << " has unsupported 'data' input precision: " << inDataPrecision; - } - - Precision indicesPrecision = getOriginalInputPrecisionAtPort(_indicesIndex); + Precision inDataPrecision = getOriginalInputPrecisionAtPort(GATHERND_DATA); + Precision indicesPrecision = getOriginalInputPrecisionAtPort(GATHERND_INDEXES); if (!MKLDNNPlugin::one_of(indicesPrecision, Precision::I32, Precision::I64, Precision::I16, Precision::U16, Precision::I8, Precision::U8)) { - IE_THROW() << _errorPrefix << " has unsupported 'indices' input precision: " << indicesPrecision; + THROW_ERROR << "has unsupported 'indices' input precision: " << indicesPrecision; } - - _dataTypeSize = inDataPrecision.size(); + attrs.dataSize = inDataPrecision.size(); addSupportedPrimDesc({{LayoutType::ncsp, inDataPrecision}, {LayoutType::ncsp, Precision::I32}}, @@ -99,121 +74,77 @@ void MKLDNNGatherNDNode::initSupportedPrimitiveDescriptors() { impl_desc_type::ref_any); } -template -void MKLDNNGatherNDNode::gatherElementwise() { - const auto *srcData = reinterpret_cast(getParentEdgeAt(_dataIndex)->getMemoryPtr()->GetPtr()); - const auto *indices = reinterpret_cast(getParentEdgeAt(_indicesIndex)->getMemoryPtr()->GetPtr()); - auto *dstData = reinterpret_cast(getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); - - auto strides = getParentEdgeAt(_dataIndex)->getMemory().GetDescWithType()->getStrides(); - const size_t* srcMultipliers = strides.data() + _batchDims; - - const size_t cycles = getChildEdgeAt(0)->getMemory().GetShape().getElementsCount() * - getChildEdgeAt(0)->getMemory().getDesc().getPrecision().size() / (sizeof(dataType) * _batchNum); - const size_t CS = cycles * _sliceRank; - const size_t CB = cycles * _blockSize; - const size_t workAmount = _batchNum * cycles; - - auto threadBody = [&](const int ithr, const int nthr) { - size_t start(0lu), end(0lu); - splitter(workAmount, nthr, ithr, start, end); - if (start >= end) - return; - size_t bStart = start / cycles; - size_t cStart = start % cycles; - size_t workCounter = start; - - const dataType* shiftedSrcData = srcData + bStart * _batchStep; - const int* shiftedIndices = indices + bStart * CS + cStart * _sliceRank; - dataType* shiftedDstData = dstData + bStart * CB + cStart * _blockSize; - - for (size_t b = bStart; b < _batchNum; b++) { - for (size_t j = cStart; j < cycles; j++) { - size_t dataIdx = 0lu; - for (size_t i = 0lu; i < _sliceRank; i++) - dataIdx += srcMultipliers[i] * shiftedIndices[i]; - shiftedDstData[0] = shiftedSrcData[dataIdx]; - shiftedDstData++; - shiftedIndices += _sliceRank; - if (++workCounter == end) { - return; - } - } - cStart = 0lu; - shiftedSrcData += _batchStep; - } - }; +void MKLDNNGatherNDNode::createPrimitive() { + if (inputShapesDefined()) { + if (needPrepareParams()) + prepareParams(); + updateLastInputDims(); + } +} - parallel_nt(0, threadBody); +void MKLDNNGatherNDNode::prepareParams() { + auto& srcMemPtr = getParentEdgeAt(GATHERND_DATA)->getMemoryPtr(); + auto& idxMemPtr = getParentEdgeAt(GATHERND_INDEXES)->getMemoryPtr(); + auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); + if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) + THROW_ERROR << " has not allocated input memory of 'data'."; + if (!idxMemPtr || !idxMemPtr->GetPrimitivePtr()) + THROW_ERROR << " has not allocated input memory of 'indices'."; + if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr()) + THROW_ERROR << " has not allocated output memory."; + if (getSelectedPrimitiveDescriptor() == nullptr) + THROW_ERROR << " has unidentified preferable primitive descriptor."; + + attrs.srcDims = srcMemPtr->getStaticDims(); + attrs.srcStrides = srcMemPtr->GetDescWithType()->getStrides(); + attrs.dstSize = dstMemPtr->GetSize(); + attrs.sliceRank = idxMemPtr->getStaticDims().back(); + execPtr = std::make_shared(attrs); } -void MKLDNNGatherNDNode::gatherBlocks() { - const uint8_t* srcData = reinterpret_cast(getParentEdgeAt(_dataIndex)->getMemoryPtr()->GetPtr()); - const int* indices = reinterpret_cast(getParentEdgeAt(_indicesIndex)->getMemoryPtr()->GetPtr()); - uint8_t* dstData = reinterpret_cast(getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); - - std::vector srcMultipliers(_sliceRank); - for (size_t i = 0; i < _sliceRank ; i++) - srcMultipliers[i] = _dataTypeSize * getParentEdgeAt(_dataIndex)->getMemory().GetDescWithType()->getStrides()[i + _batchDims]; - - const size_t batchStep = _batchStep * _dataTypeSize; - const size_t dataStep = _blockSize * _dataTypeSize; - const size_t cycles = getChildEdgeAt(0)->getMemory().GetSize() / (dataStep * _batchNum); - const size_t CS = cycles * _sliceRank; - const size_t CB = cycles * dataStep; - const size_t workAmount = _batchNum * cycles; - - auto threadBody = [&](const int ithr, const int nthr) { - size_t start(0lu), end(0lu); - splitter(workAmount, nthr, ithr, start, end); - if (start >= end) - return; - size_t bStart = start / cycles; - size_t cStart = start % cycles; - size_t workCounter = start; - - const uint8_t* shiftedSrcData = srcData + bStart * batchStep; - const int* shiftedIndices = indices + bStart * CS + cStart * _sliceRank; - uint8_t* shiftedDstData = dstData + bStart * CB + cStart * dataStep; - - for (size_t b = bStart; b < _batchNum; b++) { - for (size_t j = cStart; j < cycles; j++) { - size_t dataIdx = 0lu; - for (size_t i = 0; i < _sliceRank ; i++) - dataIdx += srcMultipliers[i] * shiftedIndices[i]; - cpu_memcpy(shiftedDstData, &(shiftedSrcData[dataIdx]), dataStep); - shiftedDstData += dataStep; - shiftedIndices += _sliceRank; - if (++workCounter == end) { - return; - } - } - cStart = 0; - shiftedSrcData += batchStep; - } - }; +MKLDNNGatherNDNode::GatherNDExecutor::GatherNDExecutor(const GatherNDAttributes& attrs) : attrs(attrs) { + batchSize = std::accumulate(attrs.srcDims.begin(), attrs.srcDims.begin() + attrs.batchDims, 1lu, std::multiplies()); + dataLength = std::accumulate(attrs.srcDims.begin() + attrs.sliceRank + attrs.batchDims, attrs.srcDims.end(), 1lu, + std::multiplies()) * attrs.dataSize; + cycles = attrs.dstSize / (dataLength * batchSize); + + srcBatchStride = std::accumulate(attrs.srcDims.begin() + attrs.batchDims, attrs.srcDims.end(), 1lu, + std::multiplies()) * attrs.dataSize; + idxBatchStride = cycles * attrs.sliceRank; + dstBatchStride = cycles * dataLength; - parallel_nt(0, threadBody); + srcShifts.resize(attrs.sliceRank, 0); + for (size_t i = 0; i < attrs.sliceRank ; i++) + srcShifts[i] = attrs.srcStrides[i + attrs.batchDims] * attrs.dataSize; +} + +void MKLDNNGatherNDNode::GatherNDExecutor::exec(const uint8_t* srcData, const int32_t* indices, uint8_t* dstData) { + parallel_for2d(batchSize, cycles, [&](const size_t b, const size_t j) { + const size_t srcStride = b * srcBatchStride; + const size_t idxStride = b * idxBatchStride + j * attrs.sliceRank; + const size_t dstStride = b * dstBatchStride + j * dataLength; + + size_t dataIdx = 0lu; + for (size_t i = 0; i < attrs.sliceRank ; ++i) + dataIdx += srcShifts[i] * indices[idxStride + i]; + + cpu_memcpy(&dstData[dstStride], &srcData[srcStride + dataIdx], dataLength); + }); } void MKLDNNGatherNDNode::execute(mkldnn::stream strm) { - if (_blockSize > 1) { - gatherBlocks(); - } else { - switch (_dataTypeSize) { - case sizeof(PrecisionTrait::value_type): - gatherElementwise::value_type>(); - break; - case sizeof(PrecisionTrait::value_type): - gatherElementwise::value_type>(); - break; - case sizeof(PrecisionTrait::value_type): - gatherElementwise::value_type>(); - break; - default: - IE_THROW() << _errorPrefix + " has data input with unsupported precision: " + getOriginalInputPrecisionAtPort(_dataIndex).name(); - } - } + if (!execPtr) + THROW_ERROR << "has not compiled executor."; + + const uint8_t* srcData = reinterpret_cast(getParentEdgeAt(GATHERND_DATA)->getMemoryPtr()->GetPtr()); + const int32_t* indices = reinterpret_cast(getParentEdgeAt(GATHERND_INDEXES)->getMemoryPtr()->GetPtr()); + uint8_t* dstData = reinterpret_cast(getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); + + execPtr->exec(srcData, indices, dstData); +} + +void MKLDNNGatherNDNode::executeDynamicImpl(dnnl::stream strm) { + execute(strm); } bool MKLDNNGatherNDNode::created() const { diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h index 3d826621c9d0af..fefce4415906c8 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_gather_nd_node.h @@ -18,27 +18,50 @@ class MKLDNNGatherNDNode : public MKLDNNNode { void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; - void createPrimitive() override {}; + void createPrimitive() override; void execute(mkldnn::stream strm) override; bool created() const override; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; +protected: + void executeDynamicImpl(mkldnn::stream strm) override; + void prepareParams() override; + private: - size_t _dataRank; - size_t _sliceRank; - size_t _blockSize; - size_t _batchDims; - size_t _batchNum; - size_t _batchStep; - size_t _dataTypeSize; - const size_t _dataIndex = 0; - const size_t _indicesIndex = 1; - std::string _errorPrefix; - - template - void gatherElementwise(); - void gatherBlocks(); + struct GatherNDAttributes { + size_t batchDims = 0lu; + size_t dataSize = 1lu; + size_t dstSize = 0lu; + size_t sliceRank = 0lu; + + VectorDims srcDims; + VectorDims srcStrides; + } attrs; + + struct GatherNDExecutor { + GatherNDExecutor(const GatherNDAttributes& attrs); + ~GatherNDExecutor() = default; + void exec(const uint8_t* srcData, const int32_t* indices, uint8_t* dstData); + + private: + size_t batchSize = 1lu; + size_t cycles = 1lu; + size_t dataLength = 1lu; + + size_t srcBatchStride = 1lu; + size_t idxBatchStride = 1lu; + size_t dstBatchStride = 1lu; + VectorDims srcShifts; + + GatherNDAttributes attrs; + }; + + static constexpr size_t GATHERND_DATA = 0lu; + static constexpr size_t GATHERND_INDEXES = 1lu; + + using executorPtr = std::shared_ptr; + executorPtr execPtr = nullptr; }; } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.cpp index 3efe3f69cbe456..9f537b490fcac7 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.cpp @@ -13,10 +13,6 @@ using namespace InferenceEngine; bool MKLDNNLogSoftmaxNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } const auto logSoftMax = std::dynamic_pointer_cast(op); if (!logSoftMax) { errorMessage = "Only opset5 LogSoftmax operation is supported"; @@ -41,21 +37,45 @@ MKLDNNLogSoftmaxNode::MKLDNNLogSoftmaxNode(const std::shared_ptr& IE_THROW() << "Operation with name '" << op->get_friendly_name() << "' is not an instance of LogSoftmax from opset5."; - if (getOriginalInputsNumber() != 1 || getOriginalOutputsNumber() != 1) + if (inputShapes.size() != 1 || outputShapes.size() != 1) IE_THROW() << errorPrefix << " has incorrect number of input/output edges!"; - SizeVector dims = op->get_input_shape(0); - if (!dims.size()) - dims = SizeVector(1, 1); - int axis = logSoftMax->get_axis(); + auto dimsSize = getInputShapeAtPort(0).getDims().size(); + if (dimsSize == 0) + dimsSize += 1; + axis = logSoftMax->get_axis(); if (axis < 0) - axis += dims.size(); + axis += dimsSize; - if (dims.size() < static_cast((size_t)(1) + axis)) + if (dimsSize < static_cast((size_t)(1) + axis)) IE_THROW() << errorPrefix << " has incorrect input parameters dimensions and axis number!"; +} + +void MKLDNNLogSoftmaxNode::initSupportedPrimitiveDescriptors() { + if (!supportedPrimitiveDescriptors.empty()) + return; - int j; - for (j = dims.size() - 1; j >= 0; j--) { + addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32}}, + {{LayoutType::ncsp, Precision::FP32}}, + impl_desc_type::ref_any); +} + +void MKLDNNLogSoftmaxNode::createPrimitive() { + if (inputShapesDefined()) { + if (needPrepareParams()) + prepareParams(); + updateLastInputDims(); + } +} + +void MKLDNNLogSoftmaxNode::prepareParams() { + const auto &dims = getParentEdgesAtPort(0)[0]->getMemory().getStaticDims(); + reducedAxisStride = 1; + axisStep = 1; + isLastDim = false; + + int j = static_cast(dims.size()) - 1; + for (; j >= 0; j--) { if (dims[j] != 1) break; } if (j == axis) isLastDim = true; @@ -67,15 +87,6 @@ MKLDNNLogSoftmaxNode::MKLDNNLogSoftmaxNode(const std::shared_ptr& reducedAxisStride *= dims[i]; } -void MKLDNNLogSoftmaxNode::initSupportedPrimitiveDescriptors() { - if (!supportedPrimitiveDescriptors.empty()) - return; - - addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32}}, - {{LayoutType::ncsp, Precision::FP32}}, - impl_desc_type::ref_any); -} - void MKLDNNLogSoftmaxNode::execute(mkldnn::stream strm) { const float *srcData = reinterpret_cast(getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); float* dstData = reinterpret_cast(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr()); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.h index 15479cb81ffff5..f74b4dbae9af73 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_log_softmax_node.h @@ -16,13 +16,17 @@ class MKLDNNLogSoftmaxNode : public MKLDNNNode { void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; - void createPrimitive() override {}; + void createPrimitive() override; void execute(mkldnn::stream strm) override; bool created() const override; + void prepareParams() override; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); }; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: + int axis; size_t reducedAxisSize; size_t reducedAxisStride = 1; size_t axisStep = 1; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.cpp index 4f8d4fba1e11aa..163e76ca483a1a 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.cpp @@ -16,10 +16,6 @@ using namespace InferenceEngine; bool MKLDNNMathNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } if (initializers.find(op->get_type_info()) == initializers.end()) { errorMessage = "Unsupported Math layer type."; return false; @@ -63,6 +59,10 @@ void MKLDNNMathNode::initSupportedPrimitiveDescriptors() { impl_desc_type::ref_any); } +std::vector MKLDNNMathNode::shapeInfer() const { + return std::vector{getParentEdgesAtPort(0)[0]->getMemory().getStaticDims()}; +} + void MKLDNNMathNode::execute(mkldnn::stream strm) { size_t dataSize = getChildEdgesAtPort(0)[0]->getMemory().GetShape().getElementsCount(); const float *src_data = reinterpret_cast(getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.h index 5c5de72a750a70..ee2ce5d75b1475 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_math_node.h @@ -19,6 +19,10 @@ class MKLDNNMathNode : public MKLDNNNode { void execute(mkldnn::stream strm) override; bool created() const override; + std::vector shapeInfer() const override; + bool needPrepareParams() const override { return false; }; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); }; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matrix_nms_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matrix_nms_node.h index e0b77e3f08062f..d87cc68d867370 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matrix_nms_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_matrix_nms_node.h @@ -13,7 +13,7 @@ namespace MKLDNNPlugin { -enum MatrixNmsSortResultType { +enum class MatrixNmsSortResultType { CLASSID, // sort selected boxes by class id (ascending) in each batch element SCORE, // sort selected boxes by score (descending) in each batch element NONE // do not guarantee the order in each batch element diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.cpp index 64d08e0fab3255..15f26d87145aef 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.cpp @@ -214,20 +214,20 @@ void MKLDNNMultiClassNmsNode::execute(mkldnn::stream strm) { } if (sort_result_across_batch) { - if (sort_result_type == SCORE) { + if (sort_result_type == MulticlassNmsSortResultType::SCORE) { parallel_sort(filtBoxes.begin(), filtBoxes.begin() + startOffset, [](const filteredBoxes& l, const filteredBoxes& r) { return (l.score > r.score) || (l.score == r.score && l.batch_index < r.batch_index) || (l.score == r.score && l.batch_index == r.batch_index && l.class_index < r.class_index) || (l.score == r.score && l.batch_index == r.batch_index && l.class_index == r.class_index && l.box_index < r.box_index); }); - } else if (sort_result_type == CLASSID) { + } else if (sort_result_type == MulticlassNmsSortResultType::CLASSID) { parallel_sort(filtBoxes.begin(), filtBoxes.begin() + startOffset, [](const filteredBoxes& l, const filteredBoxes& r) { return (l.class_index < r.class_index) || (l.class_index == r.class_index && l.batch_index < r.batch_index) || (l.class_index == r.class_index && l.batch_index == r.batch_index && l.score > r.score) || (l.class_index == r.class_index && l.batch_index == r.batch_index && l.score == r.score && l.box_index < r.box_index); }); } - } else if (sort_result_type == CLASSID) { + } else if (sort_result_type == MulticlassNmsSortResultType::CLASSID) { parallel_sort(filtBoxes.begin(), filtBoxes.begin() + startOffset, [](const filteredBoxes& l, const filteredBoxes& r) { return ((l.batch_index < r.batch_index) || ((l.batch_index == r.batch_index) && diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.hpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.hpp index ac4a350bc564cd..2fbdc2a9712a61 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.hpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_multiclass_nms.hpp @@ -11,7 +11,7 @@ namespace MKLDNNPlugin { -enum MulticlassNmsSortResultType { +enum class MulticlassNmsSortResultType { CLASSID, // sort selected boxes by class id (ascending) in each batch element SCORE, // sort selected boxes by score (descending) in each batch element NONE // do not guarantee the order in each batch element @@ -40,7 +40,7 @@ class MKLDNNMultiClassNmsNode : public MKLDNNNode { const size_t NMS_SELECTEDNUM = 2; bool sort_result_across_batch = false; - MulticlassNmsSortResultType sort_result_type = NONE; + MulticlassNmsSortResultType sort_result_type = MulticlassNmsSortResultType::NONE; size_t num_batches; size_t num_boxes; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.cpp index aec7819ce95020..6bd0e44ae8c953 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.cpp @@ -20,21 +20,13 @@ using namespace InferenceEngine; bool MKLDNNNonMaxSuppressionNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (op->is_dynamic()) { - errorMessage = "Doesn't support op with dynamic input shapes"; - return false; - } - + // TODO [DS NMS]: remove when nodes from models where nms is not last node in model supports DS using NonMaxSuppressionV5 = ngraph::op::v5::NonMaxSuppression; if (!one_of(op->get_type_info(), NonMaxSuppressionV5::get_type_info_static(), ngraph::op::internal::NonMaxSuppressionIEInternal::get_type_info_static())) { errorMessage = "Only NonMaxSuppression v5 and NonMaxSuppressionIEInternal are supported"; return false; } - if (op->get_input_size() > 2 && !dynamic_cast(op->get_input_node_ptr(2))) { - errorMessage = "Doesn't support NonMaxSuppression with undefined max_output_boxes_per_class"; - return false; - } if (const auto nms5 = std::dynamic_pointer_cast(op)) { const auto boxEncoding = nms5->get_box_encoding(); @@ -67,6 +59,7 @@ MKLDNNNonMaxSuppressionNode::MKLDNNNonMaxSuppressionNode(const std::shared_ptr(op)) { boxEncodingType = static_cast(nms5->get_box_encoding()); sort_result_descending = nms5->get_sort_result_descending(); + // TODO [DS NMS]: remove when nodes from models where nms is not last node in model supports DS } else if (const auto nmsIe = std::dynamic_pointer_cast(op)) { boxEncodingType = nmsIe->m_center_point_box ? boxEncoding::CENTER : boxEncoding::CORNER; sort_result_descending = nmsIe->m_sort_result_descending; @@ -75,28 +68,16 @@ MKLDNNNonMaxSuppressionNode::MKLDNNNonMaxSuppressionNode(const std::shared_ptrgetMemory().getStaticDims() : + getInputShapeAtPort(NMS_BOXES).getStaticDims(); + const auto& scores_dims = isDynamicNode() ? getParentEdgesAtPort(NMS_SCORES)[0]->getMemory().getStaticDims() : + getInputShapeAtPort(NMS_SCORES).getStaticDims(); + + num_batches = boxes_dims[0]; + num_boxes = boxes_dims[1]; + num_classes = scores_dims[1]; + if (num_batches != scores_dims[0]) + IE_THROW() << errorPrefix << " num_batches is different in 'boxes' and 'scores' inputs"; + if (num_boxes != scores_dims[2]) + IE_THROW() << errorPrefix << " num_boxes is different in 'boxes' and 'scores' inputs"; + + numFiltBox.resize(num_batches); + for (auto & i : numFiltBox) + i.resize(num_classes); +} + +void MKLDNNNonMaxSuppressionNode::createPrimitive() { + if (inputShapesDefined()) { + prepareParams(); + updateLastInputDims(); + } +} + +void MKLDNNNonMaxSuppressionNode::executeDynamicImpl(mkldnn::stream strm) { + execute(strm); +} + void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) { const float *boxes = reinterpret_cast(getParentEdgeAt(NMS_BOXES)->getMemoryPtr()->GetPtr()); const float *scores = reinterpret_cast(getParentEdgeAt(NMS_SCORES)->getMemoryPtr()->GetPtr()); @@ -155,9 +166,7 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) { max_output_boxes_per_class = reinterpret_cast(getParentEdgeAt(NMS_MAXOUTPUTBOXESPERCLASS)->getMemoryPtr()->GetPtr())[0]; } - if (!isDynamicNode()) { - max_output_boxes_per_class = std::min(max_output_boxes_per_class, num_boxes); - } + max_output_boxes_per_class = std::min(max_output_boxes_per_class, num_boxes); if (max_output_boxes_per_class == 0) return; @@ -216,6 +225,7 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) { auto scoresMemPtr = getChildEdgesAtPort(NMS_SELECTEDSCORES)[0]->getMemoryPtr(); const size_t validOutputs = std::min(filtBoxes.size(), maxNumberOfBoxes); + // TODO [DS NMS]: remove when nodes from models where nms is not last node in model supports DS if (isDynamicNode()) { VectorDims newDims{validOutputs, 3}; indicesMemPtr->redefineDesc(getBaseMemDescAtOutputPort(NMS_SELECTEDINDICES)->cloneWithNewDims(newDims)); @@ -240,6 +250,7 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) { selectedScoresPtr += selectedIndicesStride; } + // TODO [DS NMS]: remove when nodes from models where nms is not last node in model supports DS if (!isDynamicNode()) { std::fill(selectedIndicesPtr, selectedIndicesPtr + (maxNumberOfBoxes - idx) * selectedIndicesStride, -1); std::fill(selectedScoresPtr, selectedScoresPtr + (maxNumberOfBoxes - idx) * selectedIndicesStride, -1.f); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.h index 1578e6f4a32a8a..bbd6e8cf0814bf 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_max_suppression_node.h @@ -20,7 +20,7 @@ class MKLDNNNonMaxSuppressionNode : public MKLDNNNode { void getSupportedDescriptors() override {}; void initSupportedPrimitiveDescriptors() override; - void createPrimitive() override {}; + void createPrimitive() override; void execute(mkldnn::stream strm) override; bool created() const override; @@ -50,10 +50,10 @@ class MKLDNNNonMaxSuppressionNode : public MKLDNNNode { void nmsWithoutSoftSigma(const float *boxes, const float *scores, const SizeVector &boxesStrides, const SizeVector &scoresStrides, std::vector &filtBoxes); - void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); } + void executeDynamicImpl(mkldnn::stream strm) override; bool needShapeInfer() const override { return false; } - bool needPrepareParams() const override { return false; } + void prepareParams() override; private: // input diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_zero.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_zero.cpp new file mode 100644 index 00000000000000..f6e0624a4ba0c9 --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_zero.cpp @@ -0,0 +1,138 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "mkldnn_non_zero.h" +#include +#include + +using namespace MKLDNNPlugin; +using namespace InferenceEngine; + +bool MKLDNNNonZeroNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { + try { + if (op->get_type_info() != ngraph::op::v3::NonZero::get_type_info_static()) { + errorMessage = "Node is not an instance of NonZero from the operation set v3."; + return false; + } + } catch (...) { + return false; + } + return true; +} + +MKLDNNNonZeroNode::MKLDNNNonZeroNode(const std::shared_ptr& op, const mkldnn::engine& eng, + MKLDNNWeightsSharing::Ptr &cache) : MKLDNNNode(op, eng, cache) { + std::string errorMessage; + if (isSupportedOperation(op, errorMessage)) { + errorPrefix = "NonZero layer with name '" + getName() + "' "; + } else { + IE_THROW(NotImplemented) << errorMessage; + } + if (op->get_output_element_type(0) != ngraph::element::i32) { + IE_THROW() << errorPrefix << "doesn't support demanded output precision"; + } +} + +void MKLDNNNonZeroNode::getSupportedDescriptors() { + if (!descs.empty()) + return; + if (getParentEdges().size() != 1) + IE_THROW() << errorPrefix << "has incorrect number of input edges: " << getParentEdges().size(); + if (getChildEdges().size() != 1) + IE_THROW() << errorPrefix << "has incorrect number of output edges: " << getChildEdges().size(); +} + +void MKLDNNNonZeroNode::initSupportedPrimitiveDescriptors() { + if (!supportedPrimitiveDescriptors.empty()) + return; + + const auto &inPrc = getOriginalInputPrecisionAtPort(0); + if (!one_of(inPrc, Precision::FP32, Precision::BF16, Precision::I32, Precision::U32, Precision::I8, Precision::U8)) { + IE_THROW() << "Can't create primitive descriptor for NonZero layer with name: " << getName() << " doesn't support " + << inPrc.name() << " precision on 0 port"; + } + + addSupportedPrimDesc({{LayoutType::ncsp}}, + {{LayoutType::ncsp, Precision::I32}}, + impl_desc_type::ref); +} + +template +size_t MKLDNNNonZeroNode::getNonZeroElementsCount(const T* src, const Shape& inShape) { + T zero = 0; + size_t count = 0; + size_t inSize = inShape.getElementsCount(); + if (inShape.getRank() == 0) { + if (src[0] != zero) + count = 1; + } else { + for (size_t i = 0; i < inSize; i++) { + if (src[i] != zero) + count++; + } + } + return count; +} +namespace { +struct NonZeroContext { + MKLDNNNonZeroNode &node; +}; +} +template +struct MKLDNNNonZeroNode::NonZeroExecute { + void operator()(NonZeroContext & ctx) { + ctx.node.executeSpecified(); + } +}; +void MKLDNNNonZeroNode::execute(mkldnn::stream strm) { + auto inputPrec = getParentEdgesAtPort(0)[0]->getMemory().getDesc().getPrecision(); + NonZeroContext ctx = {*this }; + OV_SWITCH(MKLDNNPlugin, NonZeroExecute, ctx, inputPrec, + OV_CASE(Precision::FP32, float), + OV_CASE(Precision::BF16, bfloat16_t), + OV_CASE(Precision::I32, int), + OV_CASE(Precision::U32, uint32_t), + OV_CASE(Precision::I8, int8_t), + OV_CASE(Precision::U8, uint8_t)) +} +template +void MKLDNNNonZeroNode::executeSpecified() { + T zero = 0; + T *src = reinterpret_cast(getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); + auto dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); + Shape inShape = getParentEdgeAt(0)->getMemory().GetShape(); + size_t inRank = inShape.getRank(); + size_t nonZeroCount = getNonZeroElementsCount(src, inShape); + if (isDynamicNode()) { + VectorDims newDims{inRank, nonZeroCount}; + dstMemPtr->redefineDesc(getBaseMemDescAtOutputPort(0)->cloneWithNewDims(newDims)); + } + int *dst = reinterpret_cast(dstMemPtr->GetPtr()); + size_t inSize = inShape.getElementsCount(); + auto srcStrides = getParentEdgeAt(0)->getMemory().GetDescWithType()->getStrides(); + if (nonZeroCount == 0) + return; + if (inShape.getRank() == 0) { + dst[0] = 0; + } else { + size_t colIndex = 0, outIndex = 0; + for (size_t i = 0; i < inSize; i++) { + if (src[i] != zero) { + size_t temp = i; + for (size_t j = 0; j < inRank; j++) { + outIndex = j * nonZeroCount + colIndex; + dst[outIndex] = temp / srcStrides[j]; + temp = temp % srcStrides[j]; + } + colIndex++; + } + } + } +} + +bool MKLDNNNonZeroNode::created() const { + return getType() == NonZero; +} + +REG_MKLDNN_PRIM_FOR(MKLDNNNonZeroNode, NonZero) diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_zero.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_zero.h new file mode 100644 index 00000000000000..2f46042a331d5e --- /dev/null +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_non_zero.h @@ -0,0 +1,42 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace MKLDNNPlugin { + +class MKLDNNNonZeroNode : public MKLDNNNode { +public: + MKLDNNNonZeroNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); + + void getSupportedDescriptors() override; + void initSupportedPrimitiveDescriptors() override; + void createPrimitive() override { + if (inputShapesDefined()) + updateLastInputDims(); + }; + void execute(mkldnn::stream strm) override; + bool created() const override; + bool needShapeInfer() const override {return false;}; + bool needPrepareParams() const override {return false;}; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); } + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; + +private: + std::string errorPrefix; + template + void executeSpecified(); + template + struct NonZeroExecute; + template + size_t getNonZeroElementsCount(const T* arg, const Shape& arg_shape); +}; + +} // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.cpp index 626d66921d1d59..db4eb8629219c1 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.cpp @@ -18,36 +18,37 @@ using namespace mkldnn; using namespace MKLDNNPlugin; using namespace InferenceEngine; +#define THROW_ERROR IE_THROW() << "Pad layer with name '" << getName() << "' " + bool MKLDNNPadNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } - - const auto pad = std::dynamic_pointer_cast(op); + auto pad = ov::as_type_ptr(op); if (!pad) { errorMessage = "Only opset1 Pad operation is supported"; return false; } - if (std::dynamic_pointer_cast(pad->get_input_node_shared_ptr(PADS_BEGIN_ID)) == nullptr || - std::dynamic_pointer_cast(pad->get_input_node_shared_ptr(PADS_END_ID)) == nullptr || - (pad->get_pad_mode() == ngraph::op::PadMode::CONSTANT && pad->get_input_size() == 4 && - std::dynamic_pointer_cast(pad->get_input_node_shared_ptr(PAD_VALUE_ID)) == nullptr)) { - errorMessage = "Only Constant operation on 'pads_begin', 'pads_end', 'pad_value' inpus is supported"; - return false; - } + const auto pad_mode = pad->get_pad_mode(); - if (pad_mode != ngraph::op::PadMode::CONSTANT && pad_mode != ngraph::op::PadMode::EDGE && pad_mode != ngraph::op::PadMode::REFLECT && - pad_mode != ngraph::op::PadMode::SYMMETRIC) { + if (!MKLDNNPlugin::one_of(pad_mode, ngraph::op::PadMode::CONSTANT, ngraph::op::PadMode::EDGE, ngraph::op::PadMode::REFLECT, + ngraph::op::PadMode::SYMMETRIC)) { errorMessage = "Has unsupported pad_mode: " + ngraph::as_string(pad_mode); return false; } + + if (op->get_input_node_shared_ptr(PADS_BEGIN_ID)->get_type_info() != ov::op::v0::Constant::get_type_info_static() || + op->get_input_node_shared_ptr(PADS_END_ID)->get_type_info() != ov::op::v0::Constant::get_type_info_static() || + (pad->get_input_size() == 4 && pad->get_pad_mode() == ngraph::op::PadMode::CONSTANT && + op->get_input_node_shared_ptr(PAD_VALUE_ID)->get_type_info() != ov::op::v0::Constant::get_type_info_static())) { + // TODO: Support pads_begin, pads_end, pad_value inputs for dynamic shapes. + errorMessage = "Only Constant 'pads_begin', 'pads_end' and 'pad_value' inputs are supported."; + return false; + } + const auto pb = pad->get_pads_begin(); const auto pe = pad->get_pads_end(); - if (std::count_if(pb.begin(), pb.end(), [](ptrdiff_t x) { return x < 0; }) != 0 || - std::count_if(pe.begin(), pe.end(), [](ptrdiff_t x) { return x < 0; }) != 0) { - errorMessage = "Doesn't support 'pads_begin' or 'pads_end' negative value"; + if (std::any_of(pb.begin(), pb.end(), [](ptrdiff_t x) { return x < 0; }) || + std::any_of(pe.begin(), pe.end(), [](ptrdiff_t x) { return x < 0; })) { + errorMessage = "Doesn't support 'pads_begin' or 'pads_end' with negative values"; return false; } } catch (...) { @@ -59,62 +60,61 @@ bool MKLDNNPadNode::isSupportedOperation(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache) : MKLDNNNode(op, eng, cache) { std::string errorMessage; - if (isSupportedOperation(op, errorMessage)) { - errorPrefix = "Pad node with name '" + op->get_friendly_name() + "'"; - const auto pad = std::dynamic_pointer_cast(op); + if (!isSupportedOperation(op, errorMessage)) { + IE_THROW(NotImplemented) << errorMessage; + } + + if (inputShapes.size() != 3 && inputShapes.size() != 4) + THROW_ERROR << " has incorrect number of input edges"; + if (outputShapes.size() != 1) + THROW_ERROR << "Incorrect number of output edges"; + const size_t srcDimsRank = inputShapes[DATA_ID].getRank(); + const size_t dstDimsRank = outputShapes[DATA_ID].getRank(); + if (srcDimsRank != dstDimsRank) + THROW_ERROR << "has incorrect number of input/output dimensions!"; + + auto pad = ov::as_type_ptr(op); + if (!pad) { + THROW_ERROR << "couldn't be casted to op of opset1"; + } + + if (op->get_input_node_shared_ptr(PADS_BEGIN_ID)->get_type_info() == ov::op::v0::Constant::get_type_info_static() && + op->get_input_node_shared_ptr(PADS_END_ID)->get_type_info() == ov::op::v0::Constant::get_type_info_static()) { const auto pb = pad->get_pads_begin(); const auto pe = pad->get_pads_end(); + for (size_t i = 0; i < pb.size(); i++) - padsBegin.push_back(static_cast(pb[i])); - for (size_t i = 0; i < pe.size(); i++) - padsEnd.push_back(static_cast(pe[i])); + attrs.padsBegin.push_back(static_cast(pb[i])); + for (size_t i = 0; i < pe.size(); i++) + attrs.padsEnd.push_back(static_cast(pe[i])); - const auto pad_mode = pad->get_pad_mode(); - isPadValueSpecified = pad->get_input_size() == 4; - if (pad_mode == ngraph::op::PadMode::CONSTANT) { - padMode = CONSTANT; - if (isPadValueSpecified) { - if (!ngraph::is_scalar(pad->get_input_shape(PAD_VALUE_ID))) - IE_THROW() << errorPrefix << " has non scalar 'pad_value' input"; - padValue = std::dynamic_pointer_cast(pad->get_input_node_shared_ptr(PAD_VALUE_ID))->cast_vector()[0]; - } - } else if (pad_mode == ngraph::op::PadMode::EDGE) { - padMode = EDGE; - } else if (pad_mode == ngraph::op::PadMode::REFLECT) { - padMode = REFLECT; - } else if (pad_mode == ngraph::op::PadMode::SYMMETRIC) { - padMode = SYMMETRIC; - } - } else { - IE_THROW(NotImplemented) << errorMessage; + if (attrs.padsBegin.size() != srcDimsRank || attrs.padsEnd.size() != srcDimsRank) + THROW_ERROR << "has incorrect number of input/output dimensions!"; } -} -void MKLDNNPadNode::getSupportedDescriptors() { - if (getParentEdges().size() != 3 && getParentEdges().size() != 4) - IE_THROW() << errorPrefix << " has incorrect number of input edges"; - if (getChildEdges().empty()) - IE_THROW() << errorPrefix << "Incorrect number of output edges"; - - const auto srcDims = getInputShapeAtPort(DATA_ID).getStaticDims(); - const auto dstDims = getOutputShapeAtPort(DATA_ID).getStaticDims(); - if (srcDims.size() != dstDims.size() || padsBegin.size() != srcDims.size() || padsEnd.size() != srcDims.size()) - IE_THROW() << errorPrefix << " has incorrect number of input/output dimensions!"; - - if (padMode == REFLECT) { - for (size_t i = 0; i < srcDims.size(); i++) { - if ((srcDims[i] - 1) < padsBegin[i] || (srcDims[i] - 1) < padsEnd[i]) - IE_THROW() << errorPrefix << " has incorrect padsBegin or padsEnd for 'reflect' pad mode"; - } - } else if (padMode == SYMMETRIC) { - for (size_t i = 0; i < srcDims.size(); i++) { - if (srcDims[i] < padsBegin[i] || srcDims[i] < padsEnd[i]) - IE_THROW() << errorPrefix << " has incorrect padsBegin or padsEnd for 'symmetric' pad mode"; + const auto pad_mode = pad->get_pad_mode(); + isPadValueSpecified = pad->get_input_size() == 4; + if (pad_mode == ngraph::op::PadMode::CONSTANT) { + attrs.padMode = CONSTANT; + if (isPadValueSpecified && op->get_input_node_shared_ptr(PAD_VALUE_ID)->get_type_info() == ov::op::v0::Constant::get_type_info_static()) { + if (!ngraph::is_scalar(pad->get_input_shape(PAD_VALUE_ID))) + THROW_ERROR << "has non scalar 'pad_value' input"; + attrs.padValue = ov::as_type_ptr(pad->get_input_node_shared_ptr(PAD_VALUE_ID))->cast_vector()[0]; } + } else if (pad_mode == ngraph::op::PadMode::EDGE) { + attrs.padMode = EDGE; + } else if (pad_mode == ngraph::op::PadMode::REFLECT) { + attrs.padMode = REFLECT; + } else if (pad_mode == ngraph::op::PadMode::SYMMETRIC) { + attrs.padMode = SYMMETRIC; + } else { + THROW_ERROR << "has unsupported pad_mode: " + ngraph::as_string(pad_mode); } } +void MKLDNNPadNode::getSupportedDescriptors() {} + void MKLDNNPadNode::initSupportedPrimitiveDescriptors() { if (!supportedPrimitiveDescriptors.empty()) return; @@ -126,8 +126,8 @@ void MKLDNNPadNode::initSupportedPrimitiveDescriptors() { if (std::find(supportedPrecisions.begin(), supportedPrecisions.end(), precision) == supportedPrecisions.end()) precision = precision.is_float() ? InferenceEngine::Precision::FP32 : InferenceEngine::Precision::I32; - auto srcDims = getInputShapeAtPort(DATA_ID).getStaticDims(); - int numOfDims = srcDims.size(); + const auto& inputDataShape = getInputShapeAtPort(DATA_ID); + const size_t numOfDims = inputDataShape.getRank(); NodeConfig config; config.dynBatchSupport = false; @@ -151,15 +151,17 @@ void MKLDNNPadNode::initSupportedPrimitiveDescriptors() { pushSupportedPrimitiveDescriptor(LayoutType::ncsp); - auto canUseBlocked = [=](const size_t blockSize) { - return (padMode == CONSTANT && padsBegin[1] % blockSize == 0 && padsEnd[1] % blockSize == 0) || - (padMode != CONSTANT && padsBegin[1] == 0 && padsEnd[1] == 0); + auto canUseBlocked = [&](const size_t blockSize) { + const auto& srcDims = inputDataShape.getDims(); + return srcDims[1] != Shape::UNDEFINED_DIM && srcDims[1] % blockSize == 0 && + ((attrs.padMode == CONSTANT && attrs.padsBegin[1] % blockSize == 0 && attrs.padsEnd[1] % blockSize == 0) || + (attrs.padMode != CONSTANT && attrs.padsBegin[1] == 0 && attrs.padsEnd[1] == 0)); }; if (numOfDims == 4 || numOfDims == 5) { - if (srcDims[1] % 8 == 0 && canUseBlocked(8)) + if (canUseBlocked(8)) pushSupportedPrimitiveDescriptor(LayoutType::nCsp8c); - if (srcDims[1] % 16 == 0 && canUseBlocked(16)) + if (canUseBlocked(16)) pushSupportedPrimitiveDescriptor(LayoutType::nCsp16c); } } @@ -168,65 +170,90 @@ void MKLDNNPadNode::createPrimitive() { auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr(); auto& srcMemPtr = getParentEdgeAt(0)->getMemoryPtr(); if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr()) - IE_THROW() << "Destination memory for Pad " << getName() << " didn't allocate."; + THROW_ERROR << "has not allocated source memory."; if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) - IE_THROW() << "Input memory for Pad " << getName() << " didn't allocate."; + THROW_ERROR << "has not allocated destination memory."; if (getSelectedPrimitiveDescriptor() == nullptr) - IE_THROW() << "Preferable primitive descriptor for Pad " << getName() << " is not set."; - - params.sizeData = this->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc->getPrecision().size(); - - const auto inBlkDesc = getParentEdgeAt(0)->getMemory().GetDescWithType(); - params.srcDims = inBlkDesc->getBlockDims(); - params.dstDims = getChildEdgeAt(0)->getMemory().GetDescWithType()->getBlockDims(); - - size_t nDims = params.srcDims.size(); - params.srcStrides.resize(nDims, 1); - params.dstStrides.resize(nDims, 1); - for (int i = nDims - 2; i >= 0; i--) { - params.srcStrides[i] = params.srcStrides[i + 1] * params.srcDims[i + 1]; - params.dstStrides[i] = params.dstStrides[i + 1] * params.dstDims[i + 1]; - } - - if (getParentEdgeAt(0)->getMemory().getDesc().hasLayoutType(LayoutType::nCsp16c) || - getParentEdgeAt(0)->getMemory().getDesc().hasLayoutType(LayoutType::nCsp8c)) { - padsBegin[1] /= params.srcDims[params.srcDims.size() - 1]; - padsEnd[1] /= params.srcDims[params.srcDims.size() - 1]; - padsBegin.push_back(0); - padsEnd.push_back(0); + THROW_ERROR << "has unidentified preferable primitive descriptor"; + + // pads are constant, so we can calculate new collapsing pads for first target dimensions and use it for the next dimensions + // to avoid permanent identical pad calculations + const size_t blockSize = srcMemPtr->getDesc().hasLayoutType(LayoutType::nCsp16c) ? 16 : + (srcMemPtr->getDesc().hasLayoutType(LayoutType::nCsp8c) ? 8 : 1); + if (blockSize > 1) { + attrs.padsBegin[1] /= blockSize; + attrs.padsEnd[1] /= blockSize; + attrs.padsBegin.push_back(0); + attrs.padsEnd.push_back(0); } else { - auto order = inBlkDesc->getOrder(); - std::vector newPadsBegin(padsBegin.size(), 0), newPadsEnd(padsEnd.size(), 0); - for (size_t i = 0; i < padsBegin.size(); ++i) { - newPadsBegin[i] = padsBegin[order[i]]; - newPadsEnd[i] = padsEnd[order[i]]; + auto order = getParentEdgeAt(0)->getMemory().GetDescWithType()->getOrder(); + std::vector newPadsBegin(attrs.padsBegin.size(), 0), newPadsEnd(attrs.padsEnd.size(), 0); + for (size_t i = 0; i < attrs.padsBegin.size(); ++i) { + newPadsBegin[i] = attrs.padsBegin[order[i]]; + newPadsEnd[i] = attrs.padsEnd[order[i]]; } - padsBegin = newPadsBegin; - padsEnd = newPadsEnd; + attrs.padsBegin = newPadsBegin; + attrs.padsEnd = newPadsEnd; } - int beginIdx = 0; - int endIdx = padsBegin.size() - 1; + // collapse dimensions + attrs.beginPadIdx = 0; + attrs.endPadIdx = attrs.padsBegin.size() - 1; - for (int i = 0; i < padsBegin.size(); ++i) { - if (padsBegin[i] != 0 || padsEnd[i] != 0) { - beginIdx = i - 1; + for (int i = 0; i < attrs.padsBegin.size(); ++i) { + if (attrs.padsBegin[i] != 0 || attrs.padsEnd[i] != 0) { + attrs.beginPadIdx = i - 1; break; } } - for (int i = padsBegin.size() - 1; i >= 0; --i) { - if (padsBegin[i] != 0 || padsEnd[i] != 0) { - endIdx = i; + for (int i = attrs.padsBegin.size() - 1; i >= 0; --i) { + if (attrs.padsBegin[i] != 0 || attrs.padsEnd[i] != 0) { + attrs.endPadIdx = i; break; } } - params.lastDstDim = params.dstStrides[std::max(endIdx - 1, 0)]; - params.nDimsForWork = endIdx - std::max(beginIdx, 0); + if (attrs.beginPadIdx > 0) { + attrs.padsBegin.erase(attrs.padsBegin.begin() + 1, attrs.padsBegin.begin() + attrs.beginPadIdx + 1); + attrs.padsEnd.erase(attrs.padsEnd.begin() + 1, attrs.padsEnd.begin() + attrs.beginPadIdx + 1); + } + + attrs.prc = srcMemPtr->getDesc().getPrecision(); + + if (inputShapesDefined()) { + prepareParams(); + updateLastInputDims(); + } +} + +void MKLDNNPadNode::prepareParams() { + execPtr = std::make_shared(attrs, + getParentEdgeAt(0)->getMemoryPtr()->GetDescWithType()->getBlockDims(), + getChildEdgeAt(0)->getMemoryPtr()->GetDescWithType()->getBlockDims()); +} + +MKLDNNPadNode::PadExecutor::PadExecutor(const PadAttrs& attrs, + const VectorDims& srcDims, + const VectorDims& dstDims) { + params.attrs = attrs; + params.srcDims = srcDims; + params.dstDims = dstDims; + params.dataSize = attrs.prc.size(); + + size_t nDims = params.srcDims.size(); + params.srcStrides.resize(nDims, 1); + params.dstStrides.resize(nDims, 1); + for (int i = nDims - 2; i >= 0; i--) { + params.srcStrides[i] = params.srcStrides[i + 1] * params.srcDims[i + 1]; + params.dstStrides[i] = params.dstStrides[i + 1] * params.dstDims[i + 1]; + } + + params.lastDstDim = params.dstStrides[std::max(params.attrs.endPadIdx - 1, 0)]; + params.nDimsForWork = params.attrs.endPadIdx - std::max(params.attrs.beginPadIdx, 0); params.nThreads = params.nDimsForWork > 0 ? 0 : 1; params.workAmount = params.nDimsForWork > 0 ? params.dstDims[0] : 1lu; - for (int i = 1; i <= beginIdx; ++i) { + for (int i = 1; i <= params.attrs.beginPadIdx; ++i) { params.workAmount *= params.dstDims[i]; params.dstDims[0] *= params.dstDims[i]; params.srcDims[0] *= params.srcDims[i]; @@ -234,51 +261,62 @@ void MKLDNNPadNode::createPrimitive() { params.srcStrides[0] /= params.srcDims[i]; } - if (beginIdx > 0) { - beginIdx++; - params.dstDims.erase(params.dstDims.begin() + 1, params.dstDims.begin() + beginIdx); - params.srcDims.erase(params.srcDims.begin() + 1, params.srcDims.begin() + beginIdx); - params.dstStrides.erase(params.dstStrides.begin() + 1, params.dstStrides.begin() + beginIdx); - params.srcStrides.erase(params.srcStrides.begin() + 1, params.srcStrides.begin() + beginIdx); - padsBegin.erase(padsBegin.begin() + 1, padsBegin.begin() + beginIdx); - padsEnd.erase(padsEnd.begin() + 1, padsEnd.begin() + beginIdx); + if (params.attrs.beginPadIdx > 0) { + params.attrs.beginPadIdx++; + params.dstDims.erase(params.dstDims.begin() + 1, params.dstDims.begin() + params.attrs.beginPadIdx); + params.srcDims.erase(params.srcDims.begin() + 1, params.srcDims.begin() + params.attrs.beginPadIdx); + params.dstStrides.erase(params.dstStrides.begin() + 1, params.dstStrides.begin() + params.attrs.beginPadIdx); + params.srcStrides.erase(params.srcStrides.begin() + 1, params.srcStrides.begin() + params.attrs.beginPadIdx); } params.workAmount = params.workAmount * params.dstStrides[0] / params.lastDstDim; params.shift = params.dstStrides[params.nDimsForWork]; - if (padMode != CONSTANT || (padMode == CONSTANT && padValue == 0)) { - params.lastDstDim *= params.sizeData; - params.shift *= params.sizeData; + if (params.attrs.padMode != CONSTANT || (params.attrs.padMode == CONSTANT && params.attrs.padValue == 0)) { + params.lastDstDim *= params.dataSize; + params.shift *= params.dataSize; } + params.srcODims.clear(); for (size_t i = 0; i < params.srcDims.size(); ++i) - params.srcODims.push_back(padsBegin[i] + params.srcDims[i]); + params.srcODims.push_back(params.attrs.padsBegin[i] + params.srcDims[i]); - if (padMode == REFLECT || padMode == SYMMETRIC) { - int shift = padMode == SYMMETRIC ? 1 : 0; + params.srcDimsForReflectOrSymmetric.clear(); + if (params.attrs.padMode == REFLECT || params.attrs.padMode == SYMMETRIC) { + int shift = params.attrs.padMode == SYMMETRIC ? 1 : 0; for (size_t i = 0; i < params.srcDims.size(); ++i) params.srcDimsForReflectOrSymmetric.push_back(params.srcDims[i] + params.srcODims[i] - 2 + shift); } } -void MKLDNNPadNode::execute(mkldnn::stream strm) { - switch (padMode) { +void MKLDNNPadNode::PadExecutor::exec(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr) { + switch (params.attrs.padMode) { case CONSTANT: - padConstant(); + padConstant(srcMemPtr, dstMemPtr); break; case EDGE: - padEdge(); + padEdge(srcMemPtr, dstMemPtr); break; case REFLECT: - padReflectOrSymmetric(); + padReflectOrSymmetric(srcMemPtr, dstMemPtr); break; case SYMMETRIC: - padReflectOrSymmetric(true); + padReflectOrSymmetric(srcMemPtr, dstMemPtr, true); break; } } -static inline size_t parallel_init(size_t start, size_t nDims, const SizeVector& dims, SizeVector& indexes) { +void MKLDNNPadNode::execute(mkldnn::stream strm) { + if (!execPtr) + THROW_ERROR << "has not compiled executor."; + + execPtr->exec(getParentEdgeAt(0)->getMemoryPtr(), getChildEdgeAt(0)->getMemoryPtr()); +} + +void MKLDNNPadNode::executeDynamicImpl(mkldnn::stream strm) { + execute(strm); +} + +static inline size_t parallel_init(size_t start, size_t nDims, const VectorDims& dims, VectorDims& indexes) { for (int j = nDims - 1; j >= 0; j--) { indexes[j] = start % dims[j]; start = start / dims[j]; @@ -286,7 +324,7 @@ static inline size_t parallel_init(size_t start, size_t nDims, const SizeVector& return start; } -static inline void parallel_step(size_t nDims, const SizeVector& dims, SizeVector& indexes) { +static inline void parallel_step(size_t nDims, const VectorDims& dims, VectorDims& indexes) { for (int j = nDims - 1; j >= 0; --j) { ++indexes[j]; if (indexes[j] < dims[j]) @@ -296,17 +334,14 @@ static inline void parallel_step(size_t nDims, const SizeVector& dims, SizeVecto } } -void MKLDNNPadNode::padConstant() { - if (padValue == 0) { - padConstantZero(); +void MKLDNNPadNode::PadExecutor::padConstant(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr) { + if (params.attrs.padValue == 0) { + padConstantZero(srcMemPtr, dstMemPtr); return; } - auto selectedPrimitiveDescriptor = getSelectedPrimitiveDescriptor(); - if (!selectedPrimitiveDescriptor) - IE_THROW() << "CPU Pad node with name '" << getName() << "' doesn't have primitive descriptors."; - InferenceEngine::Precision precision = selectedPrimitiveDescriptor->getConfig().inConfs[0].desc->getPrecision(); - OV_SWITCH(MKLDNNPlugin, PadConstantEmitter, this, precision, + PadContext ctx { this, srcMemPtr, dstMemPtr }; + OV_SWITCH(MKLDNNPlugin, PadConstantEmitter, ctx, params.attrs.prc, OV_CASE(InferenceEngine::Precision::FP32, float), OV_CASE(InferenceEngine::Precision::I32, int32_t), OV_CASE(InferenceEngine::Precision::BF16, bfloat16_t), @@ -315,18 +350,18 @@ void MKLDNNPadNode::padConstant() { } template -void MKLDNNPadNode::padConstantCommon() { - const T* srcData = reinterpret_cast(this->getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); - T* dstData = reinterpret_cast(this->getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); - const T value = static_cast(padValue); +void MKLDNNPadNode::PadExecutor::padConstantCommon(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr) { + const T* srcData = reinterpret_cast(srcMemPtr->GetPtr()); + T* dstData = reinterpret_cast(dstMemPtr->GetPtr()); + const T value = static_cast(params.attrs.padValue); - const size_t beginShift = padsBegin[params.nDimsForWork] * params.shift; + const size_t beginShift = params.attrs.padsBegin[params.nDimsForWork] * params.shift; const size_t copySize = params.srcDims[params.nDimsForWork] * params.shift; - const size_t endShift = padsEnd[params.nDimsForWork] * params.shift; + const size_t endShift = params.attrs.padsEnd[params.nDimsForWork] * params.shift; parallel_nt(params.nThreads, [&](const int ithr, const int nthr) { size_t start = 0, end = 0; - SizeVector indexes(params.nDimsForWork, 0); + VectorDims indexes(params.nDimsForWork, 0); splitter(params.workAmount, nthr, ithr, start, end); parallel_init(start, params.nDimsForWork, params.dstDims, indexes); @@ -336,7 +371,7 @@ void MKLDNNPadNode::padConstantCommon() { for (size_t iwork = start; iwork < end; ++iwork, dstIdx += params.lastDstDim) { size_t j = 0; for (; j < params.nDimsForWork; ++j) { - if (indexes[j] < padsBegin[j] || indexes[j] >= params.srcODims[j]) + if (indexes[j] < params.attrs.padsBegin[j] || indexes[j] >= params.srcODims[j]) break; } @@ -348,10 +383,10 @@ void MKLDNNPadNode::padConstantCommon() { size_t srcIdx = 0; for (size_t idx = 0; idx < params.nDimsForWork; ++idx) - srcIdx += (indexes[idx] - padsBegin[idx]) * params.srcStrides[idx]; + srcIdx += (indexes[idx] - params.attrs.padsBegin[idx]) * params.srcStrides[idx]; std::fill_n(&dstData[dstIdx], beginShift, value); - cpu_memcpy(&dstData[dstIdx + beginShift], &srcData[srcIdx], copySize * params.sizeData); + cpu_memcpy(&dstData[dstIdx + beginShift], &srcData[srcIdx], copySize * params.dataSize); std::fill_n(&dstData[dstIdx + beginShift + copySize], endShift, value); parallel_step(params.nDimsForWork, params.dstDims, indexes); @@ -359,27 +394,28 @@ void MKLDNNPadNode::padConstantCommon() { }); } -void MKLDNNPadNode::padConstantZero() { - const uint8_t* srcData = reinterpret_cast(this->getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); - uint8_t* dstData = reinterpret_cast(this->getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); +void MKLDNNPadNode::PadExecutor::padConstantZero(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr) { + const uint8_t* srcData = reinterpret_cast(srcMemPtr->GetPtr()); + uint8_t* dstData = reinterpret_cast(dstMemPtr->GetPtr()); - const size_t beginShift = padsBegin[params.nDimsForWork] * params.shift; + const size_t beginShift = params.attrs.padsBegin[params.nDimsForWork] * params.shift; const size_t copySize = params.srcDims[params.nDimsForWork] * params.shift; - const size_t endShift = padsEnd[params.nDimsForWork] * params.shift; + const size_t endShift = params.attrs.padsEnd[params.nDimsForWork] * params.shift; parallel_nt(params.nThreads, [&](const int ithr, const int nthr) { size_t start = 0, end = 0; - SizeVector indexes(params.nDimsForWork, 0); + VectorDims indexes(params.nDimsForWork, 0); splitter(params.workAmount, nthr, ithr, start, end); parallel_init(start, params.nDimsForWork, params.dstDims, indexes); size_t dstIdx = 0; getDstIdx(indexes, dstIdx); + dstIdx *= params.dataSize; for (size_t iwork = start; iwork < end; ++iwork, dstIdx += params.lastDstDim) { size_t j = 0; for (; j < params.nDimsForWork; ++j) { - if (indexes[j] < padsBegin[j] || indexes[j] >= params.srcODims[j]) + if (indexes[j] < params.attrs.padsBegin[j] || indexes[j] >= params.srcODims[j]) break; } @@ -391,8 +427,8 @@ void MKLDNNPadNode::padConstantZero() { size_t srcIdx = 0; for (size_t idx = 0; idx < params.nDimsForWork; ++idx) - srcIdx += (indexes[idx] - padsBegin[idx]) * params.srcStrides[idx]; - srcIdx *= params.sizeData; + srcIdx += (indexes[idx] - params.attrs.padsBegin[idx]) * params.srcStrides[idx]; + srcIdx *= params.dataSize; memset(&dstData[dstIdx], 0, beginShift); cpu_memcpy(&dstData[dstIdx + beginShift], &srcData[srcIdx], copySize); @@ -403,37 +439,38 @@ void MKLDNNPadNode::padConstantZero() { }); } -void MKLDNNPadNode::padEdge() { - const uint8_t* srcData = reinterpret_cast(this->getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); - uint8_t* dstData = reinterpret_cast(this->getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); +void MKLDNNPadNode::PadExecutor::padEdge(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr) { + const uint8_t* srcData = reinterpret_cast(srcMemPtr->GetPtr()); + uint8_t* dstData = reinterpret_cast(dstMemPtr->GetPtr()); - const size_t beginShift = padsBegin[params.nDimsForWork] * params.shift; + const size_t beginShift = params.attrs.padsBegin[params.nDimsForWork] * params.shift; const size_t copySize = params.srcDims[params.nDimsForWork] * params.shift; parallel_nt(params.nThreads, [&](const int ithr, const int nthr) { size_t start = 0, end = 0; - SizeVector indexes(params.nDimsForWork, 0); + VectorDims indexes(params.nDimsForWork, 0); splitter(params.workAmount, nthr, ithr, start, end); parallel_init(start, params.nDimsForWork, params.dstDims, indexes); size_t dstIdx = 0; getDstIdx(indexes, dstIdx); + dstIdx *= params.dataSize; for (size_t iwork = start; iwork < end; ++iwork, dstIdx += params.lastDstDim) { size_t srcIdx = 0; for (size_t idx = 0; idx < params.nDimsForWork; ++idx) { - size_t shift = (indexes[idx] < padsBegin[idx]) ? 0 : - ((indexes[idx] >= params.srcODims[idx]) ? (params.srcDims[idx] - 1) : (indexes[idx] - padsBegin[idx])); + size_t shift = (indexes[idx] < params.attrs.padsBegin[idx]) ? 0 : + ((indexes[idx] >= params.srcODims[idx]) ? (params.srcDims[idx] - 1) : (indexes[idx] - params.attrs.padsBegin[idx])); srcIdx += shift * params.srcStrides[idx]; } - srcIdx *= params.sizeData; + srcIdx *= params.dataSize; - for (size_t i = 0; i < padsBegin[params.nDimsForWork]; ++i) + for (size_t i = 0; i < params.attrs.padsBegin[params.nDimsForWork]; ++i) cpu_memcpy(&dstData[dstIdx + i * params.shift], &srcData[srcIdx], params.shift); cpu_memcpy(&dstData[dstIdx + beginShift], &srcData[srcIdx], copySize); - for (size_t i = 0; i < padsEnd[params.nDimsForWork]; ++i) + for (size_t i = 0; i < params.attrs.padsEnd[params.nDimsForWork]; ++i) cpu_memcpy(&dstData[dstIdx + beginShift + copySize + i * params.shift], &srcData[srcIdx + (params.srcDims[params.nDimsForWork] - 1) * params.shift], params.shift); @@ -442,38 +479,40 @@ void MKLDNNPadNode::padEdge() { }); } -void MKLDNNPadNode::padReflectOrSymmetric(const bool isSymmetric) { - const uint8_t* srcData = reinterpret_cast(this->getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); - uint8_t* dstData = reinterpret_cast(this->getChildEdgeAt(0)->getMemoryPtr()->GetPtr()); +void MKLDNNPadNode::PadExecutor::padReflectOrSymmetric(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr, const bool isSymmetric) { + const uint8_t* srcData = reinterpret_cast(srcMemPtr->GetPtr()); + uint8_t* dstData = reinterpret_cast(dstMemPtr->GetPtr()); size_t shift = isSymmetric ? 1 : 0; parallel_nt(params.nThreads, [&](const int ithr, const int nthr) { size_t start = 0, end = 0; - SizeVector indexes(params.nDimsForWork, 0); + VectorDims indexes(params.nDimsForWork, 0); splitter(params.workAmount, nthr, ithr, start, end); parallel_init(start, params.nDimsForWork, params.dstDims, indexes); size_t dstIdx = 0; getDstIdx(indexes, dstIdx); + dstIdx *= params.dataSize; for (size_t iwork = start; iwork < end; ++iwork, dstIdx += params.lastDstDim) { size_t srcIdx = 0; for (size_t i = 0; i < params.nDimsForWork; ++i) { - size_t idx = (indexes[i] < padsBegin[i]) ? (padsBegin[i] - indexes[i] - shift) : - ((indexes[i] >= params.srcODims[i]) ? (params.srcDimsForReflectOrSymmetric[i] - indexes[i]) : (indexes[i] - padsBegin[i])); + size_t idx = (indexes[i] < params.attrs.padsBegin[i]) ? (params.attrs.padsBegin[i] - indexes[i] - shift) : + ((indexes[i] >= params.srcODims[i]) ? (params.srcDimsForReflectOrSymmetric[i] - indexes[i]) : + (indexes[i] - params.attrs.padsBegin[i])); srcIdx += idx * params.srcStrides[i]; } - srcIdx *= params.sizeData; + srcIdx *= params.dataSize; - for (size_t i = 0; i < padsBegin[params.nDimsForWork]; ++i) + for (size_t i = 0; i < params.attrs.padsBegin[params.nDimsForWork]; ++i) cpu_memcpy(&dstData[dstIdx + i * params.shift], - &srcData[srcIdx + (padsBegin[params.nDimsForWork] - shift - i) * params.shift], params.shift); + &srcData[srcIdx + (params.attrs.padsBegin[params.nDimsForWork] - shift - i) * params.shift], params.shift); - cpu_memcpy(&dstData[dstIdx + padsBegin[params.nDimsForWork] * params.shift], &srcData[srcIdx], + cpu_memcpy(&dstData[dstIdx + params.attrs.padsBegin[params.nDimsForWork] * params.shift], &srcData[srcIdx], params.srcDims[params.nDimsForWork] * params.shift); size_t srcShift = (params.srcDimsForReflectOrSymmetric[params.nDimsForWork] - params.srcODims[params.nDimsForWork]) * params.shift; - for (size_t i = 0; i < padsEnd[params.nDimsForWork]; ++i) + for (size_t i = 0; i < params.attrs.padsEnd[params.nDimsForWork]; ++i) cpu_memcpy(&dstData[dstIdx + (params.srcODims[params.nDimsForWork] + i) * params.shift], &srcData[srcIdx + srcShift - i * params.shift], params.shift); @@ -482,10 +521,9 @@ void MKLDNNPadNode::padReflectOrSymmetric(const bool isSymmetric) { }); } -inline void MKLDNNPadNode::getDstIdx(const InferenceEngine::SizeVector& indexes, size_t& dstIdx) const { +inline void MKLDNNPadNode::PadExecutor::getDstIdx(const VectorDims& indexes, size_t& dstIdx) const { for (size_t i = 0; i < params.nDimsForWork; ++i) dstIdx += indexes[i] * params.dstStrides[i]; - dstIdx *= (padMode == CONSTANT && padValue != 0) ? 1 : params.sizeData; } bool MKLDNNPadNode::created() const { diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h index 68af48dac0ba50..74189292fd80c4 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pad_node.h @@ -14,13 +14,17 @@ class MKLDNNPadNode : public MKLDNNNode { public: MKLDNNPadNode(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache); + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; void initSupportedPrimitiveDescriptors() override; void createPrimitive() override; void execute(mkldnn::stream strm) override; bool created() const override; - static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; + void prepareParams() override; + +protected: + void executeDynamicImpl(mkldnn::stream strm) override; private: enum PadMode { @@ -30,48 +34,70 @@ class MKLDNNPadNode : public MKLDNNNode { SYMMETRIC = 3 }; - void padConstant(); - template void padConstantCommon(); - void padConstantZero(); - void padEdge(); - void padReflectOrSymmetric(const bool isSymmetric = false); - - inline void getDstIdx(const InferenceEngine::SizeVector& indexes, size_t& dstIdx) const; - - PadMode padMode = CONSTANT; - float padValue = 0.f; - std::vector padsBegin; - std::vector padsEnd; - - struct { - InferenceEngine::SizeVector srcDims; - InferenceEngine::SizeVector dstDims; - InferenceEngine::SizeVector srcODims; - InferenceEngine::SizeVector srcStrides; - InferenceEngine::SizeVector dstStrides; - InferenceEngine::SizeVector srcDimsForReflectOrSymmetric; - int nThreads = 0; - size_t nDimsForWork = 0lu; - size_t workAmount = 0lu; - size_t lastDstDim = 1lu; - size_t shift = 0lu; - uint8_t sizeData = 1; - } params; - - template - struct PadConstantEmitter { - void operator()(MKLDNNPadNode* node) { - node->padConstantCommon(); - } + struct PadAttrs { + PadMode padMode = CONSTANT; + float padValue = 0.f; + std::vector padsBegin; + std::vector padsEnd; + int beginPadIdx = 0; + int endPadIdx = 0; + InferenceEngine::Precision prc; + } attrs; + + struct PadExecutor { + PadExecutor(const PadAttrs& params, const VectorDims& srcDims, const VectorDims& dstDims); + void exec(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr); + ~PadExecutor() = default; + + private: + void padConstant(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr); + template void padConstantCommon(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr); + void padConstantZero(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr); + void padEdge(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr); + void padReflectOrSymmetric(MKLDNNMemoryPtr& srcMemPtr, MKLDNNMemoryPtr& dstMemPtr, const bool isSymmetric = false); + + inline void getDstIdx(const VectorDims& indexes, size_t& dstIdx) const; + + struct PadContext { + PadExecutor* executor; + MKLDNNMemoryPtr srcMemPtr; + MKLDNNMemoryPtr dstMemPtr; + }; + + template + struct PadConstantEmitter { + void operator()(PadContext& ctx) { + ctx.executor->padConstantCommon(ctx.srcMemPtr, ctx.dstMemPtr); + } + }; + + struct { + PadAttrs attrs; + VectorDims srcDims; + VectorDims dstDims; + VectorDims srcODims; + VectorDims srcStrides; + VectorDims dstStrides; + VectorDims srcDimsForReflectOrSymmetric; + int nThreads = 0; + size_t nDimsForWork = 0lu; + size_t workAmount = 0lu; + size_t lastDstDim = 1lu; + size_t shift = 0lu; + size_t dataSize = 1lu; + PadMode padMode; + } params; }; - std::string errorPrefix; - static const size_t DATA_ID = 0; - static const size_t PADS_BEGIN_ID = 1; - static const size_t PADS_END_ID = 2; - static const size_t PAD_VALUE_ID = 3; + static constexpr size_t DATA_ID = 0lu; + static constexpr size_t PADS_BEGIN_ID = 1lu; + static constexpr size_t PADS_END_ID = 2lu; + static constexpr size_t PAD_VALUE_ID = 3lu; bool isPadValueSpecified = false; + + using executorPtr = std::shared_ptr; + executorPtr execPtr = nullptr; }; } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.cpp index 72f26b5b0b4933..941c043d140d11 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.cpp @@ -22,10 +22,6 @@ using namespace InferenceEngine; bool MKLDNNPoolingNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } if (!ngraph::as_type_ptr(op) && !ngraph::as_type_ptr(op)) { errorMessage = "Only opset1 MaxPool and AvgPool operations are supported"; return false; @@ -61,6 +57,7 @@ MKLDNNPoolingNode::MKLDNNPoolingNode(const std::shared_ptr& op, co for (int i = 0; i < maxPoolOp->get_pads_end().size(); i++) { data_pad_end.push_back(static_cast(maxPoolOp->get_pads_end()[i])); } + auto_pad = (maxPoolOp->get_auto_pad() == ov::op::PadType::SAME_LOWER || maxPoolOp->get_auto_pad() == ov::op::PadType::SAME_UPPER); } else if (avgPoolOp) { algorithm = PoolingAvg; exclude_pad = avgPoolOp->get_exclude_pad(); @@ -77,6 +74,7 @@ MKLDNNPoolingNode::MKLDNNPoolingNode(const std::shared_ptr& op, co for (int i = 0; i < avgPoolOp->get_pads_end().size(); i++) { data_pad_end.push_back(static_cast(avgPoolOp->get_pads_end()[i])); } + auto_pad = (avgPoolOp->get_auto_pad() == ov::op::PadType::SAME_LOWER || avgPoolOp->get_auto_pad() == ov::op::PadType::SAME_UPPER); } } @@ -96,6 +94,23 @@ std::vector MKLDNNPoolingNode::getAvailableFormatsForDims(co return {memory::format_tag::any}; } +void MKLDNNPoolingNode::initEffectivePad(const Shape &inShape, const Shape &outShape) { + effective_pad_begin = data_pad_begin; + effective_pad_end.resize(data_pad_end.size()); + + const auto &inDims = inShape.getStaticDims(); + const auto &outDims = outShape.getStaticDims(); + + for (int i = 0; i < effective_pad_end.size(); i++) { + int krn = kernel[i]; + int src = inDims[2 + i]; + int dst = outDims[2 + i]; + + int calc_dst = (src - krn + data_pad_begin[i]) / stride[i] + 1; + effective_pad_end[i] = (dst - calc_dst) * stride[i]; + } +} + void MKLDNNPoolingNode::getSupportedDescriptors() { if (!descs.empty()) return; @@ -129,24 +144,16 @@ void MKLDNNPoolingNode::getSupportedDescriptors() { auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(inputPrecision); auto outputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(outputPrecision); - effective_pad_begin = data_pad_begin; - effective_pad_end.resize(data_pad_end.size()); - - auto parentShape = getInputShapeAtPort(0); - auto childShape = getOutputShapeAtPort(0); + const auto &parentShape = getInputShapeAtPort(0); + const auto &childShape = getOutputShapeAtPort(0); const size_t inputRank = getInputShapeAtPort(0).getRank(); if ((inputRank < 4) || (inputRank > 5)) IE_THROW() << "Pooling layer. Unsupported mode. Only 4D and 5D blobs are supported as input."; - for (int i = 0; i < effective_pad_end.size(); i++) { - int krn = kernel[i]; - int src = getInputShapeAtPort(0).getStaticDims()[2 + i]; - int dst = getOutputShapeAtPort(0).getStaticDims()[2 + i]; + initEffectivePad(MemoryDescUtils::makeDummyShape(parentShape), + MemoryDescUtils::makeDummyShape(childShape)); - int calc_dst = (src - krn + data_pad_begin[i]) / stride[i] + 1; - effective_pad_end[i] = (dst - calc_dst) * stride[i]; - } if (inputPrecision == Precision::I8 || inputPrecision == Precision::U8) { // We have to extend i8i8_pooling_fwd_t from oneDNN to support BF16 output data type if (outputDataType == memory::data_type::bf16) @@ -157,7 +164,7 @@ void MKLDNNPoolingNode::getSupportedDescriptors() { const auto out_candidate = std::make_shared(childShape, outputDataType, inputRank == 5 ? memory::format_tag::ndhwc : memory::format_tag::nhwc); createDescriptor({ in_candidate }, { out_candidate }); - } else if ((inputRank == 4 || inputRank == 5) && parentShape.getStaticDims()[1] == 1) { + } else if ((inputRank == 4 || inputRank == 5) && parentShape.getDims()[1] == 1) { // WA. We should force planar layout since it provides better performance const auto in_candidate = std::make_shared(parentShape, inputDataType, inputRank == 5 ? memory::format_tag::ncdhw : memory::format_tag::nchw); @@ -178,14 +185,70 @@ void MKLDNNPoolingNode::getSupportedDescriptors() { } } -void MKLDNNPoolingNode::createPrimitive() { - if (prim) - return; +std::pair, std::vector> MKLDNNPoolingNode::getPaddingFromNode(std::shared_ptr node) const { + const auto convertPadding = [](const VectorDims &newPads) { + std::vector pads(newPads.size()); + for (int i = 0; i < newPads.size(); i++) { + pads[i] = static_cast(newPads[i]); + } + return pads; + }; - mkldnn::primitive_attr attr; - setPostOps(attr, true); + VectorDims padsBegin, padsEnd; + if (getAlgorithm() == PoolingMax) { + const auto pool = ngraph::as_type_ptr(opToShapeInfer); + padsBegin = pool->get_pads_begin(); + padsEnd = pool->get_pads_end(); + } else if (getAlgorithm() == PoolingAvg) { + const auto pool = ngraph::as_type_ptr(opToShapeInfer); + padsBegin = pool->get_pads_begin(); + padsEnd = pool->get_pads_end(); + } + return {convertPadding(padsBegin), convertPadding(padsEnd)}; +} + +void MKLDNNPoolingNode::prepareParams() { + const NodeDesc *selected_pd = getSelectedPrimitiveDescriptor(); + if (selected_pd == nullptr) + IE_THROW() << "Pooling node with name '" << getName() << "' did not set preferable primitive descriptor"; + + AttrPtr attr; + if (isDynamicNode()) { + if (!pAttr) { + pAttr = initPrimitiveAttr(); + } + attr = pAttr; + } else { + attr = initPrimitiveAttr(); + } + + auto inDesc = getParentEdgesAtPort(0)[0]->getMemory().GetDescWithType(); + const auto& in_candidate = inDesc->getDnnlDesc(); + auto outDesc = getChildEdgesAtPort(0)[0]->getMemory().GetDescWithType(); + const auto& out_candidate = outDesc->getDnnlDesc(); - auto prim_desc = createPrimitiveDescriptor(attr); + if (isDynamicNode()) { + if (auto_pad) { + std::tie(data_pad_begin, data_pad_end) = getPaddingFromNode(opToShapeInfer); + } + initEffectivePad(inDesc->getShape(), outDesc->getShape()); + } + + mkldnn::algorithm alg = getPoolingAlgorithm(); + MKLDNNDescriptor desc{createDescriptorInternal(in_candidate, out_candidate, alg)}; + pooling_forward::primitive_desc prim_desc; + primitive_desc_iterator itpd = desc.createPrimitiveDescriptorIterator(getEngine(), *attr); + + while (static_cast(itpd)) { + impl_desc_type impl_type = parse_impl_name(itpd.impl_info_str()); + + if (impl_type == selected_pd->getImplementationType()) { + prim_desc = itpd.get(); + break; + } + if (!itpd.next_impl()) + IE_THROW() << "Primitive descriptor was not found for node " << getName() << "."; + } prim.reset(new pooling_forward(prim_desc)); @@ -194,16 +257,19 @@ void MKLDNNPoolingNode::createPrimitive() { primArgs = {{DNNL_ARG_SRC, src}, {DNNL_ARG_DST, dst}}; } +void MKLDNNPoolingNode::createPrimitive() { + if (inputShapesDefined()) { + if (needPrepareParams()) + prepareParams(); + updateLastInputDims(); + } +} + bool MKLDNNPoolingNode::created() const { return getType() == Pooling; } -void MKLDNNPoolingNode::createDescriptor(const std::vector &inputDesc, - const std::vector &outputDesc) { - auto in_candidate = MemoryDescUtils::convertToDnnlMemoryDesc(inputDesc[0])->getDnnlDesc(); - auto out_candidate = MemoryDescUtils::convertToDnnlMemoryDesc(outputDesc[0])->getDnnlDesc(); - - mkldnn::algorithm alg; +mkldnn::algorithm MKLDNNPoolingNode::getPoolingAlgorithm() const { if (algorithm == PoolingAvg) { bool not_zero_l = false; for (auto lr : data_pad_begin) { @@ -220,12 +286,20 @@ void MKLDNNPoolingNode::createDescriptor(const std::vector &input } } if (!exclude_pad && (not_zero_l || not_zero_r)) - alg = mkldnn::algorithm::pooling_avg_include_padding; + return mkldnn::algorithm::pooling_avg_include_padding; else - alg = mkldnn::algorithm::pooling_avg_exclude_padding; + return mkldnn::algorithm::pooling_avg_exclude_padding; } else if (algorithm == PoolingMax) { - alg = mkldnn::algorithm::pooling_max; + return mkldnn::algorithm::pooling_max; } else { + return mkldnn::algorithm::undef; + } +} + +std::shared_ptr MKLDNNPoolingNode::createDescriptorInternal(const mkldnn::memory::desc& in_candidate, + const mkldnn::memory::desc& out_candidate, + const mkldnn::algorithm alg) const { + if (alg == mkldnn::algorithm::undef) { IE_THROW() << "Unsupported pooling type"; } @@ -253,6 +327,30 @@ void MKLDNNPoolingNode::createDescriptor(const std::vector &input } } + return desc_ptr; +} + +void MKLDNNPoolingNode::createDescriptor(const std::vector &inputDesc, + const std::vector &outputDesc) { + auto inDesc = inputDesc[0]->isDefined() ? inputDesc[0] : MemoryDescUtils::makeDummyDesc(*inputDesc[0]); + auto dnnlInDesc = MemoryDescUtils::convertToDnnlMemoryDesc(inDesc); + auto in_candidate = dnnlInDesc->getDnnlDesc(); + + auto outDesc = outputDesc[0]; + if (!outDesc->isDefined()) { + auto outDims = shapeInferGeneric({Shape(inDesc->getShape().getStaticDims())}); + outDesc = outDesc->cloneWithNewDims(outDims[0]); + if (auto_pad) { + std::tie(data_pad_begin, data_pad_end) = getPaddingFromNode(opToShapeInfer); + } + initEffectivePad(inDesc->getShape(), outDesc->getShape()); + } + auto dnnlOutDesc = MemoryDescUtils::convertToDnnlBlockedMemoryDesc(*outDesc); + auto out_candidate = dnnlOutDesc.getDnnlDesc(); + + mkldnn::algorithm alg = getPoolingAlgorithm(); + auto desc_ptr = createDescriptorInternal(in_candidate, out_candidate, alg); + descs.emplace_back(desc_ptr); } @@ -272,12 +370,8 @@ void MKLDNNPoolingNode::initSupportedPrimitiveDescriptors() { PortConfig dataConfig; dataConfig.inPlace = -1; dataConfig.constant = false; - auto desc = getSrcMemDesc(itpd, i); - if (desc->getType() & MemoryDescType::Blocked) { - dataConfig.desc = desc->as()->cloneWithUndefStridesAndOffset(); - } else { - dataConfig.desc = std::move(desc); - } + dataConfig.desc = getSrcMemDesc(itpd, i); + config.inConfs.push_back(dataConfig); } @@ -285,12 +379,8 @@ void MKLDNNPoolingNode::initSupportedPrimitiveDescriptors() { PortConfig dataConfig; dataConfig.inPlace = canBeInPlace() ? 0 : -1; dataConfig.constant = false; - auto desc = getDstMemDesc(itpd, i); - if (desc->getType() & MemoryDescType::Blocked) { - dataConfig.desc = desc->as()->cloneWithUndefStridesAndOffset(); - } else { - dataConfig.desc = std::move(desc); - } + dataConfig.desc = getDstMemDesc(itpd, i); + config.outConfs.push_back(dataConfig); } impl_desc_type impl_type = parse_impl_name(itpd.impl_info_str()); @@ -382,7 +472,15 @@ void MKLDNNPoolingNode::initDescriptor(const NodeConfig& config) { selectedPD->setConfig(rightConfig); } -void MKLDNNPoolingNode::setPostOps(mkldnn::primitive_attr &attr, bool initWeights) { +MKLDNNNode::AttrPtr MKLDNNPoolingNode::initPrimitiveAttr() const { + auto attr = std::make_shared(mkldnn::primitive_attr()); + + setPostOps(*attr, true); + + return attr; +} + +void MKLDNNPoolingNode::setPostOps(mkldnn::primitive_attr &attr, bool initWeights) const { mkldnn::post_ops ops; for (auto &node : fusedWith) { diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h index d131bed7857cad..104b6f65e0bbe7 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_pooling_node.h @@ -28,11 +28,27 @@ class MKLDNNPoolingNode : public MKLDNNNode { return false; } + void prepareParams() override;; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); } + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; +protected: + AttrPtr initPrimitiveAttr() const override; + private: - void setPostOps(mkldnn::primitive_attr &attr, bool initWeights = false); + void setPostOps(mkldnn::primitive_attr &attr, bool initWeights = false) const; + + std::pair, std::vector> getPaddingFromNode(std::shared_ptr node) const; + void initEffectivePad(const Shape &inDims, const Shape &outDims); + mkldnn::algorithm getPoolingAlgorithm() const; + std::shared_ptr createDescriptorInternal(const mkldnn::memory::desc& in_candidate, + const mkldnn::memory::desc& out_candidate, + const mkldnn::algorithm alg) const; + + AttrPtr pAttr; + bool auto_pad = false; bool exclude_pad = false; std::vector stride; std::vector kernel; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.cpp index bcc37aebfe5305..1d3f2ff60d11fe 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.cpp @@ -73,10 +73,6 @@ using namespace InferenceEngine; bool MKLDNNProposalNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } const auto proposal0Op = ngraph::as_type_ptr(op); const auto proposal4Op = ngraph::as_type_ptr(op); if (!proposal0Op && !proposal4Op) { diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.h index c2da9756b7fc45..0c0c6d443a86ce 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_proposal_node.h @@ -22,6 +22,9 @@ class MKLDNNProposalNode : public MKLDNNNode { void execute(mkldnn::stream strm) override; bool created() const override; + bool needPrepareParams() const override { return false; }; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); }; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: @@ -35,8 +38,6 @@ class MKLDNNProposalNode : public MKLDNNNode { std::vector anchors; std::vector roi_indices; bool store_prob; // store blob with proposal probabilities - - std::string errorPrefix; }; } // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.cpp index 5ee2f0f92dd3bd..3d34abdef96d23 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.cpp @@ -22,6 +22,13 @@ MKLDNNReferenceNode::MKLDNNReferenceNode(const std::shared_ptr& op } setType(Reference); setTypeStr("Reference"); + + // RandomUniform should generate new sequence each run even if all inputs are constants. So that method MKLDNNNode::IsConstant() + // doesn't return 'True' for RandomUniform with all constant inputs and the node generates new values for each inference, + // we set 'NoConst' value for 'ConstantType' in ctor + if (ov::is_type(ngraphOp)) { + constant = ConstantType::NoConst; + } } void MKLDNNReferenceNode::getSupportedDescriptors() {} @@ -98,3 +105,7 @@ void MKLDNNReferenceNode::executeDynamicImpl(mkldnn::stream strm) { bool MKLDNNReferenceNode::created() const { return getType() == Reference; } + +bool MKLDNNReferenceNode::needShapeInfer() const { + return true; +} diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h index 41c4b3c7ac83d8..7b22ca646dbd79 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_reference_node.h @@ -19,6 +19,7 @@ class MKLDNNReferenceNode : public MKLDNNNode { bool created() const override; std::vector shapeInfer() const override; + bool needShapeInfer() const override; bool needPrepareParams() const override { return false; } void executeDynamicImpl(mkldnn::stream strm) override; diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp index d4367bb4837d80..7c3e3eb2c20e46 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_rnn.cpp @@ -794,6 +794,7 @@ void MKLDNNRNN::execute(mkldnn::stream strm) { (*prim).execute(strm, args); } +} // namespace MKLDNNPlugin + REG_MKLDNN_PRIM_FOR(MKLDNNRNN, RNNCell); REG_MKLDNN_PRIM_FOR(MKLDNNRNN, RNNSeq); -} // namespace MKLDNNPlugin diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.cpp index c6081a04593c61..1412d0d5afeb94 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.cpp @@ -21,11 +21,6 @@ using namespace InferenceEngine; bool MKLDNNSplitNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } - if (!MKLDNNPlugin::one_of(op->get_type_info(), ngraph::op::v1::Split::get_type_info_static(), ngraph::op::v1::VariadicSplit::get_type_info_static())) { errorMessage = "Only opset1 Split and VariadicSplit operations are supported"; return false; @@ -61,12 +56,13 @@ MKLDNNSplitNode::MKLDNNSplitNode(const std::shared_ptr& op, const INPUTS_NUM = 3; } + const auto inRank = getInputShapeAtPort(0).getRank(); auto axisOp = ngraph::as_type_ptr(op->get_input_node_shared_ptr(1)); auto axis = axisOp->cast_vector()[0]; if (axis < 0) { - axis += op->get_input_shape(0).size(); + axis += inRank; } - if (axis >= op->get_input_shape(0).size()) { + if (axis >= inRank) { THROW_ERROR << "Split node with name '" << op->get_friendly_name() << "' has invalid value of axis parameter: " << axis; } this->axis = axis; @@ -81,26 +77,21 @@ void MKLDNNSplitNode::initSupportedPrimitiveDescriptors() { if (!supportedPrimitiveDescriptors.empty()) return; - auto srcShape = getInputShapeAtPort(0); - auto axis_size = 0; - auto dstFirstDims = getOutputShapeAtPort(0).getStaticDims(); + const auto &srcShape = getInputShapeAtPort(0); + const auto &dstFirstDims = getOutputShapeAtPort(0).getDims(); for (size_t i = 0; i < outputShapes.size(); i++) { - auto o_Dims = outputShapes[i].getStaticDims(); + const auto &o_Dims = outputShapes[i].getDims(); if (dstFirstDims.size() != o_Dims.size()) { THROW_ERROR << "only supports output blobs with equal number of dimensions"; } - axis_size += o_Dims[axis]; for (size_t j = 0; j < dstFirstDims.size(); j++) { if (j == axis) continue; - if (o_Dims[j] != dstFirstDims[j]) + if (!dimsEqualWeak(o_Dims[j], dstFirstDims[j])) THROW_ERROR << "has incorrect output dimensions"; } } - dstFirstDims[axis] = axis_size; - if (std::accumulate(dstFirstDims.begin(), dstFirstDims.end(), 1, std::multiplies()) != srcShape.getElementsCount()) - THROW_ERROR << "sizes of input blob and sum of output blobs are not equal."; InferenceEngine::Precision inpPrecision = getOriginalInputPrecisionAtPort(0); const auto axisPrecision = getOriginalInputPrecisionAtPort(1); @@ -111,19 +102,20 @@ void MKLDNNSplitNode::initSupportedPrimitiveDescriptors() { dynBatchSupport = false; } - //Set plain and tailC formats + // Set plain and tailC formats std::vector tdCreatorTypes{ LayoutType::ncsp, LayoutType::nspc }; - //Support channel blocked format + // Support channel blocked format if (srcShape.getRank() > 2) { for (auto item : { std::make_pair(8lu, LayoutType::nCsp8c), std::make_pair(16lu, LayoutType::nCsp16c) }) { - SizeVector blkDims = srcShape.getStaticDims(); - if (blkDims[channelsPos] % item.first) + const auto &blkDims = srcShape.getDims(); + if (blkDims[channelsPos] == Shape::UNDEFINED_DIM || blkDims[channelsPos] % item.first != 0) continue; bool blocked = true; for (size_t i = 0; i < outputShapes.size(); i++) { - if (outputShapes[i].getStaticDims()[channelsPos] % item.first) { + const auto &outBlkDims = getOutputShapeAtPort(i).getDims(); + if (outBlkDims[channelsPos] == Shape::UNDEFINED_DIM || outBlkDims[channelsPos] % item.first != 0) { blocked = false; break; } @@ -148,9 +140,9 @@ void MKLDNNSplitNode::initSupportedPrimitiveDescriptors() { config.inConfs[0].desc = std::make_shared(itr->second->createDesc(inpPrecision, srcShape)); config.inConfs[1].inPlace = -1; config.inConfs[1].constant = true; - config.inConfs[1].desc = std::make_shared(axisPrecision, Shape(SizeVector {1})); + config.inConfs[1].desc = std::make_shared(axisPrecision, Shape(VectorDims{1})); if (INPUTS_NUM == 3) { - config.inConfs[2].desc = std::make_shared(axisPrecision, Shape(SizeVector{outputShapes.size()})); + config.inConfs[2].desc = std::make_shared(axisPrecision, Shape(VectorDims{outputShapes.size()})); config.inConfs[2].constant = true; } @@ -174,38 +166,41 @@ void MKLDNNSplitNode::initSupportedPrimitiveDescriptors() { } // Optimized inplace case - for (auto refPdIndex : pdIndexesToReuse) { - const auto& refConfig = supportedPrimitiveDescriptors[refPdIndex].getConfig(); - auto config = refConfig; - const auto inBlockingDesc = refConfig.inConfs[0].desc->as(); - const auto& order = inBlockingDesc->getOrder(); - const auto& blkDims = inBlockingDesc->getBlockDims(); - auto numOfDim = blkDims.size(); - - SizeVector offsets(numOfDim, 0lu); - SizeVector strides(numOfDim); - strides.back() = 1lu; - size_t offset = (std::numeric_limits::max)(); - - for (size_t i = 2; i <= numOfDim; i++) { - if (numOfDim - i < axis) { - strides[numOfDim - i] = (std::numeric_limits::max)(); - } else { - strides[numOfDim - i] = strides[numOfDim - i + 1] * blkDims[numOfDim - i + 1]; + // TODO [DS]: inplace + if (!isDynamicNode()) { + for (auto refPdIndex : pdIndexesToReuse) { + const auto& refConfig = supportedPrimitiveDescriptors[refPdIndex].getConfig(); + auto config = refConfig; + const auto inBlockingDesc = refConfig.inConfs[0].desc->as(); + const auto& order = inBlockingDesc->getOrder(); + const auto& blkDims = inBlockingDesc->getBlockDims(); + auto numOfDim = blkDims.size(); + + SizeVector offsets(numOfDim, 0lu); + SizeVector strides(numOfDim); + strides.back() = 1lu; + size_t offset = (std::numeric_limits::max)(); + + for (size_t i = 2; i <= numOfDim; i++) { + if (numOfDim - i < axis) { + strides[numOfDim - i] = (std::numeric_limits::max)(); + } else { + strides[numOfDim - i] = strides[numOfDim - i + 1] * blkDims[numOfDim - i + 1]; + } } - } - config.inConfs[0].desc = std::make_shared(inpPrecision, srcShape, blkDims, order, offset, offsets, strides); + config.inConfs[0].desc = std::make_shared(inpPrecision, srcShape, blkDims, order, offset, offsets, strides); - for (size_t i = 0; i < outputShapes.size(); i++) { - auto outBlockingDesc = refConfig.outConfs[i].desc->as(); - const auto& outBlkDims = outBlockingDesc->getBlockDims(); - const auto& dims = outBlockingDesc->getShape().getStaticDims(); + for (size_t i = 0; i < outputShapes.size(); i++) { + auto outBlockingDesc = refConfig.outConfs[i].desc->as(); + const auto& outBlkDims = outBlockingDesc->getBlockDims(); + const auto& dims = outBlockingDesc->getShape().getStaticDims(); - config.outConfs[i].inPlace = 0; - config.outConfs[i].desc = std::make_shared(outPrecision, Shape(dims), outBlkDims, order, offset, offsets, strides); + config.outConfs[i].inPlace = 0; + config.outConfs[i].desc = std::make_shared(outPrecision, Shape(dims), outBlkDims, order, offset, offsets, strides); + } + supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown); } - supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown); } // Special nspc -> ncsp case when splitting channels @@ -219,9 +214,9 @@ void MKLDNNSplitNode::initSupportedPrimitiveDescriptors() { config.inConfs[0].desc = creatorsMap.at(LayoutType::nspc)->createSharedDesc(inpPrecision, srcShape); config.inConfs[1].inPlace = -1; config.inConfs[1].constant = true; - config.inConfs[1].desc = std::make_shared(axisPrecision, Shape(SizeVector{1})); + config.inConfs[1].desc = std::make_shared(axisPrecision, Shape(VectorDims{1})); if (INPUTS_NUM == 3) { - config.inConfs[2].desc = std::make_shared(axisPrecision, Shape(SizeVector{outputShapes.size()})); + config.inConfs[2].desc = std::make_shared(axisPrecision, Shape(VectorDims{outputShapes.size()})); config.inConfs[2].constant = true; } config.outConfs.resize(outputShapes.size()); @@ -235,63 +230,75 @@ void MKLDNNSplitNode::initSupportedPrimitiveDescriptors() { } } -void MKLDNNSplitNode::createPrimitive() { - auto& srcMemPtr = getParentEdgeAt(0)->getMemoryPtr(); - if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) - THROW_ERROR << "Input memory has not been allocated."; - for (size_t i = 0; i < getChildEdges().size(); i++) { - if (!getChildEdgeAt(i)->getMemoryPtr() || !getChildEdgeAt(i)->getMemory().GetPrimitivePtr()) - THROW_ERROR << "Destination memory has not been allocated."; +bool MKLDNNSplitNode::needPrepareParams() const { + if (isOptimized()) { + return false; } - if (getSelectedPrimitiveDescriptor() == nullptr) - THROW_ERROR << "Preferable primitive descriptor is not set."; + return MKLDNNNode::inputShapesModified(); +} - auto& memDesc = getParentEdgeAt(0)->getMemoryPtr()->getDesc(); +void MKLDNNSplitNode::prepareParams() { + const auto &srcMemPtr = getParentEdgesAtPort(0)[0]->getMemoryPtr(); + if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) { + THROW_ERROR << "has not allocated input memory"; + } - canUseOptimizedNspc2Ncsp = false; - if (axis == 1 && one_of(memDesc.getShape().getRank(), 4, 5) && memDesc.hasLayoutType(LayoutType::nspc)) { - canUseOptimizedNspc2Ncsp = true; - for (size_t i = 0; i < getChildEdges().size(); i++) { - auto& childMemDesc = getChildEdgeAt(i)->getMemoryPtr()->getDesc(); - if (!childMemDesc.hasLayoutType(LayoutType::ncsp)) - canUseOptimizedNspc2Ncsp = false; + dstMemPtrs.clear(); + std::vector outDescs; + for (size_t i = 0; i < outputShapes.size(); ++i) { + const auto &outMemPtr = this->getChildEdgesAtPort(i)[0]->getMemoryPtr(); + if (!outMemPtr || !outMemPtr->GetPrimitivePtr()) { + THROW_ERROR << "has not allocated destination memory"; + } + + if (uint8_t* dstData = reinterpret_cast(outMemPtr->GetPtr())) { + dstMemPtrs.push_back(dstData); + } else { + THROW_ERROR << "can't get child edge indx " << i << "data."; + } + + if (!canUseOptimizedNspc2Ncsp) { + outDescs.push_back(outMemPtr->GetDescWithType()); } } - if (!isOptimized()) { - initializeDstMemPtrs(); - if (!canUseOptimizedNspc2Ncsp) - prepareOptimizedParams(); + if (!canUseOptimizedNspc2Ncsp) { + const auto inDesc = srcMemPtr->GetDescWithType(); + execPtr = std::make_shared(inDesc, outDescs, axis); + } +} + +void MKLDNNSplitNode::createPrimitive() { + if (getSelectedPrimitiveDescriptor() == nullptr) + THROW_ERROR << "Preferable primitive descriptor is not set."; + + if (inputShapesDefined()) { + if (needPrepareParams()) + prepareParams(); + updateLastInputDims(); } } void MKLDNNSplitNode::execute(mkldnn::stream strm) { - if (isOptimized()) + if (isOptimized()) { return; + } if (dstMemPtrs.empty()) THROW_ERROR << "Output data pointers have not been initialized."; - int MB = batchToProcess(); + const auto &srcMem = getParentEdgesAtPort(0)[0]->getMemory(); + size_t batch = srcMem.getStaticDims()[0]; + Dim MB = isDynamicNode() ? batch : batchToProcess(); if (canUseOptimizedNspc2Ncsp) { optimizedNspc2Ncsp(MB); return; } - uint8_t* srcData = reinterpret_cast(this->getParentEdgeAt(0)->getMemoryPtr()->GetPtr()); - size_t batch = getParentEdgesAtPort(0)[0]->getMemory().getStaticDims()[0]; - - if (batch != MB) - optimizedParams.countStrides = optimizedParams.countStrides / batch * MB; - - parallel_for2d(dstMemPtrs.size(), optimizedParams.countStrides, [&](size_t i, size_t j) { - uint8_t* dstData = dstMemPtrs[i]; - - cpu_memcpy(&dstData[j * optimizedParams.dataSize[i]], - &srcData[optimizedParams.srcDataOffsets[i] + j * optimizedParams.srcDataStride], - optimizedParams.dataSize[i]); - }); + uint8_t* srcData = reinterpret_cast(srcMem.GetPtr()); + IE_ASSERT(execPtr != nullptr); + execPtr->exec(srcData, dstMemPtrs, batch, MB); } bool MKLDNNSplitNode::created() const { @@ -303,61 +310,70 @@ bool MKLDNNSplitNode::isOptimized() const { } void MKLDNNSplitNode::initOptimalPrimitiveDescriptor() { - if (!isOptimized()) { - MKLDNNNode::initOptimalPrimitiveDescriptor(); - return; - } - auto selected_pd = getSelectedPrimitiveDescriptor(); if (selected_pd == nullptr) THROW_ERROR << "Preferable primitive descriptor is not set."; auto config = selected_pd->getConfig(); - if (isConfigDefined(config)) - return; - for (size_t i = 0; i < config.inConfs.size(); i++) { - if (config.inConfs[i].desc->isDefined()) - continue; - - int num = getParentEdgeAt(i)->getOutputNum(); - if (getParentEdgeAt(i)->getParent()->getSelectedPrimitiveDescriptor()) { - if (num >= 0) { - const auto& parentConfig = getParentEdgeAt(i)->getParent()->getSelectedPrimitiveDescriptor()->getConfig().outConfs[num]; - if (!parentConfig.desc->isDefined() && parentConfig.inPlace >= 0) - getParentEdgeAt(i)->getParent()->initOptimalPrimitiveDescriptor(); - if (parentConfig.desc->isDefined() && parentConfig.desc->isCompatible(*config.inConfs[i].desc)) { - config.inConfs[i].desc = parentConfig.desc; - continue; + if (!isOptimized()) { + MKLDNNNode::initOptimalPrimitiveDescriptor(); + } else if (!isConfigDefined(config)) { + for (size_t i = 0; i < config.inConfs.size(); i++) { + if (config.inConfs[i].desc->isDefined()) + continue; + + int num = getParentEdgeAt(i)->getOutputNum(); + if (getParentEdgeAt(i)->getParent()->getSelectedPrimitiveDescriptor()) { + if (num >= 0) { + const auto& parentConfig = getParentEdgeAt(i)->getParent()->getSelectedPrimitiveDescriptor()->getConfig().outConfs[num]; + if (!parentConfig.desc->isDefined() && parentConfig.inPlace >= 0) + getParentEdgeAt(i)->getParent()->initOptimalPrimitiveDescriptor(); + if (parentConfig.desc->isDefined() && parentConfig.desc->isCompatible(*config.inConfs[i].desc)) { + config.inConfs[i].desc = parentConfig.desc; + continue; + } } } + + // reset undefined offsets + config.inConfs[i].desc = config.inConfs[i].desc->as()->cloneWithDefaultStridesAndOffset(); } + if (config.outConfs.size() != outputShapes.size()) + THROW_ERROR << "has invalid config"; - // reset undefined offsets - config.inConfs[i].desc = config.inConfs[i].desc->as()->cloneWithDefaultStridesAndOffset(); + auto firstInBlockingDesc = config.inConfs[0].desc->as(); + size_t offset = 0; + for (size_t i = 0; i < outputShapes.size(); i++) { + auto oldDesc = config.outConfs[i].desc; + auto outBlockingDesc = oldDesc->as(); + config.outConfs[i].desc = std::make_shared(outBlockingDesc->getPrecision(), + outBlockingDesc->getShape(), + outBlockingDesc->getBlockDims(), + outBlockingDesc->getOrder(), + firstInBlockingDesc->getOffsetPadding() + offset, + firstInBlockingDesc->getOffsetPaddingToData(), + firstInBlockingDesc->getStrides()); + + size_t axisSize = 1; + for (size_t j = axis; j < outBlockingDesc->getBlockDims().size(); j++) { + axisSize *= outBlockingDesc->getBlockDims()[j]; + } + offset += axisSize; + } + initDescriptor(config); } - if (config.outConfs.size() != outputShapes.size()) - THROW_ERROR << "has invalid config"; - auto firstInBlockingDesc = config.inConfs[0].desc->as(); - size_t offset = 0; - for (size_t i = 0; i < outputShapes.size(); i++) { - auto oldDesc = config.outConfs[i].desc; - auto outBlockingDesc = oldDesc->as(); - config.outConfs[i].desc = std::make_shared(outBlockingDesc->getPrecision(), - outBlockingDesc->getShape(), - outBlockingDesc->getBlockDims(), - outBlockingDesc->getOrder(), - firstInBlockingDesc->getOffsetPadding() + offset, - firstInBlockingDesc->getOffsetPaddingToData(), - firstInBlockingDesc->getStrides()); - - size_t axisSize = 1; - for (size_t j = axis; j < outBlockingDesc->getBlockDims().size(); j++) { - axisSize *= outBlockingDesc->getBlockDims()[j]; + config = selected_pd->getConfig(); + canUseOptimizedNspc2Ncsp = false; + IE_ASSERT(config.inConfs.size() > 0); + const auto inConfDesc = config.inConfs[0].desc; + if (axis == 1 && one_of(inConfDesc->getShape().getRank(), 4, 5) && inConfDesc->hasLayoutType(LayoutType::nspc)) { + canUseOptimizedNspc2Ncsp = true; + for (size_t i = 0; i < config.outConfs.size(); i++) { + if (!config.outConfs[i].desc->hasLayoutType(LayoutType::ncsp)) + canUseOptimizedNspc2Ncsp = false; } - offset += axisSize; } - initDescriptor(config); } void MKLDNNSplitNode::selectOptimalPrimitiveDescriptor() { @@ -375,8 +391,7 @@ void MKLDNNSplitNode::selectOptimalPrimitiveDescriptor() { } } - //check the descriptors and select the ones that have the same data format as the input - + // check the descriptors and select the ones that have the same data format as the input std::vector canSelectPrimitive; for (size_t i = 0; i < supportedPrimitiveDescriptors.size(); i++) { auto parentEdge = getParentEdgeAt(0); @@ -397,6 +412,7 @@ void MKLDNNSplitNode::selectOptimalPrimitiveDescriptor() { selectPrimitiveDescriptorByIndex(static_cast(canSelectPrimitive[0])); return; } + // if there are more then one PD with similar data layouts - select the optimized one for (auto indx : canSelectPrimitive) { if (supportedPrimitiveDescriptors[indx].getImplementationType() == impl_desc_type::unknown) { @@ -463,55 +479,6 @@ void MKLDNNSplitNode::setDynamicBatchLim(int lim) { dynBatchLim = lim; } -void MKLDNNSplitNode::prepareOptimizedParams() { - auto selectedPrimitiveDescriptor = getSelectedPrimitiveDescriptor(); - if (!selectedPrimitiveDescriptor) - IE_THROW() << "CPU Split node with name '" << getName() << "' doesn't have primitive descriptors."; - const auto inpTensorDesc = getParentEdgeAt(0)->getMemory().GetDescWithType(); - const auto outputPortsCount = outputShapes.size(); - - //find axis order position - const auto& order = inpTensorDesc->getOrder(); - unsigned axisOrderPos = std::numeric_limits::max(); - for (size_t i = 0; i < order.size(); ++i) { - if (order[i] == axis) { - axisOrderPos = i; - break; - } - } - if (std::numeric_limits::max() == axisOrderPos) { - THROW_ERROR << "Can't find the axis in the input tensor order list"; - } - - uint8_t srcDataSize = inpTensorDesc->getPrecision().size(); - const auto& srcDims = inpTensorDesc->getBlockDims(); - const auto getRank = srcDims.size(); - - optimizedParams.countStrides = 1; - for (int i = 0; i < axisOrderPos; i++) - optimizedParams.countStrides *= srcDims[i]; - - optimizedParams.srcDataStride = 0; - optimizedParams.dataSize.resize(outputPortsCount); - - for (size_t i = 0; i < outputPortsCount; i++) { - auto outputEdge = this->getChildEdgesAtPort(i).front(); - optimizedParams.dataSize[i] = srcDataSize; - - auto desc = outputEdge->getMemory().getDesc().as(); - for (size_t j = axisOrderPos; j < getRank; j++) - optimizedParams.dataSize[i] *= desc->getBlockDims()[j]; - - optimizedParams.srcDataStride += optimizedParams.dataSize[i]; - } - - optimizedParams.srcDataOffsets.resize(outputPortsCount); - optimizedParams.srcDataOffsets[0] = 0; - for (size_t i = 1; i < outputPortsCount; i++) { - optimizedParams.srcDataOffsets[i] = optimizedParams.srcDataOffsets[i - 1] + optimizedParams.dataSize[i - 1]; - } -} - void MKLDNNSplitNode::optimizedNspc2Ncsp(size_t MB) { auto parentEdge = getParentEdgeAt(0); const int rank = parentEdge->getMemory().GetShape().getRank(); @@ -534,7 +501,7 @@ void MKLDNNSplitNode::optimizedNspc2Ncsp(size_t MB) { auto dstData = dstMemPtrs[i]; size_t innerSize = 1; - auto dims = outputShapes[i].getStaticDims(); + auto dims = getChildEdgesAtPort(i)[0]->getMemory().getStaticDims(); for (size_t j = axis; j < dims.size(); j++) { innerSize *= dims[j]; @@ -558,17 +525,62 @@ void MKLDNNSplitNode::optimizedNspc2Ncsp(size_t MB) { } } -void MKLDNNSplitNode::initializeDstMemPtrs() { - dstMemPtrs.clear(); - - for (size_t i = 0; i < outputShapes.size(); ++i) { - auto outputEdges = this->getChildEdgesAtPort(i); - if (uint8_t* dstData = reinterpret_cast(outputEdges.front()->getMemoryPtr()->GetPtr())) { - dstMemPtrs.push_back(dstData); - } else { - THROW_ERROR << "can't get child edge indx " << i << "data."; +MKLDNNSplitNode::SplitOptimizedExecutor::SplitOptimizedExecutor(BlockedMemoryDescCPtr inDesc, const std::vector &outDescs, + const size_t axis) { + // find axis order position + const auto& order = inDesc->getOrder(); + unsigned axisOrderPos = std::numeric_limits::max(); + for (size_t i = 0; i < order.size(); ++i) { + if (order[i] == axis) { + axisOrderPos = i; + break; } } + if (std::numeric_limits::max() == axisOrderPos) { + IE_THROW() << "Can't create split executor, because can't find the axis in the input tensor order list"; + } + + const auto outputPortsCount = outDescs.size(); + + uint8_t srcDataSize = inDesc->getPrecision().size(); + const auto& srcDims = inDesc->getBlockDims(); + const auto getRank = srcDims.size(); + + countStrides = 1; + for (int i = 0; i < axisOrderPos; i++) + countStrides *= srcDims[i]; + + srcDataStride = 0; + dataSize.resize(outputPortsCount); + + for (size_t i = 0; i < outputPortsCount; i++) { + dataSize[i] = srcDataSize; + for (size_t j = axisOrderPos; j < getRank; j++) + dataSize[i] *= outDescs[i]->getBlockDims()[j]; + + srcDataStride += dataSize[i]; + } + + srcDataOffsets.resize(outputPortsCount); + srcDataOffsets[0] = 0; + for (size_t i = 1; i < outputPortsCount; i++) { + srcDataOffsets[i] = srcDataOffsets[i - 1] + dataSize[i - 1]; + } +} + +void MKLDNNSplitNode::SplitOptimizedExecutor::exec(const uint8_t* srcData, const std::vector &dstMemPtrs, + const Dim origBatch, const Dim perInferBatch) { + size_t execCountStrides = countStrides; + if (origBatch != perInferBatch) + execCountStrides = execCountStrides / origBatch * perInferBatch; + + parallel_for2d(dstMemPtrs.size(), execCountStrides, [&](size_t i, size_t j) { + uint8_t* dstData = dstMemPtrs[i]; + + cpu_memcpy(&dstData[j * dataSize[i]], + &srcData[srcDataOffsets[i] + j * srcDataStride], + dataSize[i]); + }); } REG_MKLDNN_PRIM_FOR(MKLDNNSplitNode, Split); diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h index e7f99105d1d4d2..20f18555d905e0 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_split_node.h @@ -30,9 +30,31 @@ class MKLDNNSplitNode : public MKLDNNNode { return !isOptimized(); } + bool needPrepareParams() const override; + void prepareParams() override; + void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); } + private: - void prepareOptimizedParams(); - void initializeDstMemPtrs(); + struct SplitExecutor { + virtual void exec(const uint8_t* srcData, const std::vector &dstMemPtrs, + const Dim origBatch, const Dim perInferBatch) = 0; + virtual ~SplitExecutor() = default; + }; + std::shared_ptr execPtr = nullptr; + + struct SplitOptimizedExecutor : public SplitExecutor { + public: + SplitOptimizedExecutor(BlockedMemoryDescCPtr inDesc, const std::vector &outDescs, const size_t axis); + void exec(const uint8_t* srcData, const std::vector &dstMemPtrs, + const Dim origBatch, const Dim perInferBatch) override; + + private: + std::vector dataSize; + std::vector srcDataOffsets; + size_t srcDataStride; + size_t countStrides; + }; + void optimizedNspc2Ncsp(size_t MB); bool canUseOptimizedNspc2Ncsp; @@ -40,13 +62,6 @@ class MKLDNNSplitNode : public MKLDNNNode { size_t axis = 1; std::vector dstMemPtrs; - struct { - std::vector dataSize; - std::vector srcDataOffsets; - size_t srcDataStride; - size_t countStrides; - } optimizedParams; - size_t INPUTS_NUM = 2; }; diff --git a/inference-engine/src/mkldnn_plugin/utils/cpu_utils.hpp b/inference-engine/src/mkldnn_plugin/utils/cpu_utils.hpp index 14fd043dce0824..e9c213f23fb608 100644 --- a/inference-engine/src/mkldnn_plugin/utils/cpu_utils.hpp +++ b/inference-engine/src/mkldnn_plugin/utils/cpu_utils.hpp @@ -38,7 +38,8 @@ inline std::vector getNormalizedDimsBySize(const InferenceEngine::SizeVe */ inline bool isPerTensorOrPerChannelBroadcastable(const InferenceEngine::SizeVector &firstInputDims, const InferenceEngine::SizeVector& secondInputDims, bool weakComparison = false) { - bool (*dimsEqual)(size_t, size_t) = weakComparison ? static_cast(dimsEqualWeak) : dimsEqualStrong; + bool (*dimsEqual)(size_t, size_t) = weakComparison ? static_cast(dimsEqualWeak) : + static_cast(dimsEqualStrong); if (secondInputDims.size() > firstInputDims.size()) return false; if (std::accumulate(secondInputDims.begin(), secondInputDims.end(), 1, std::multiplies()) == 1) @@ -72,12 +73,17 @@ inline InferenceEngine::Precision normalizeToSupportedPrecision(InferenceEngine: case InferenceEngine::Precision::FP32: { break; } + case InferenceEngine::Precision::FP64: { + precision = InferenceEngine::Precision::FP32; + break; + } case InferenceEngine::Precision::BOOL: { precision = InferenceEngine::Precision::U8; break; } case InferenceEngine::Precision::U16: case InferenceEngine::Precision::I16: + case InferenceEngine::Precision::U32: case InferenceEngine::Precision::I64: case InferenceEngine::Precision::U64: { precision = InferenceEngine::Precision::I32; diff --git a/inference-engine/src/mkldnn_plugin/utils/general_utils.h b/inference-engine/src/mkldnn_plugin/utils/general_utils.h index 012054e59e10c5..7a6c1e51022dd4 100644 --- a/inference-engine/src/mkldnn_plugin/utils/general_utils.h +++ b/inference-engine/src/mkldnn_plugin/utils/general_utils.h @@ -67,6 +67,26 @@ inline bool dimsEqualStrong(size_t lhs, size_t rhs) { return (lhs == rhs && lhs != Shape::UNDEFINED_DIM && rhs != Shape::UNDEFINED_DIM); } +/** + * @brief Compares that two shapes are equal + * @param lhs + * first shape + * @param rhs + * second shape + * @return result of comparison + */ +inline bool dimsEqualStrong(const std::vector& lhs, const std::vector& rhs, size_t skipAxis = Shape::UNDEFINED_DIM) { + if (lhs.size() != rhs.size()) + return false; + + for (size_t i = 0; i < lhs.size(); i++) { + if (i != skipAxis && !dimsEqualStrong(lhs[i], rhs[i])) + return false; + } + + return true; +} + /** * @brief Compares that two dims are equal or undefined * @param lhs @@ -87,7 +107,7 @@ inline bool dimsEqualWeak(size_t lhs, size_t rhs) { * second shape * @param skipAxis * marks shape axis which shouldn't be validated - * @return order + * @return result of comparison */ inline bool dimsEqualWeak(const std::vector& lhs, const std::vector& rhs, size_t skipAxis = Shape::UNDEFINED_DIM) { if (lhs.size() != rhs.size()) diff --git a/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_dimension.hpp b/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_dimension.hpp index 03aee9d63f94c6..20efc49cdc70c6 100644 --- a/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_dimension.hpp +++ b/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_dimension.hpp @@ -9,6 +9,9 @@ #include #include +#include "openvino/core/dimension.hpp" +#include "openvino/core/except.hpp" + namespace ov { /// \brief Class representing a dimension, which must be static, /// in a shape or shape-like object. @@ -25,6 +28,10 @@ class StaticDimension { /// \brief Construct a zero dimension StaticDimension() = default; + StaticDimension(const Dimension &) { + OPENVINO_UNREACHABLE("[shape infer] Shoudn't convert from Dimension to StaticDimension."); + } + bool operator==(const StaticDimension& dimension) const; bool operator!=(const StaticDimension& dimension) const; @@ -35,6 +42,12 @@ class StaticDimension { value_type get_min_length() const; value_type get_max_length() const; + Interval& get_interval() const { + static Interval dummy{}; + OPENVINO_UNREACHABLE("[shape infer] Shoudn't call get_interval() in StaticDimension."); + return dummy; + } + bool same_scheme(const StaticDimension& dim) const; bool compatible(const StaticDimension& d) const; static bool merge(StaticDimension& dst, const StaticDimension& d1, const StaticDimension& d2); diff --git a/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_shape.hpp b/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_shape.hpp index f0dd557f7f3f4a..1afa6f2b02ddf7 100644 --- a/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_shape.hpp +++ b/inference-engine/src/mkldnn_plugin/utils/shape_inference/static_shape.hpp @@ -12,6 +12,7 @@ #include "openvino/core/rank.hpp" #include "openvino/core/shape.hpp" #include "openvino/core/partial_shape.hpp" +#include "openvino/core/except.hpp" namespace ov { namespace op { @@ -26,6 +27,10 @@ class StaticShape : public std::vector { StaticShape(const std::vector& dimensions); StaticShape(std::vector dimensions); + StaticShape(const PartialShape &) { + OPENVINO_UNREACHABLE("[shape infer] Shouldn't convert from PartialShape to StaticShape at runtime."); + } + static bool is_static() { return true; } static bool is_dynamic() { return false; } diff --git a/inference-engine/src/multi_device/multi_device_exec_network.cpp b/inference-engine/src/multi_device/multi_device_exec_network.cpp index 2e90d94f2f5aa3..30d39e382d6f7c 100644 --- a/inference-engine/src/multi_device/multi_device_exec_network.cpp +++ b/inference-engine/src/multi_device/multi_device_exec_network.cpp @@ -21,6 +21,7 @@ #include "ngraph/opsets/opset1.hpp" #include "transformations/utils/utils.hpp" +#include "multi_itt.hpp" // ------------------------------MultiDeviceExecutableNetwork---------------------------- namespace MultiDevicePlugin { using namespace InferenceEngine; @@ -159,7 +160,7 @@ MultiDeviceExecutableNetwork::MultiDeviceExecutableNetwork(const std::string& _config[MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES] = strDevices; std::vector needLoadDevices; - + std::string profilingTask = "MultiDeviceExecutableNetwork::MultiDeviceExecutableNetwork:AutoMode"; // check if have cpu device const auto CPUIter = std::find_if(metaDevices.begin(), metaDevices.end(), [=](const DeviceInformation& d)->bool{return d.deviceName.find("CPU") != std::string::npos;}); @@ -168,6 +169,7 @@ MultiDeviceExecutableNetwork::MultiDeviceExecutableNetwork(const std::string& _config.insert(_cpuDevice.config.begin(), _cpuDevice.config.end()); needLoadDevices.push_back(_cpuDevice); _cpuFuture = _cpuPromise.get_future(); + profilingTask += _cpuDevice.deviceName; } // get accelerator device, like GPU @@ -179,8 +181,9 @@ MultiDeviceExecutableNetwork::MultiDeviceExecutableNetwork(const std::string& _config.insert(_acceleratorDevice.config.begin(), _acceleratorDevice.config.end()); needLoadDevices.push_back(_acceleratorDevice); _acceleratorFuture = _acceleratorPromise.get_future(); + profilingTask += _acceleratorDevice.deviceName; } - + OV_ITT_SCOPED_TASK(itt::domains::MULTIPlugin, openvino::itt::handle(profilingTask)); if (needLoadDevices.size() == 0) { IE_THROW() << "No device set"; } @@ -254,6 +257,7 @@ void MultiDeviceExecutableNetwork::WaitFirstNetworkReady() { void MultiDeviceExecutableNetwork::WaitActualNetworkReady() const { // Maybe different API will call this function, so add call once here // for every MultiDeviceExecutableNetwork instance + OV_ITT_SCOPED_TASK(itt::domains::MULTIPlugin, "MultiDeviceExecutableNetwork::WaitActualNetworkReady"); std::call_once(_oc, [&] () { if (_acceleratorFuture.valid()) { _networkActualNeeded = _acceleratorFuture.get(); @@ -350,7 +354,6 @@ std::shared_ptr MultiDeviceExecutableNetwork::Ge WaitActualNetworkReady(); return _networkActualNeeded->GetContext(); } - auto devices = [&] { std::lock_guard lock(_mutex); return _devicePriorities; @@ -380,6 +383,11 @@ InferenceEngine::IInferRequestInternal::Ptr MultiDeviceExecutableNetwork::Create InferenceEngine::SoIInferRequestInternal request_to_share_blobs_with; if (_workModeIsAUTO) { + if (!_networkFirstReady && _networkActualNeeded) { + auto& dev_requests = _workerRequests[_acceleratorDevice.deviceName]; + auto index = num % dev_requests.size(); + request_to_share_blobs_with = dev_requests.at(index)._inferRequest; + } return std::make_shared(inputs, outputs, request_to_share_blobs_with); } @@ -403,6 +411,11 @@ InferenceEngine::IInferRequestInternal::Ptr MultiDeviceExecutableNetwork::Create InferenceEngine::SoIInferRequestInternal request_to_share_blobs_with; if (_workModeIsAUTO) { + if (!_networkFirstReady && _networkActualNeeded) { + auto& dev_requests = _workerRequests[_acceleratorDevice.deviceName]; + auto index = num % dev_requests.size(); + request_to_share_blobs_with = dev_requests.at(index)._inferRequest; + } return std::make_shared(networkInputs, networkOutputs, request_to_share_blobs_with); } diff --git a/inference-engine/src/multi_device/multi_device_plugin.cpp b/inference-engine/src/multi_device/multi_device_plugin.cpp index 79d3eee9312a54..8fc3fc7a621e94 100644 --- a/inference-engine/src/multi_device/multi_device_plugin.cpp +++ b/inference-engine/src/multi_device/multi_device_plugin.cpp @@ -20,6 +20,7 @@ #include #include +#include "multi_itt.hpp" // ------------------------------MultiDeviceInferencePlugin---------------------------- namespace MultiDevicePlugin { using namespace InferenceEngine; @@ -57,6 +58,8 @@ namespace { auto res = PerfHintsConfig::SupportedKeys(); res.push_back(MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES); res.push_back(CONFIG_KEY_INTERNAL(MULTI_WORK_MODE_AS_AUTO)); + res.push_back(PluginConfigParams::KEY_PERF_COUNT); + res.push_back(PluginConfigParams::KEY_EXCLUSIVE_ASYNC_REQUESTS); return res; }(); } // namespace @@ -159,16 +162,12 @@ InferenceEngine::Parameter MultiDeviceInferencePlugin::GetConfig(const std::stri } void MultiDeviceInferencePlugin::SetConfig(const std::map & config) { - const auto perf_hints_configs = PerfHintsConfig::SupportedKeys(); + bool needPerfCounters = false; + std::map filterConfig; + CheckConfig(config, needPerfCounters, filterConfig); for (auto && kvp : config) { const auto& name = kvp.first; - if (supported_configKeys.end() != std::find(supported_configKeys.begin(), supported_configKeys.end(), name)) { - if (std::find(perf_hints_configs.begin(), perf_hints_configs.end(), kvp.first) != perf_hints_configs.end()) - PerfHintsConfig::CheckConfigAndValue(kvp); - _config[name] = kvp.second; - } else { - IE_THROW() << "Unsupported config key: " << name; - } + _config[name] = kvp.second; } } @@ -237,6 +236,7 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons if (workModeAuto) { // check the configure and check if need to set PerfCounters configure to device // and set filter configure + OV_ITT_SCOPED_TASK(itt::domains::MULTIPlugin, "MultiDeviceInferencePlugin::LoadNetworkImpl::AutoMode"); bool needPerfCounters = false; std::map filterConfig; CheckConfig(fullConfig, needPerfCounters, filterConfig); @@ -268,7 +268,7 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons return std::make_shared(modelPath, network, supportDevices, strDevices, this, needPerfCounters); } - + OV_ITT_SCOPED_TASK(itt::domains::MULTIPlugin, "MultiDeviceInferencePlugin::LoadNetworkImpl:MultiMode"); if (priorities == fullConfig.end()) { IE_THROW() << "KEY_MULTI_DEVICE_PRIORITIES key is not set for " << GetName() << " device"; } else { // for use case -d MULTI:xPU or -d AUTO:xPU @@ -375,6 +375,7 @@ QueryNetworkResult MultiDeviceInferencePlugin::QueryNetwork(const CNNNetwork& } DeviceInformation MultiDeviceInferencePlugin::SelectDevice(const std::vector& metaDevices, const std::string& networkPrecision) { + OV_ITT_SCOPED_TASK(itt::domains::MULTIPlugin, "MultiDeviceInferencePlugin::SelectDevice"); if (metaDevices.empty()) { IE_THROW(NotFound) << "No available device to select in " << GetName() << " plugin"; } diff --git a/inference-engine/src/multi_device/multi_itt.hpp b/inference-engine/src/multi_device/multi_itt.hpp new file mode 100644 index 00000000000000..dd3b7a03f9f210 --- /dev/null +++ b/inference-engine/src/multi_device/multi_itt.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/** + * @brief Defines openvino domains for tracing + * @file multi_itt.h + */ + +#pragma once + +#include + +namespace MultiDevicePlugin { +namespace itt { +namespace domains { + OV_ITT_DOMAIN(MULTIPlugin); +} +} +} diff --git a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp index b454d6a326fca9..bd0c074eb4c8d1 100644 --- a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp +++ b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iexecutable_network_internal.hpp @@ -115,13 +115,6 @@ class INFERENCE_ENGINE_API_CLASS(IExecutableNetworkInternal) */ virtual std::shared_ptr GetExecGraphInfo(); - /** - * @deprecated Need to implement GetVariablesInfo for ExecutableNetwork - * @brief Queries memory states. - * @return Returns memory states - */ - virtual std::vector> QueryState(); - /** * @brief Sets the pointer to plugin internal. * @param[in] plugin The plugin diff --git a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp index 2a4db632fd757d..09383330e22b86 100644 --- a/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp +++ b/inference-engine/src/plugin_api/cpp_interfaces/interface/ie_iplugin_internal.hpp @@ -331,7 +331,6 @@ using CreatePluginEngineFunc = void(std::shared_ptr&); * @private */ using CreateExtensionFunc = void(std::shared_ptr&); -; /** * @def IE_CREATE_PLUGIN diff --git a/inference-engine/src/plugin_api/performance_heuristics.hpp b/inference-engine/src/plugin_api/performance_heuristics.hpp index 3b58ae88570b6c..aeb4ebcfaf007a 100644 --- a/inference-engine/src/plugin_api/performance_heuristics.hpp +++ b/inference-engine/src/plugin_api/performance_heuristics.hpp @@ -28,7 +28,7 @@ static MemBandwidthPressure MemBandwidthPressureTolerance( const float memThresholdAssumeLimited = MemBandwidthPressure::LIMITED) { int total_convs = 0, mem_limited_convs = 0, compute_convs = 0, total_gemms = 0, mem_limited_gemms = 0, total_deconvs = 0, compute_deconvs = 0, mem_limited_deconvs = 0; - auto memLimitedFactor = [&](int size_data_moved, int datatype_size = 4) -> float { + auto memLimitedFactor = [&](int size_data_moved, int datatype_size) -> float { return (L2_cache_size * 1.0f /*util factor, tbd */ / (size_data_moved * datatype_size)); }; diff --git a/inference-engine/src/preprocessing/CMakeLists.txt b/inference-engine/src/preprocessing/CMakeLists.txt index e3c52c8236d21b..29e415e9ade136 100644 --- a/inference-engine/src/preprocessing/CMakeLists.txt +++ b/inference-engine/src/preprocessing/CMakeLists.txt @@ -139,8 +139,9 @@ else() target_link_libraries(inference_engine PRIVATE ${TARGET_NAME}) endif() -target_include_directories(${TARGET_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}" - $) +target_include_directories(${TARGET_NAME} INTERFACE + $ + $) # Workaround to avoid warnings caused with bug in the avx512intrin.h of GCC5 if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND @@ -185,5 +186,9 @@ openvino_developer_export_targets(COMPONENT inference_engine TARGETS ${TARGET_NA # install -install(TARGETS ${TARGET_NAME} - LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core) +if(BUILD_SHARED_LIBS) + install(TARGETS ${TARGET_NAME} + LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core) +else() + ov_install_static_lib(${TARGET_NAME} core) +endif() diff --git a/inference-engine/src/preprocessing/ie_preprocess_data.hpp b/inference-engine/src/preprocessing/ie_preprocess_data.hpp index 347c239f943cf6..4204aa69b54bc6 100644 --- a/inference-engine/src/preprocessing/ie_preprocess_data.hpp +++ b/inference-engine/src/preprocessing/ie_preprocess_data.hpp @@ -102,7 +102,7 @@ class PreProcessDataPlugin { } void isApplicable(const Blob::Ptr &src, const Blob::Ptr &dst) { - OV_PREPROC_PLUGIN_CALL_STATEMENT(return _ptr->isApplicable(src, dst)); + OV_PREPROC_PLUGIN_CALL_STATEMENT(_ptr->isApplicable(src, dst)); } }; diff --git a/inference-engine/src/readers/CMakeLists.txt b/inference-engine/src/readers/CMakeLists.txt index 46028205d37932..29cd6e6c3277f2 100644 --- a/inference-engine/src/readers/CMakeLists.txt +++ b/inference-engine/src/readers/CMakeLists.txt @@ -8,9 +8,11 @@ set(TARGET_NAME inference_engine_reader_api) add_library(${TARGET_NAME} INTERFACE) target_include_directories(${TARGET_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/reader_api" + $ $) +ov_install_static_lib(${TARGET_NAME} core) + file(GLOB_RECURSE reader_api_hpp "${CMAKE_CURRENT_SOURCE_DIR}/reader_api/*.hpp") add_cpplint_target(${TARGET_NAME}_cpplint FOR_SOURCES ${reader_api_hpp}) diff --git a/inference-engine/src/readers/ir_reader_v7/CMakeLists.txt b/inference-engine/src/readers/ir_reader_v7/CMakeLists.txt index 846b831825be81..d53fc13abc7d1e 100644 --- a/inference-engine/src/readers/ir_reader_v7/CMakeLists.txt +++ b/inference-engine/src/readers/ir_reader_v7/CMakeLists.txt @@ -55,6 +55,8 @@ endif() add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME}) +# Install rules + # for ieFuncTests install(TARGETS ${TARGET_NAME} LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT tests EXCLUDE_FROM_ALL) @@ -67,3 +69,5 @@ else() install(TARGETS ${TARGET_NAME} LIBRARY DESTINATION tests/lib COMPONENT tests EXCLUDE_FROM_ALL) endif() + +ov_install_static_lib(${TARGET_NAME} core) diff --git a/inference-engine/src/snippets/CMakeLists.txt b/inference-engine/src/snippets/CMakeLists.txt index db2c8413083c4e..334c2b8fb312a6 100644 --- a/inference-engine/src/snippets/CMakeLists.txt +++ b/inference-engine/src/snippets/CMakeLists.txt @@ -17,7 +17,7 @@ source_group("include" FILES ${PUBLIC_HEADERS}) # Create library -add_library(${TARGET_NAME} +add_library(${TARGET_NAME} EXCLUDE_FROM_ALL ${LIBRARY_SRC} ${PUBLIC_HEADERS}) @@ -53,9 +53,13 @@ openvino_developer_export_targets(COMPONENT inference_engine TARGETS ${TARGET_NA # install # TODO: uncomment once snippets are integrated into CPU plugin -# install(TARGETS ${TARGET_NAME} -# RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core -# LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) +# if(BUILD_SHARED_LIBS) +# install(TARGETS ${TARGET_NAME} +# RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT core +# LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT core) +# else() +# ov_install_static_lib(${TARGET_NAME} core) +# endif() # TODO: remove once install commands above are commented out install(TARGETS ${TARGET_NAME} diff --git a/inference-engine/src/transformations/include/ngraph_ops/type_relaxed.hpp b/inference-engine/src/transformations/include/ngraph_ops/type_relaxed.hpp index f59818a93f4106..2c331f3fb468d6 100644 --- a/inference-engine/src/transformations/include/ngraph_ops/type_relaxed.hpp +++ b/inference-engine/src/transformations/include/ngraph_ops/type_relaxed.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -92,7 +93,9 @@ class NGRAPH_API TypeRelaxedBase { for (size_t i = 0; i < node.get_input_size(); ++i) { auto origin_input_type = get_origin_input_type(i); if (origin_input_type != element::undefined) { + OPENVINO_SUPPRESS_DEPRECATED_START node.get_input_tensor(i).set_tensor_type(origin_input_type, node.get_input_partial_shape(i)); + OPENVINO_SUPPRESS_DEPRECATED_END } } } @@ -100,7 +103,9 @@ class NGRAPH_API TypeRelaxedBase { void restore_input_data_types(Node &node, const element::TypeVector &old_input_types) { // Restore original input data types for (size_t i = 0; i < node.get_input_size(); ++i) { + OPENVINO_SUPPRESS_DEPRECATED_START node.get_input_tensor(i).set_tensor_type(old_input_types[i], node.get_input_partial_shape(i)); + OPENVINO_SUPPRESS_DEPRECATED_END } if (m_original_output_data_types.empty()) { @@ -158,7 +163,9 @@ class TemporaryReplaceOutputType { TemporaryReplaceOutputType(Output output, element::Type tmp_type) : m_output(output) { // save original element type in order to restore it in the destructor orig_type = m_output.get_element_type(); + OPENVINO_SUPPRESS_DEPRECATED_START m_output.get_tensor().set_element_type(tmp_type); + OPENVINO_SUPPRESS_DEPRECATED_END } /// Return the output port that was used in the constructor @@ -168,7 +175,9 @@ class TemporaryReplaceOutputType { /// Restores the original element type for the output ~TemporaryReplaceOutputType() { + OPENVINO_SUPPRESS_DEPRECATED_START m_output.get_tensor().set_element_type(orig_type); + OPENVINO_SUPPRESS_DEPRECATED_END } }; @@ -227,6 +236,7 @@ class TypeRelaxed : public BaseOp, public TypeRelaxedBase { bool visit_attributes(AttributeVisitor& visitor) override; private: + mutable std::mutex type_relax_mutex; void init() { validate_and_infer_types(); } @@ -307,6 +317,7 @@ void TypeRelaxed::validate_and_infer_types() { template std::shared_ptr TypeRelaxed::clone_with_new_inputs(const OutputVector& new_args) const { + std::lock_guard lock(type_relax_mutex); // copy then modify inputs std::shared_ptr new_node = std::make_shared>((BaseOp&)(*this), m_input_data_types, m_output_data_types); for (size_t i = 0; i < new_node->get_input_size(); ++i) { diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/compress_float_constants.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/compress_float_constants.hpp new file mode 100644 index 00000000000000..a0a4ef18580e7d --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/compress_float_constants.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "transformations_visibility.hpp" +#include "openvino/pass/graph_rewrite.hpp" + +namespace ov { +namespace pass { + +class TRANSFORMATIONS_API CompressFloatConstantsImpl; +class TRANSFORMATIONS_API AddOldApiMapToParameters; +class TRANSFORMATIONS_API CompressFloatConstants; + +} // namespace pass +} // namespace ov + +/** + * @ingroup ie_transformation_common_api + * @brief CompressFloatConstantsImpl transformation replaces FP32/FP64 Constants with FP16 ones. + */ +class ov::pass::CompressFloatConstantsImpl : public ov::pass::MatcherPass { +public: + OPENVINO_RTTI("CompressFloatConstantsImpl", "0"); + CompressFloatConstantsImpl(); +}; + +/** + * @ingroup ie_transformation_common_api + * @brief AddOldApiMapToParameters transformation adds OldApiMap to each float input to the model. + */ +class ov::pass::AddOldApiMapToParameters : public ov::pass::MatcherPass { +public: + OPENVINO_RTTI("AddOldApiMapToParameters", "0"); + AddOldApiMapToParameters(); +}; + +/** + * @ingroup ie_transformation_common_api + * @brief CompressFloatConstants transformation replaces FP32/FP64 Constants with FP16 ones. + */ +class ov::pass::CompressFloatConstants : public ov::pass::GraphRewrite { +public: + OPENVINO_RTTI("CompressFloatConstants", "0"); + CompressFloatConstants() { + add_matcher(); + add_matcher(); + } +}; diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/convert_compression_only_to_legacy.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/convert_compression_only_to_legacy.hpp new file mode 100644 index 00000000000000..40a297f65913b8 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/convert_compression_only_to_legacy.hpp @@ -0,0 +1,50 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "transformations_visibility.hpp" +#include "openvino/pass/pass.hpp" +#include "openvino/pass/graph_rewrite.hpp" + +namespace ov { +namespace pass { + +class TRANSFORMATIONS_API ConvertPrecisionCompressedOnly; +class TRANSFORMATIONS_API EnableDecompressionConvertConstantFolding; +class TRANSFORMATIONS_API ConvertCompressedOnlyToLegacy; + +} // namespace pass +} // namespace ov + +/** + * @ingroup ie_transformation_common_api + * @brief ConvertPrecisionCompressedOnly transformation runs ConvertPrecision transformation for CompressedOnly format. + */ + +class ov::pass::ConvertPrecisionCompressedOnly : public ov::pass::FunctionPass { +public: + OPENVINO_RTTI("ConvertPrecisionCompressedOnly", "0"); + bool run_on_function(std::shared_ptr f) override; +}; + +/** + * @ingroup ie_transformation_common_api + * @brief Enables ConstantFolding for Convert operation in compressed function. + */ +class ov::pass::EnableDecompressionConvertConstantFolding : public ov::pass::MatcherPass { +public: + OPENVINO_RTTI("EnableDecompressionConvertConstantFolding", "0"); + EnableDecompressionConvertConstantFolding(); +}; + +/** + * @ingroup ie_transformation_common_api + * @brief ConvertCompressedOnlyToLegacy transformation converts compression only FP16 format to legacy FP16 format. + */ +class ov::pass::ConvertCompressedOnlyToLegacy : public ov::pass::FunctionPass { +public: + OPENVINO_RTTI("ConvertCompressedOnlyToLegacy", "0"); + bool run_on_function(std::shared_ptr f) override; +}; diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/divide_fusion.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/divide_fusion.hpp new file mode 100644 index 00000000000000..e469b0a57985f7 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/divide_fusion.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +namespace ngraph { +namespace pass { + +class TRANSFORMATIONS_API DivideFusion; + +} // namespace pass +} // namespace ngraph + +/** + * @ingroup ie_transformation_common_api + * @brief DivideFusion transformation replaces a sub-graph + * Pow(y, -1) * x or x * Pow(y, -1) with Divide(x,y) + */ +class ngraph::pass::DivideFusion : public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + DivideFusion(); +}; \ No newline at end of file diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/mark_precision_sensitive_subgraphs.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/mark_precision_sensitive_subgraphs.hpp new file mode 100644 index 00000000000000..ad72e23e1df091 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/mark_precision_sensitive_subgraphs.hpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "transformations_visibility.hpp" +#include "openvino/pass/pass.hpp" + + +namespace ov { +namespace pass { + +class TRANSFORMATIONS_API MarkPrecisionSensitiveSubgraphs; + +} // namespace pass +} // namespace ov + +/** + * @ingroup ie_transformation_common_api + * @brief MarkPrecisionSensitiveSubgraphs transformation marks the constants + * inside the subgraph starting from precision-sensitive input and ending at + * the ShapeOf node as disabled for FP16 compression. + */ +class ov::pass::MarkPrecisionSensitiveSubgraphs : public FunctionPass { +public: + OPENVINO_RTTI("MarkPrecisionSensitiveSubgraphs", "0"); + bool run_on_function(std::shared_ptr f) override; +}; diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/optimize_strided_slice.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/optimize_strided_slice.hpp index 9b4f7f80d7f2ec..1d6c10a5909da1 100644 --- a/inference-engine/src/transformations/include/transformations/common_optimizations/optimize_strided_slice.hpp +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/optimize_strided_slice.hpp @@ -68,6 +68,11 @@ class ngraph::pass::GroupedStridedSliceOptimizer: public ngraph::pass::FunctionP */ class ngraph::pass::StridedSliceOptimization: public ngraph::pass::FunctionPass { public: + StridedSliceOptimization(bool use_shapes = true); + NGRAPH_RTTI_DECLARATION; bool run_on_function(std::shared_ptr f) override; + +private: + bool m_use_shapes = true; }; diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/remove_filtering_boxes_by_size.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/remove_filtering_boxes_by_size.hpp index 1aa4ee16bddcf3..4ae870ccc6f45e 100644 --- a/inference-engine/src/transformations/include/transformations/common_optimizations/remove_filtering_boxes_by_size.hpp +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/remove_filtering_boxes_by_size.hpp @@ -14,11 +14,18 @@ namespace ngraph { namespace pass { +class TRANSFORMATIONS_API FuseFilteringBoxesBySize; class TRANSFORMATIONS_API RemoveFilteringBoxesBySize; } // namespace pass } // namespace ngraph +class ngraph::pass::FuseFilteringBoxesBySize: public ngraph::pass::GraphRewrite { +public: + NGRAPH_RTTI_DECLARATION; + FuseFilteringBoxesBySize(); +}; + class ngraph::pass::RemoveFilteringBoxesBySize: public ngraph::pass::MatcherPass { public: NGRAPH_RTTI_DECLARATION; diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/subtract_fusion.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/subtract_fusion.hpp new file mode 100644 index 00000000000000..c3b1c8afec6cbf --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/subtract_fusion.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include + +namespace ngraph { +namespace pass { + +class TRANSFORMATIONS_API SubtractFusion; + +} // namespace pass +} // namespace ngraph + +/** + * @ingroup ie_transformation_common_api + * @brief SubtractFusion transformation replaces a sub-graph + * Mul(y, -1) + x or x + Mul(y, -1) with Subtract(x,y) + */ +class ngraph::pass::SubtractFusion : public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + SubtractFusion(); +}; \ No newline at end of file diff --git a/inference-engine/src/transformations/include/transformations/common_optimizations/wrap_interpolate_into_transposes.hpp b/inference-engine/src/transformations/include/transformations/common_optimizations/wrap_interpolate_into_transposes.hpp new file mode 100644 index 00000000000000..e7b2442b255b02 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/common_optimizations/wrap_interpolate_into_transposes.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +#include +#include + +namespace ngraph { +namespace pass { + +class TRANSFORMATIONS_API WrapInterpolateIntoTransposes; + +} // namespace pass +} // namespace ngraph + +/** + * @ingroup ie_transformation_common_api + * @brief WrapInterpolateIntoTransposes transformation replaces + * Interpolate + * with + * Transpose -> Interpolate -> Transpose + * when + * 1) the source Interpolate has the static input rank; + * 2) 'axes' input is a Constant; + * 3) number of axes is equal to input rank minus 2; + * 4) axes contain 0 or 1. + * The reason of this transformation is that now CPU plugin supports interpolation only + * with respect to spatial dimensions, but TensorFlow frontend gives Interpolate with + * axes {1, 2} for 4D tensors. + */ +class ngraph::pass::WrapInterpolateIntoTransposes: public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + WrapInterpolateIntoTransposes(); +}; diff --git a/inference-engine/src/transformations/include/transformations/disable_decompression_convert_constant_folding.hpp b/inference-engine/src/transformations/include/transformations/disable_decompression_convert_constant_folding.hpp new file mode 100644 index 00000000000000..ea9935e10029d0 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/disable_decompression_convert_constant_folding.hpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "transformations_visibility.hpp" +#include "openvino/pass/graph_rewrite.hpp" + +namespace ov { +namespace pass { + +class TRANSFORMATIONS_API DisableDecompressionConvertConstantFolding; + +} // namespace pass +} // namespace ov + +/** + * @ingroup ie_transformation_common_api + * @brief Disables ConstantFolding for Convert operation in compressed function. + */ +class ov::pass::DisableDecompressionConvertConstantFolding : public ov::pass::MatcherPass { +public: + OPENVINO_RTTI("DisableDecompressionConvertConstantFolding", "0"); + DisableDecompressionConvertConstantFolding(); +}; diff --git a/inference-engine/src/transformations/include/transformations/op_conversions/convert_divide.hpp b/inference-engine/src/transformations/include/transformations/op_conversions/convert_divide.hpp index 13158b47ad13f4..b7d66501a06c91 100644 --- a/inference-engine/src/transformations/include/transformations/op_conversions/convert_divide.hpp +++ b/inference-engine/src/transformations/include/transformations/op_conversions/convert_divide.hpp @@ -15,6 +15,7 @@ namespace ngraph { namespace pass { class TRANSFORMATIONS_API ConvertDivide; +class TRANSFORMATIONS_API ConvertDivideWithConstant; } // namespace pass } // namespace ngraph @@ -24,3 +25,9 @@ class ngraph::pass::ConvertDivide: public ngraph::pass::MatcherPass { NGRAPH_RTTI_DECLARATION; ConvertDivide(); }; + +class ngraph::pass::ConvertDivideWithConstant: public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + ConvertDivideWithConstant(); +}; diff --git a/inference-engine/src/transformations/include/transformations/op_conversions/convert_slice_to_strided_slice.hpp b/inference-engine/src/transformations/include/transformations/op_conversions/convert_slice_to_strided_slice.hpp new file mode 100644 index 00000000000000..8ae55a67065510 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/op_conversions/convert_slice_to_strided_slice.hpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include + +namespace ngraph { +namespace pass { + +class TRANSFORMATIONS_API SliceToStridedSlice; + +} // namespace pass +} // namespace ngraph + + +/** + * @ingroup ie_transformation_common_api + * @brief SliceToStridedSlice transformation convert v8::Slice to v1::StridedSlice + */ +class ngraph::pass::SliceToStridedSlice: public ngraph::pass::MatcherPass { +public: + NGRAPH_RTTI_DECLARATION; + SliceToStridedSlice(bool use_shapes); +}; diff --git a/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp b/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp index f8bd5493a6f88d..92a5cbe7da685a 100644 --- a/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp +++ b/inference-engine/src/transformations/include/transformations/rt_info/attributes.hpp @@ -12,11 +12,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -37,5 +39,5 @@ class TRANSFORMATIONS_API Attributes { ngraph::FactoryRegistry m_factory_registry; }; -} // namespace pass -} // namespace ov +} // namespace pass +} // namespace ov diff --git a/inference-engine/src/transformations/include/transformations/rt_info/decompression.hpp b/inference-engine/src/transformations/include/transformations/rt_info/decompression.hpp new file mode 100644 index 00000000000000..18965d1aee26b0 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/rt_info/decompression.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include +#include + +#include "openvino/core/node.hpp" +#include "openvino/core/variant.hpp" +#include "transformations_visibility.hpp" + + +namespace ov { + +TRANSFORMATIONS_API void mark_as_decompression(const std::shared_ptr& node); + +TRANSFORMATIONS_API void unmark_as_decompression(const std::shared_ptr& node); + +TRANSFORMATIONS_API bool is_decompression(const std::shared_ptr& node); + +/** + * @ingroup ie_runtime_attr_api + * @brief Decompression class represents runtime info attribute that marks operation + * as used as decompression for Compressed Only format. + */ +class TRANSFORMATIONS_API Decompression : public VariantImpl { +public: + OPENVINO_RTTI("decompression", "0"); + + Decompression() = default; + + bool visit_attributes(AttributeVisitor& visitor) override { return true; } + + bool is_copyable() const override { return false; } +}; + +} // namespace ov diff --git a/inference-engine/src/transformations/include/transformations/rt_info/disable_fp16_compression.hpp b/inference-engine/src/transformations/include/transformations/rt_info/disable_fp16_compression.hpp new file mode 100644 index 00000000000000..00352928ba2f07 --- /dev/null +++ b/inference-engine/src/transformations/include/transformations/rt_info/disable_fp16_compression.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "openvino/core/node.hpp" +#include "openvino/core/variant.hpp" +#include "transformations_visibility.hpp" + + +namespace ov { + +TRANSFORMATIONS_API void disable_fp16_compression(const std::shared_ptr& node); + +TRANSFORMATIONS_API void enable_fp16_compression(const std::shared_ptr& node); + +TRANSFORMATIONS_API bool fp16_compression_is_disabled(const std::shared_ptr& node); + +/** + * @ingroup ie_runtime_attr_api + * @brief DisableFP16Compression class represents runtime info attribute that marks operation + * as prohibitted to convert to FP16 as part of Compressed Only format. + */ +class TRANSFORMATIONS_API DisableFP16Compression : public VariantImpl { +public: + OPENVINO_RTTI("disable_fp16_compression", "0"); + + DisableFP16Compression() = default; + + bool is_copyable() const override { return false; } +}; + +} // namespace ov diff --git a/inference-engine/src/transformations/include/transformations/utils/utils.hpp b/inference-engine/src/transformations/include/transformations/utils/utils.hpp index b4e4a8e6142505..d6342c28fe138f 100644 --- a/inference-engine/src/transformations/include/transformations/utils/utils.hpp +++ b/inference-engine/src/transformations/include/transformations/utils/utils.hpp @@ -15,10 +15,12 @@ #include #include #include +#include #include #include #include +#include namespace ngraph { namespace op { @@ -49,6 +51,17 @@ bool has_op_with_type(const std::shared_ptr &function) { } return false; } + +inline bool has_decompression_converts(const std::shared_ptr& function) { + for (const auto& op : function->get_ops()) { + if (std::dynamic_pointer_cast(op)) { + if (ov::is_decompression(op)) + return true; + } + } + return false; +} + inline std::string create_ie_output_name(const ngraph::Output& output) { const auto& prev_layer = output.get_node_shared_ptr(); std::string out_name = prev_layer->get_friendly_name(); diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/clamp_fusion.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/clamp_fusion.cpp index 2bd8bb6cd5e39e..93af8683f4b09a 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/clamp_fusion.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/clamp_fusion.cpp @@ -11,9 +11,9 @@ #include #include #include +#include #include "itt.hpp" - NGRAPH_RTTI_DEFINITION(ngraph::pass::ClampFusion, "ClampFusion", 0); ngraph::pass::ClampFusion::ClampFusion() { @@ -21,8 +21,11 @@ ngraph::pass::ClampFusion::ClampFusion() { auto data_pattern = ngraph::pattern::any_input(); auto min_const_pattern = ngraph::pattern::wrap_type(); auto max_const_pattern = ngraph::pattern::wrap_type(); - auto max_pattern = ngraph::pattern::wrap_type({data_pattern, min_const_pattern}, pattern::consumers_count(1)); - auto min_pattern = ngraph::pattern::wrap_type({max_pattern, max_const_pattern}); + auto max_pattern1 = ngraph::pattern::wrap_type({data_pattern, min_const_pattern}, pattern::consumers_count(1)); + auto min_pattern1 = ngraph::pattern::wrap_type({max_pattern1, max_const_pattern}); + auto min_pattern2 = ngraph::pattern::wrap_type({data_pattern, max_const_pattern}); + auto max_pattern2 = ngraph::pattern::wrap_type({min_pattern2, min_const_pattern}, pattern::consumers_count(1)); + auto root = std::make_shared(ngraph::OutputVector{min_pattern1, max_pattern2}); ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) { auto pattern_map = m.get_pattern_value_map(); @@ -42,19 +45,27 @@ ngraph::pass::ClampFusion::ClampFusion() { double max_value = max_const->cast_vector()[0]; auto clamp = register_new_node(data, min_value, max_value); - auto minimum = pattern_map.at(min_pattern); - clamp->set_friendly_name(minimum.get_node()->get_friendly_name()); - copy_runtime_info({ - pattern_map.at(max_pattern).get_node_shared_ptr(), - minimum.get_node_shared_ptr() - }, - clamp); - replace_node(minimum.get_node_shared_ptr(), clamp); + std::shared_ptr root_node; + NodeVector nodes; + auto min_pattern1_it = pattern_map.find(min_pattern1); + if (min_pattern1_it != std::end(pattern_map)) { + root_node = min_pattern1_it->second.get_node_shared_ptr(); + nodes.push_back(pattern_map.at(max_pattern1).get_node_shared_ptr()); + } else { + root_node = pattern_map.at(max_pattern2).get_node_shared_ptr(); + nodes.push_back(pattern_map.at(min_pattern2).get_node_shared_ptr()); + } + nodes.push_back(root_node); + + clamp->set_friendly_name(root_node->get_friendly_name()); + + copy_runtime_info(nodes, clamp); + replace_node(root_node, clamp); return true; }; - auto m = std::make_shared(min_pattern, matcher_name); + auto m = std::make_shared(root, matcher_name); this->register_matcher(m, callback); } diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp index d55ab3ca5ceeb9..7e22faf8b1fd49 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/common_optimizations.cpp @@ -49,6 +49,7 @@ #include "transformations/common_optimizations/strides_optimization.hpp" #include "transformations/common_optimizations/convert_nms_gather_path_to_unsigned.hpp" #include "transformations/common_optimizations/mul_conv_fusion.hpp" +#include "transformations/common_optimizations/convert_compression_only_to_legacy.hpp" #include "transformations/op_conversions/bidirectional_sequences_decomposition.hpp" #include "transformations/op_conversions/convert_pad_to_group_conv.hpp" #include "transformations/op_conversions/convert_divide.hpp" @@ -78,6 +79,7 @@ #include "transformations/op_conversions/gather_normalize_negative_indices.hpp" #include "transformations/op_conversions/convert_deformable_conv_v8_to_v1.hpp" #include "transformations/op_conversions/convert_maxpool_downgrade.hpp" +#include "transformations/disable_decompression_convert_constant_folding.hpp" #include #include @@ -95,10 +97,14 @@ bool ngraph::pass::CommonOptimizations::run_on_function(std::shared_ptr(); + // Disable low_precision_enabled as all plugins handle low-precision sub-graph manually // before CommonOptimization pipeline execution manager.register_pass(true, false); + manager.register_pass(); + // TODO: move to KMB manager.register_pass(); diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/compress_float_constants.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/compress_float_constants.cpp new file mode 100644 index 00000000000000..8133c108a6f85c --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/compress_float_constants.cpp @@ -0,0 +1,125 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/common_optimizations/compress_float_constants.hpp" + +#include "openvino/opsets/opset8.hpp" +#include "ngraph/rt_info.hpp" +#include "openvino/pass/pattern/op/wrap_type.hpp" +#include "transformations/rt_info/decompression.hpp" +#include "transformations/rt_info/disable_fp16_compression.hpp" +#include "transformations/rt_info/old_api_map_attribute.hpp" +#include "itt.hpp" + + +namespace { +template +std::shared_ptr change_constant_precision_to_fp16(std::shared_ptr& constant) { + using src_type = typename ov::element_type_traits::value_type; + + const auto* src_data = constant->get_data_ptr(); + const auto size = ov::shape_size(constant->get_shape()); + + auto new_constant = std::make_shared(ov::element::f16, constant->get_shape()); + auto* dst_data = const_cast(reinterpret_cast(new_constant->get_data_ptr())); + if (dst_data == nullptr) + return nullptr; + + bool is_overflow = false; + for (size_t i = 0; i < size; ++i) { + if (src_data[i] > std::numeric_limits::max()) { + dst_data[i] = std::numeric_limits::max(); + is_overflow = true; + } else if (src_data[i] < std::numeric_limits::lowest()) { + dst_data[i] = std::numeric_limits::lowest(); + is_overflow = true; + } else { + dst_data[i] = static_cast(src_data[i]); + } + } + if (is_overflow) { + std::cerr << "Warning: One or more of the values of the Constant can't fit in the float16 data type." + " Those values were casted to the nearest limit value, the model can produce incorrect results." << std::endl; + } + return new_constant; +} +} // namespace + +ov::pass::CompressFloatConstantsImpl::CompressFloatConstantsImpl() { + MATCHER_SCOPE(CompressFloatConstantsImpl); + auto const_pattern = pattern::wrap_type(); + + ov::matcher_pass_callback callback = [=](pattern::Matcher& m) { + const auto& pattern_map = m.get_pattern_value_map(); + const auto& const_node_pattern = pattern_map.at(const_pattern); + + auto const_node = std::dynamic_pointer_cast( + const_node_pattern.get_node_shared_ptr()); + if (!const_node) + return false; + + if (ov::fp16_compression_is_disabled(const_node)) + return false; + + auto c_type = const_node->get_element_type(); + std::shared_ptr new_const; + if (c_type == ov::element::f32) { + new_const = change_constant_precision_to_fp16(const_node); + } else if (c_type == ov::element::f64) { + new_const = change_constant_precision_to_fp16(const_node); + } else { + return false; + } + auto convert = std::make_shared(new_const, const_node->get_element_type()); + + convert->set_friendly_name(const_node->get_friendly_name()); + ngraph::copy_runtime_info(const_node, convert); + ov::mark_as_decompression(convert); + + ov::replace_node(const_node, convert); + + return true; + }; + + auto m = std::make_shared(const_pattern, matcher_name); + this->register_matcher(m, callback); +} + +ov::pass::AddOldApiMapToParameters::AddOldApiMapToParameters() { + MATCHER_SCOPE(AddOldApiMapToParameters); + auto param_pattern = pattern::wrap_type(); + + ov::matcher_pass_callback callback = [=](pattern::Matcher& m) { + const auto& pattern_map = m.get_pattern_value_map(); + auto node = pattern_map.at(param_pattern).get_node_shared_ptr(); + + auto param_node = std::dynamic_pointer_cast(node); + if (!param_node) + return false; + auto p_type = param_node->get_element_type(); + if (p_type == ov::element::f32 || p_type == ov::element::f64) { + std::vector order; + if (ov::has_old_api_map(node)) { + auto old_api = ov::get_old_api_map(node).get(); + order = old_api.get_order(); + } else { + auto p_rank = param_node->get_partial_shape().rank(); + if (p_rank.is_static()) { + auto r = p_rank.get_length(); + order.resize(r); + std::iota(order.begin(), order.end(), 0); + } else { + return false; + } + } + ov::set_old_api_map(node, ov::OldApiMap(ov::OldApiMapAttr(order, ov::element::Type_t::f16))); + } else { + return false; + } + return true; + }; + + auto m = std::make_shared(param_pattern, matcher_name); + this->register_matcher(m, callback); +} diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/conv_bias_fusion.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/conv_bias_fusion.cpp index 4dddec4adab9fb..2cec36d7bf5e1f 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/conv_bias_fusion.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/conv_bias_fusion.cpp @@ -99,7 +99,7 @@ bool conv_callback(ngraph::pattern::Matcher &m) { auto expected_shape = Shape(output_rank, 1); expected_shape[1] = channel_dim; - if (op::util::check_for_broadcast(expected_shape, const_shape)) { + if (ngraph::op::util::check_for_broadcast(expected_shape, const_shape)) { return false; } @@ -107,7 +107,7 @@ bool conv_callback(ngraph::pattern::Matcher &m) { // the number of weights dimensions. Output final_const = m_const; if (is_scalar_multiplier) { - final_const = op::util::broadcastTo(m_const, expected_shape); + final_const = ngraph::op::util::broadcastTo(m_const, expected_shape); } if (final_const.get_shape().size() > 1) { diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/convert_compression_only_to_legacy.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/convert_compression_only_to_legacy.cpp new file mode 100644 index 00000000000000..4725e64e5ff81b --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/convert_compression_only_to_legacy.cpp @@ -0,0 +1,52 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/common_optimizations/convert_compression_only_to_legacy.hpp" + +#include "transformations/convert_precision.hpp" +#include "transformations/utils/utils.hpp" +#include "openvino/opsets/opset8.hpp" +#include "openvino/pass/manager.hpp" +#include "itt.hpp" + +using namespace ov; + +bool ov::pass::ConvertPrecisionCompressedOnly::run_on_function(std::shared_ptr f) { + if (ngraph::op::util::has_decompression_converts(f)) { + const precisions_array convert_precision_list{ + {ov::element::f32, ov::element::f16} + }; + auto convert_precision = ngraph::pass::ConvertPrecision(convert_precision_list); + return convert_precision.run_on_function(f); + } + return false; +} + +ov::pass::EnableDecompressionConvertConstantFolding::EnableDecompressionConvertConstantFolding() { + MATCHER_SCOPE(EnableDecompressionConvertConstantFolding); + auto convert = pattern::wrap_type(); + + ov::matcher_pass_callback callback = [=](pattern::Matcher& m) { + const auto& node = m.get_match_root(); + if (!ov::is_decompression(node)) + return false; + enable_constant_folding(node); + return true; + }; + + auto m = std::make_shared(convert, matcher_name); + this->register_matcher(m, callback); +} + +bool ov::pass::ConvertCompressedOnlyToLegacy::run_on_function(std::shared_ptr f) { + Manager manager(get_pass_config()); + + manager.register_pass(); + manager.register_pass(); + manager.register_pass(); + + manager.run_passes(f); + + return false; +} diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/divide_fusion.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/divide_fusion.cpp new file mode 100644 index 00000000000000..adba32ad57ffdb --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/divide_fusion.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/common_optimizations/divide_fusion.hpp" + +#include +#include +#include +#include + +#include "itt.hpp" +#include "transformations/utils/utils.hpp" + +NGRAPH_RTTI_DEFINITION(ngraph::pass::DivideFusion, "DivideFusion", 0); + +ngraph::pass::DivideFusion::DivideFusion() { + MATCHER_SCOPE(DivideFusion); + auto p_pow_input = pattern::any_input(); + auto p_pow_const = pattern::wrap_type(); + auto p_pow = pattern::wrap_type({p_pow_input, p_pow_const}); + auto p_mul_input = pattern::any_input(); + auto p_mul = ngraph::pattern::wrap_type({p_mul_input, p_pow}); + + matcher_pass_callback callback = [=](pattern::Matcher &m) { + const auto & pattern_to_output = m.get_pattern_value_map(); + const auto & minuend_input = pattern_to_output.at(p_mul_input); + const auto & subtrahend_input = pattern_to_output.at(p_pow_input); + const auto & mul = pattern_to_output.at(p_mul).get_node_shared_ptr(); + const auto & pow = pattern_to_output.at(p_pow).get_node_shared_ptr(); + const auto & minus_one = pattern_to_output.at(p_pow_const).get_node_shared_ptr(); + + auto minus_one_const = std::dynamic_pointer_cast(minus_one); + if (!minus_one_const || !op::util::has_constant_value(minus_one_const, -1.)) { + return false; + } + + auto div = register_new_node(minuend_input, subtrahend_input); + div->set_friendly_name(mul->get_friendly_name()); + copy_runtime_info({mul, pow}, div); + replace_node(mul, div); + return true; + }; + + auto m = std::make_shared(p_mul, matcher_name); + register_matcher(m, callback); +} diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/mark_precision_sensitive_subgraphs.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/mark_precision_sensitive_subgraphs.cpp new file mode 100644 index 00000000000000..c31181edfcab3d --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/mark_precision_sensitive_subgraphs.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/common_optimizations/mark_precision_sensitive_subgraphs.hpp" + +#include +#include + +#include "transformations/utils/utils.hpp" +#include "transformations/rt_info/disable_fp16_compression.hpp" +#include "openvino/opsets/opset1.hpp" +#include "openvino/opsets/opset3.hpp" +#include "openvino/opsets/opset8.hpp" +#include "openvino/pass/pattern/op/wrap_type.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" + +using namespace std; + +namespace { +void visit_shape_path(const shared_ptr& node, unordered_set>& visited) { + if (!node) + return; + visited.insert(node); + deque> nodes{ node }; + while (!nodes.empty()) { + auto curr_node = nodes.front(); + nodes.pop_front(); + // Do not check if already visited + if (ov::is_type(curr_node) || ov::is_type(curr_node)) { + continue; + } + visited.insert(curr_node); + if (ov::is_type(curr_node)) { + ov::disable_fp16_compression(curr_node); + } else { + for (auto& input_value : curr_node->input_values()) { + // continue searching + const auto& input_node = input_value.get_node_shared_ptr(); + nodes.push_front(input_node); + } + } + } +} +} // namespace + +bool ov::pass::MarkPrecisionSensitiveSubgraphs::run_on_function(std::shared_ptr f) { + deque> nodes; + unordered_set> visited; + for (auto& r : f->get_results()) + nodes.push_back(r); + for (auto& r : f->get_sinks()) + nodes.emplace_back(r); + + while (!nodes.empty()) { + auto curr_node = nodes.front(); + nodes.pop_front(); + if (visited.count(curr_node)) + continue; + for (auto& input : curr_node->inputs()) { + if (ov::is_precision_sensitive(input)) + visit_shape_path(input.get_source_output().get_node_shared_ptr(), visited); + } + visited.insert(curr_node); + + for (auto& input_value : curr_node->input_values()) { + // continue searching + const auto& input_node = input_value.get_node_shared_ptr(); + nodes.push_front(input_node); + } + } + return true; +} diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/moc_transformations.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/moc_transformations.cpp index 781e0d972fa584..88f68a22082205 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/moc_transformations.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/moc_transformations.cpp @@ -48,7 +48,10 @@ #include #include #include -#include "transformations/common_optimizations/split_concat_pair_to_interpolate_fusion.hpp" +#include +#include +#include +#include NGRAPH_RTTI_DEFINITION(ngraph::pass::MOCTransformations, "MOCTransformations", 0); @@ -76,7 +79,10 @@ bool ngraph::pass::MOCTransformations::run_on_function(std::shared_ptr(); manager.register_pass(); - manager.register_pass(); + // FusedFilteringBoxesBySize transformation has the complex pattern + // which can be affected by further transformations. So we have to + // execute it at the beginning of the pipeline. + manager.register_pass(); manager.register_pass(); manager.register_pass(); if (!m_use_shapes) { @@ -85,9 +91,7 @@ bool ngraph::pass::MOCTransformations::run_on_function(std::shared_ptr(); - if (m_use_shapes) { - manager.register_pass(); - } + manager.register_pass(m_use_shapes); manager.register_pass(); @@ -122,6 +126,8 @@ bool ngraph::pass::MOCTransformations::run_on_function(std::shared_ptradd_matcher(); common_fusions->add_matcher(); common_fusions->add_matcher(m_use_shapes); + common_fusions->add_matcher(); + common_fusions->add_matcher(); common_fusions->set_name("ngraph::pass::CommonFusions"); manager.register_pass(); @@ -129,6 +135,7 @@ bool ngraph::pass::MOCTransformations::run_on_function(std::shared_ptr(); decomp->add_matcher(); + decomp->add_matcher(); manager.register_pass(); diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/optimize_strided_slice.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/optimize_strided_slice.cpp index f7b92fb031548b..37511260ae4741 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/optimize_strided_slice.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/optimize_strided_slice.cpp @@ -6,11 +6,15 @@ #include #include "itt.hpp" +#include "transformations/op_conversions/convert_slice_to_strided_slice.hpp" + #include #include #include +#include #include + NGRAPH_RTTI_DEFINITION(ngraph::pass::StridedSliceOptimization, "StridedSliceOptimization", 0); NGRAPH_RTTI_DEFINITION(ngraph::pass::UselessStridedSliceEraser, "UselessStridedSliceEraser", 0); @@ -245,10 +249,21 @@ bool ngraph::pass::GroupedStridedSliceOptimizer::run_on_function(std::shared_ptr return graph_rewritten; } +ngraph::pass::StridedSliceOptimization::StridedSliceOptimization(bool use_shapes) { + m_use_shapes = use_shapes; +} + bool ngraph::pass::StridedSliceOptimization::run_on_function(std::shared_ptr f) { RUN_ON_FUNCTION_SCOPE(StridedSliceOptimization); - bool rewritten = UselessStridedSliceEraser().run_on_function(f); - rewritten |= SharedStridedSliceEraser().run_on_function(f); - rewritten |= GroupedStridedSliceOptimizer().run_on_function(f); + ngraph::pass::Manager manager(get_pass_config()); + manager.register_pass(m_use_shapes); + manager.run_passes(f); + + bool rewritten = false; + if (m_use_shapes) { + rewritten = UselessStridedSliceEraser().run_on_function(f); + rewritten |= SharedStridedSliceEraser().run_on_function(f); + rewritten |= GroupedStridedSliceOptimizer().run_on_function(f); + } return rewritten; } diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/pull_transpose_through_fq.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/pull_transpose_through_fq.cpp index d07dda95face24..d4f61e7e728ae4 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/pull_transpose_through_fq.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/pull_transpose_through_fq.cpp @@ -11,12 +11,14 @@ #include #include #include +#include NGRAPH_RTTI_DEFINITION(ngraph::pass::PullTransposeThroughFQUp, "PullTransposeThroughFQUp", 0); ngraph::pass::PullTransposeThroughFQUp::PullTransposeThroughFQUp() { MATCHER_SCOPE(PullTransposeThroughFQUp); - auto m_fq = pattern::wrap_type({pattern::any_input(pattern::has_static_rank()), + const auto weights = ngraph::pattern::wrap_type(); + auto m_fq = pattern::wrap_type({weights, pattern::any_input(pattern::has_static_shape()), pattern::any_input(pattern::has_static_shape()), pattern::any_input(pattern::has_static_shape()), @@ -59,7 +61,7 @@ ngraph::pass::PullTransposeThroughFQUp::PullTransposeThroughFQUp() { opset1::Constant::create(element::i64, Shape{unsqueeze_axes.size()}, unsqueeze_axes)); new_ops.push_back(fq_input.get_node_shared_ptr()); } - fq_input = transpose->clone_with_new_inputs({fq_input, transpose->input_value(1)}); + fq_input = op::util::make_try_fold(fq_input, transpose->input_value(1)); ngraph::copy_runtime_info(transpose, fq_input.get_node_shared_ptr()); fq_inputs.push_back(fq_input); } diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/remove_filtering_boxes_by_size.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/remove_filtering_boxes_by_size.cpp index 8772858d2653cd..734d0fe3b992af 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/remove_filtering_boxes_by_size.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/remove_filtering_boxes_by_size.cpp @@ -8,11 +8,19 @@ #include #include +#include #include "transformations/common_optimizations/remove_filtering_boxes_by_size.hpp" +#include "transformations/common_optimizations/subtract_fusion.hpp" +NGRAPH_RTTI_DEFINITION(ngraph::pass::FuseFilteringBoxesBySize, "FuseFilteringBoxesBySize", 0); NGRAPH_RTTI_DEFINITION(ngraph::pass::RemoveFilteringBoxesBySize, "RemoveFilteringBoxesBySize", 0); +ngraph::pass::FuseFilteringBoxesBySize::FuseFilteringBoxesBySize() { + add_matcher(); + add_matcher(); +} + ngraph::pass::RemoveFilteringBoxesBySize::RemoveFilteringBoxesBySize() { MATCHER_SCOPE(RemoveFilteringBoxesBySize); // variadic split @@ -85,9 +93,9 @@ ngraph::pass::RemoveFilteringBoxesBySize::RemoveFilteringBoxesBySize() { auto start = opset3::Constant::create(element::i64, Shape{}, std::vector({0})); auto step = opset3::Constant::create(element::i64, Shape{}, std::vector({1})); - auto pattern_map = m.get_pattern_map(); + const auto & pattern_map = m.get_pattern_map(); - auto input = pattern_map[data]; + auto input = pattern_map.at(data); auto output = m.get_match_root(); auto input_shape = std::make_shared(input); diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/subtract_fusion.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/subtract_fusion.cpp new file mode 100644 index 00000000000000..1dfa3590b9e489 --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/subtract_fusion.cpp @@ -0,0 +1,60 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/common_optimizations/subtract_fusion.hpp" + +#include +#include +#include +#include +#include + +#include "itt.hpp" +#include "transformations/utils/utils.hpp" + +NGRAPH_RTTI_DEFINITION(ngraph::pass::SubtractFusion, "SubtractFusion", 0); + +ngraph::pass::SubtractFusion::SubtractFusion() { + MATCHER_SCOPE(SubtractFusion); + auto p_input = pattern::any_input(); + + auto p_mul_const = pattern::wrap_type(); + auto p_mul = pattern::wrap_type({p_input, p_mul_const}); + + auto p_neg = pattern::wrap_type({p_input}); + + auto p_mul_or_neg = std::make_shared(OutputVector({p_mul, p_neg})); + + auto p_add_input = pattern::any_input(); + auto p_add = ngraph::pattern::wrap_type({p_add_input, p_mul_or_neg}); + + matcher_pass_callback callback = [=](pattern::Matcher &m) { + const auto & pattern_to_output = m.get_pattern_value_map(); + const auto & minuend_input = pattern_to_output.at(p_add_input); + const auto & subtrahend_input = pattern_to_output.at(p_input); + + const auto & add = pattern_to_output.at(p_add).get_node_shared_ptr(); + + NodeVector nodes_to_replace{add}; + + if (pattern_to_output.count(p_mul_const)) { + auto minus_one_const = std::dynamic_pointer_cast(pattern_to_output.at(p_mul_const).get_node_shared_ptr()); + if (!op::util::has_constant_value(minus_one_const, -1.)) { + return false; + } + nodes_to_replace.emplace_back(pattern_to_output.at(p_mul).get_node_shared_ptr()); + } else { + nodes_to_replace.emplace_back(pattern_to_output.at(p_neg).get_node_shared_ptr()); + } + + auto sub = register_new_node(minuend_input, subtrahend_input); + sub->set_friendly_name(add->get_friendly_name()); + copy_runtime_info(nodes_to_replace, sub); + replace_node(add, sub); + return true; + }; + + auto m = std::make_shared(p_add, matcher_name); + register_matcher(m, callback); +} diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/transpose_sinking.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/transpose_sinking.cpp index f5b62cd7c9cb87..d72d15d19baa28 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/transpose_sinking.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/transpose_sinking.cpp @@ -63,7 +63,7 @@ std::shared_ptr get_reversed_order_constant(const std: ngraph::pass::TransposeReduction::TransposeReduction() { MATCHER_SCOPE(TransposeReduction); - auto transpose_label = pattern::wrap_type({pattern::any_input(), pattern::wrap_type()}); + auto transpose_label = pattern::wrap_type({pattern::any_input(), pattern::wrap_type()}, pattern::consumers_count(1)); auto reduce_or_squeeze_label = pattern::wrap_type( {transpose_label, pattern::wrap_type()}); diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/wrap_interpolate_into_transposes.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/wrap_interpolate_into_transposes.cpp new file mode 100644 index 00000000000000..3b74ce1cefb47d --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/wrap_interpolate_into_transposes.cpp @@ -0,0 +1,95 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "itt.hpp" +#include "transformations/common_optimizations/wrap_interpolate_into_transposes.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace { +std::vector reverse_permutation(const std::vector& perm) { + if (perm.empty()) return {}; + + std::vector result(perm.size()); + for (int64_t i = 0; i < static_cast(perm.size()); ++i) { + result[perm[i]] = i; + } + + return result; +} + +std::vector build_transposition_for_axes(const std::vector& axes, size_t input_rank) { + std::set non_interpolated_axes_set; + for (size_t i = 0; i < input_rank; ++i) { + non_interpolated_axes_set.insert(static_cast(i)); + } + for (const auto& axis : axes) { + non_interpolated_axes_set.erase(axis); + } + std::vector result(non_interpolated_axes_set.begin(), non_interpolated_axes_set.end()); + result.insert(result.end(), axes.begin(), axes.end()); + + return result; +} + +std::vector build_new_axes(size_t num_of_axes, size_t rank) { + std::vector result(num_of_axes); + std::iota(result.begin(), result.end(), static_cast(rank - num_of_axes)); + return result; +} +} // namespace + +NGRAPH_RTTI_DEFINITION(ngraph::pass::WrapInterpolateIntoTransposes, "WrapInterpolateIntoTransposes", 0); + +ngraph::pass::WrapInterpolateIntoTransposes::WrapInterpolateIntoTransposes() { + MATCHER_SCOPE(WrapInterpolateIntoTransposes); + auto interpolate_pattern = ov::pass::pattern::wrap_type(); + ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher& m) { + auto interpolate = std::dynamic_pointer_cast(m.get_match_root()); + if (!interpolate || interpolate->get_input_partial_shape(0).rank().is_dynamic() || interpolate->inputs().size() != 4) return false; + + int64_t input_rank = interpolate->get_input_partial_shape(0).rank().get_length(); + // If the input rank is equal to 1 or 2, then such Interpolate is supported by MKLDNN. + if (input_rank < 3) return false; + + auto axes_node = std::dynamic_pointer_cast(interpolate->input_value(3).get_node_shared_ptr()); + if (!axes_node) return false; + + const auto axes = axes_node->cast_vector(); + if (static_cast(axes.size()) > input_rank - 2 || + std::all_of(axes.begin(), axes.end(), [](int64_t axis){ return axis != 0 && axis != 1; })) { + return false; + } + + const auto first_perm = build_transposition_for_axes(axes, input_rank); + const auto last_perm = reverse_permutation(first_perm); + + auto first_transpose_perm = ov::opset8::Constant::create(element::i64, {first_perm.size()}, first_perm); + auto first_transpose = std::make_shared(interpolate->input_value(0), first_transpose_perm); + auto new_axes = build_new_axes(axes.size(), input_rank); + auto new_axes_node = ov::opset8::Constant::create(element::i64, {new_axes.size()}, new_axes); + auto new_interpolate = interpolate->clone_with_new_inputs({first_transpose, interpolate->input_value(1), interpolate->input_value(2), new_axes_node}); + auto last_transpose_perm = ov::opset8::Constant::create(element::i64, {last_perm.size()}, last_perm); + auto last_transpose = std::make_shared(new_interpolate, last_transpose_perm); + + last_transpose->set_friendly_name(interpolate->get_friendly_name()); + copy_runtime_info(interpolate, {first_transpose_perm, first_transpose, new_axes_node, new_interpolate, last_transpose_perm, last_transpose}); + replace_node(interpolate, last_transpose); + + return true; + }; + + auto m = std::make_shared(interpolate_pattern, matcher_name); + register_matcher(m, callback); +} diff --git a/inference-engine/src/transformations/src/transformations/disable_decompression_convert_constant_folding.cpp b/inference-engine/src/transformations/src/transformations/disable_decompression_convert_constant_folding.cpp new file mode 100644 index 00000000000000..3b6af212327bf6 --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/disable_decompression_convert_constant_folding.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/disable_decompression_convert_constant_folding.hpp" + +#include "openvino/opsets/opset8.hpp" +#include "openvino/pass/pattern/op/wrap_type.hpp" +#include "transformations/rt_info/disable_constant_folding.hpp" +#include "transformations/rt_info/decompression.hpp" +#include "itt.hpp" + +ov::pass::DisableDecompressionConvertConstantFolding::DisableDecompressionConvertConstantFolding() { + MATCHER_SCOPE(DisableDecompressionConvertConstantFolding); + auto convert = pattern::wrap_type(); + + ov::matcher_pass_callback callback = [=](pattern::Matcher& m) { + const auto& node = m.get_match_root(); + if (!ov::is_decompression(node)) + return false; + disable_constant_folding(node); + return true; + }; + + auto m = std::make_shared(convert, matcher_name); + this->register_matcher(m, callback); +} diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_divide.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_divide.cpp index 03aa5025861b08..07c3624839b4fe 100644 --- a/inference-engine/src/transformations/src/transformations/op_conversions/convert_divide.cpp +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_divide.cpp @@ -11,31 +11,65 @@ #include #include #include +#include +#include NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertDivide, "ConvertDivide", 0); +NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertDivideWithConstant, "ConvertDivideWithConstant", 0); + +namespace { +bool convert_divide(std::shared_ptr node) { + auto div = std::dynamic_pointer_cast(node); + // We can not apply this transformation in case with integer input data type + if (!div || div->get_input_element_type(0).is_integral() + || div->get_input_element_type(1).is_integral()) { + return false; + } + + ngraph::Output pow = std::make_shared(div->input_value(1), + ngraph::op::Constant::create(div->get_input_element_type(1), ngraph::Shape{}, {-1})); + + if (std::dynamic_pointer_cast(div->get_input_node_shared_ptr(1))) { + if (auto const_pow = ngraph::get_constant_from_source(pow)) { + pow = const_pow; + } else { + NGRAPH_DEBUG << "ConvertDivide has failed due to unsupported evaluate type in " << pow.get_node(); + return false; + } + } else { + ngraph::copy_runtime_info(div, pow.get_node_shared_ptr()); + } + + auto mul = std::make_shared(div->input(0).get_source_output(), pow); + + mul->set_friendly_name(div->get_friendly_name()); + ngraph::copy_runtime_info(div, mul); + ngraph::replace_node(div, mul); + return true; +} +} // namespace ngraph::pass::ConvertDivide::ConvertDivide() { MATCHER_SCOPE(ConvertDivide); auto div = ngraph::pattern::wrap_type(); ngraph::matcher_pass_callback callback = [](pattern::Matcher& m) { - auto div = std::dynamic_pointer_cast (m.get_match_root()); - // We can not apply this transformation in case with integer input data type - if (!div || div->input(0).get_element_type().is_integral()) { - return false; - } + return convert_divide(m.get_match_root()); + }; - auto pow = std::make_shared(div->input(1).get_source_output(), - op::Constant::create(div->get_input_element_type(1), Shape{}, {-1})); + auto m = std::make_shared(div, matcher_name); + this->register_matcher(m, callback); +} - auto mul = std::make_shared(div->input(0).get_source_output(), pow); +ngraph::pass::ConvertDivideWithConstant::ConvertDivideWithConstant() { + MATCHER_SCOPE(ConvertDivideWithConstant); + auto div = ngraph::pattern::wrap_type( + {pattern::any_input(), pattern::wrap_type()}); - mul->set_friendly_name(div->get_friendly_name()); - ngraph::copy_runtime_info(div, {pow, mul}); - ngraph::replace_node(div, mul); - return true; + ngraph::matcher_pass_callback callback = [](pattern::Matcher& m) { + return convert_divide(m.get_match_root()); }; auto m = std::make_shared(div, matcher_name); this->register_matcher(m, callback); -} +} \ No newline at end of file diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_slice_to_strided_slice.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_slice_to_strided_slice.cpp new file mode 100644 index 00000000000000..f0a1e0b6c468ca --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_slice_to_strided_slice.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include +#include +#include + +#include "transformations/op_conversions/convert_slice_to_strided_slice.hpp" +#include "transformations/utils/utils.hpp" +#include "ngraph/node.hpp" +#include "ngraph/op/constant.hpp" +#include "ngraph/op/util/op_types.hpp" +#include "ngraph/validation_util.hpp" + +#include "itt.hpp" + +using namespace ngraph; + +NGRAPH_RTTI_DEFINITION(ngraph::pass::SliceToStridedSlice, "SliceToStridedSlice", 0); + +namespace { + Output align_indices(const Output& indices, + const Output& slice_axes, + const Output& scatter_axis, + size_t slice_indices_length, + int64_t fill_in_value, + NodeVector& new_ops) { + // Handle a case when starts/ends/steps lengths are less than provided axes + // in order to ensure compatibility with `StridedSlice:v1` interface + // Example: + // data_shape: {3, 3, 3, 3} + // starts: [1, 1] - after extending --> [0, 0, 1, 1] + // ends: [2, 2] - after extending --> [0, 0, 2, 2] + // steps : [1, 1] - after extending --> [1, 1, 1, 1] + // axes: [2, 3] - apply slice values to 2 and 3 dimension of input data + // expected_output_shape: {3, 3, 1, 1} + + const auto default_indices = ngraph::opset8::Constant::create(indices.get_element_type(), Shape{slice_indices_length}, {fill_in_value}); + std::shared_ptr adjusted_indices = ngraph::op::util::make_try_fold( + default_indices, + slice_axes, + indices, // updates + scatter_axis); + + if (!ngraph::op::is_constant(adjusted_indices)) { + new_ops.push_back(default_indices); + } + return adjusted_indices; +} + +std::vector axes_to_mask(const std::vector& axes, size_t slice_indices_length) { + std::vector mask(slice_indices_length, 1); + for (auto axis : axes) { + mask[axis] = 0; + } + return mask; +} + +} // namespace + +ngraph::pass::SliceToStridedSlice::SliceToStridedSlice(bool use_shapes) { + MATCHER_SCOPE(SliceToStridedSlice); + auto slice = pattern::wrap_type(); + ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) { + auto slice_node = std::dynamic_pointer_cast(m.get_match_root()); + if (!slice_node) + return false; + + if (slice_node->get_input_size() < 4) + return false; + + auto arg = slice_node->input_value(0); + + std::shared_ptr start_const; + std::shared_ptr stop_const; + std::shared_ptr step_const; + + if (use_shapes) { + start_const = get_constant_from_source(slice_node->input_value(1)); + stop_const = get_constant_from_source(slice_node->input_value(2)); + step_const = get_constant_from_source(slice_node->input_value(3)); + } else { + start_const = std::dynamic_pointer_cast(slice_node->input_value(1).get_node_shared_ptr()); + stop_const = std::dynamic_pointer_cast(slice_node->input_value(2).get_node_shared_ptr()); + step_const = std::dynamic_pointer_cast(slice_node->input_value(3).get_node_shared_ptr()); + } + + auto start_input = start_const ? start_const : slice_node->input_value(1); + auto stop_input = stop_const ? stop_const : slice_node->input_value(2); + auto step_input = step_const ? step_const : slice_node->input_value(3); + + std::shared_ptr axes_const; + if (slice_node->get_input_size() > 4) { + axes_const = use_shapes ? get_constant_from_source(slice_node->input_value(4)) + : std::dynamic_pointer_cast(slice_node->input_value(4).get_node_shared_ptr()); + } else { + axes_const = slice_node->get_default_const_axes(start_input); + } + if (!axes_const) + return false; + + const auto& data_shape = slice_node->get_input_partial_shape(0); + auto axes_vec = axes_const->cast_vector(); + if (data_shape.rank().is_static()) { + auto norm_axes_vec = normalize_axes(slice_node->get_friendly_name(), axes_vec, data_shape.rank()); + axes_vec = std::vector(norm_axes_vec.begin(), norm_axes_vec.end()); + } else { + const bool need_normalization = std::any_of(axes_vec.begin(), + axes_vec.end(), + [](int64_t axis) { + return axis < 0; + }); + if (need_normalization) + return false; + } + const size_t slice_indices_length = *std::max_element(std::begin(axes_vec), std::end(axes_vec)) + 1; + const auto begin_end_mask = axes_to_mask(axes_vec, slice_indices_length); + + const bool are_axes_sorted = std::is_sorted(axes_vec.begin(), axes_vec.end()); + const bool are_indices_aligned = are_axes_sorted && (axes_vec.size() == slice_indices_length); + + NodeVector new_ops; + if (!are_indices_aligned) { + const auto scatter_axis = opset8::Constant::create(element::i32, Shape{1}, {0}); + const auto slice_axes = opset8::Constant::create(element::i64, Shape{axes_vec.size()}, axes_vec); + new_ops.insert(new_ops.end(), {scatter_axis, slice_axes}); + + start_input = align_indices(start_input, slice_axes, scatter_axis, slice_indices_length, 0, new_ops); + stop_input = align_indices(stop_input, slice_axes, scatter_axis, slice_indices_length, 0, new_ops); + step_input = align_indices(step_input, slice_axes, scatter_axis, slice_indices_length, 1, new_ops); + } + new_ops.insert(new_ops.end(), {start_input.get_node_shared_ptr(), stop_input.get_node_shared_ptr(), step_input.get_node_shared_ptr()}); + + const auto strided_slice = std::make_shared(arg, start_input, stop_input, step_input, begin_end_mask, begin_end_mask); + new_ops.push_back(strided_slice); + + strided_slice->set_friendly_name(slice_node->get_friendly_name()); + ngraph::copy_runtime_info(slice_node, new_ops); + ngraph::replace_node(slice_node, strided_slice); + return true; + }; + + auto m = std::make_shared(slice, matcher_name); + register_matcher(m, callback); +} diff --git a/inference-engine/src/transformations/src/transformations/rt_info/attributes.cpp b/inference-engine/src/transformations/src/transformations/rt_info/attributes.cpp index 26c42ab0fbceb5..910788d6c43ef9 100644 --- a/inference-engine/src/transformations/src/transformations/rt_info/attributes.cpp +++ b/inference-engine/src/transformations/src/transformations/rt_info/attributes.cpp @@ -8,10 +8,12 @@ ov::pass::Attributes::Attributes() { register_factory>(); register_factory(); register_factory(); + register_factory(); register_factory(); register_factory(); register_factory(); register_factory(); + register_factory(); } ov::Variant* ov::pass::Attributes::create_by_type_info(const ov::DiscreteTypeInfo& type_info) { diff --git a/inference-engine/src/transformations/src/transformations/rt_info/decompression.cpp b/inference-engine/src/transformations/src/transformations/rt_info/decompression.cpp new file mode 100644 index 00000000000000..01b45f2bfaba67 --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/rt_info/decompression.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/rt_info/decompression.hpp" + +void ov::mark_as_decompression(const std::shared_ptr& node) { + auto& rt_info = node->get_rt_info(); + rt_info[Decompression::get_type_info_static()] = std::make_shared(); +} + +void ov::unmark_as_decompression(const std::shared_ptr& node) { + auto& rt_info = node->get_rt_info(); + rt_info.erase(Decompression::get_type_info_static()); +} + +bool ov::is_decompression(const std::shared_ptr& node) { + const auto& rt_info = node->get_rt_info(); + return rt_info.count(Decompression::get_type_info_static()); +} diff --git a/inference-engine/src/transformations/src/transformations/rt_info/disable_fp16_compression.cpp b/inference-engine/src/transformations/src/transformations/rt_info/disable_fp16_compression.cpp new file mode 100644 index 00000000000000..79513ddf2b7158 --- /dev/null +++ b/inference-engine/src/transformations/src/transformations/rt_info/disable_fp16_compression.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "transformations/rt_info/disable_fp16_compression.hpp" + +void ov::disable_fp16_compression(const std::shared_ptr& node) { + auto& rt_info = node->get_rt_info(); + rt_info[DisableFP16Compression::get_type_info_static()] = std::make_shared(); +} + +void ov::enable_fp16_compression(const std::shared_ptr& node) { + auto& rt_info = node->get_rt_info(); + rt_info.erase(DisableFP16Compression::get_type_info_static()); +} + +bool ov::fp16_compression_is_disabled(const std::shared_ptr& node) { + const auto& rt_info = node->get_rt_info(); + return rt_info.count(DisableFP16Compression::get_type_info_static()); +} diff --git a/inference-engine/src/vpu/common/CMakeLists.txt b/inference-engine/src/vpu/common/CMakeLists.txt index d8b55be48257e8..6b9800394cb2ad 100644 --- a/inference-engine/src/vpu/common/CMakeLists.txt +++ b/inference-engine/src/vpu/common/CMakeLists.txt @@ -33,7 +33,7 @@ function(add_common_target TARGET_NAME STATIC_IE) target_include_directories(${TARGET_NAME} PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/include") + $) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC $ @@ -58,6 +58,8 @@ function(add_common_target TARGET_NAME STATIC_IE) if(NOT STATIC_IE) target_link_libraries(${TARGET_NAME} PUBLIC inference_engine_legacy) endif() + + ov_install_static_lib(${TARGET_NAME} myriad) endfunction() add_common_target("vpu_common_lib" FALSE) diff --git a/inference-engine/src/vpu/common/include/vpu/configuration/options/ir_with_scales_directory.hpp b/inference-engine/src/vpu/common/include/vpu/configuration/options/vpu_scales_option.hpp similarity index 85% rename from inference-engine/src/vpu/common/include/vpu/configuration/options/ir_with_scales_directory.hpp rename to inference-engine/src/vpu/common/include/vpu/configuration/options/vpu_scales_option.hpp index e4ed56fd0d51fd..e1736aa88f6f4f 100644 --- a/inference-engine/src/vpu/common/include/vpu/configuration/options/ir_with_scales_directory.hpp +++ b/inference-engine/src/vpu/common/include/vpu/configuration/options/vpu_scales_option.hpp @@ -19,8 +19,8 @@ enum class Category; class PluginConfiguration; -struct IRWithScalesDirectoryOption : public AsParameterEnabler { - using value_type = std::string; +struct VPUScalesOption : public AsParameterEnabler { + using value_type = std::map; static std::string key(); static void validate(const std::string&); diff --git a/inference-engine/src/vpu/common/include/vpu/private_plugin_config.hpp b/inference-engine/src/vpu/common/include/vpu/private_plugin_config.hpp index 78f1964e0804bb..97791374cab149 100644 --- a/inference-engine/src/vpu/common/include/vpu/private_plugin_config.hpp +++ b/inference-engine/src/vpu/common/include/vpu/private_plugin_config.hpp @@ -21,7 +21,7 @@ DECLARE_VPU_CONFIG(MYRIAD_TILING_CMX_LIMIT_KB); DECLARE_VPU_CONFIG(MYRIAD_TENSOR_STRIDES); -DECLARE_VPU_CONFIG(MYRIAD_IR_WITH_SCALES_DIRECTORY); +DECLARE_VPU_CONFIG(MYRIAD_SCALES_PATTERN); DECLARE_VPU_CONFIG(MYRIAD_DETECT_NETWORK_BATCH); DECLARE_VPU_CONFIG(MYRIAD_COPY_OPTIMIZATION); DECLARE_VPU_CONFIG(MYRIAD_HW_INJECT_STAGES); diff --git a/inference-engine/src/vpu/common/src/configuration/options/ir_with_scales_directory.cpp b/inference-engine/src/vpu/common/src/configuration/options/ir_with_scales_directory.cpp deleted file mode 100644 index 42037bdc9f0769..00000000000000 --- a/inference-engine/src/vpu/common/src/configuration/options/ir_with_scales_directory.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "vpu/private_plugin_config.hpp" -#include "vpu/configuration/options/ir_with_scales_directory.hpp" -#include "vpu/utils/containers.hpp" -#include "vpu/configuration/plugin_configuration.hpp" - -namespace vpu { - -void IRWithScalesDirectoryOption::validate(const std::string& value) {} - -void IRWithScalesDirectoryOption::validate(const PluginConfiguration& configuration) { - validate(configuration[key()]); -} - -std::string IRWithScalesDirectoryOption::key() { - return InferenceEngine::MYRIAD_IR_WITH_SCALES_DIRECTORY; -} - -details::Access IRWithScalesDirectoryOption::access() { - return details::Access::Private; -} - -details::Category IRWithScalesDirectoryOption::category() { - return details::Category::CompileTime; -} - -std::string IRWithScalesDirectoryOption::defaultValue() { - return std::string(); -} - -IRWithScalesDirectoryOption::value_type IRWithScalesDirectoryOption::parse(const std::string& value) { - return value; -} - -} // namespace vpu diff --git a/inference-engine/src/vpu/common/src/configuration/options/vpu_scales_option.cpp b/inference-engine/src/vpu/common/src/configuration/options/vpu_scales_option.cpp new file mode 100644 index 00000000000000..0c67f1c99cac2f --- /dev/null +++ b/inference-engine/src/vpu/common/src/configuration/options/vpu_scales_option.cpp @@ -0,0 +1,75 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "vpu/private_plugin_config.hpp" +#include "vpu/configuration/options/vpu_scales_option.hpp" +#include "vpu/utils/containers.hpp" +#include "vpu/configuration/plugin_configuration.hpp" + +#if defined(__GNUC__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 9) && !defined(__clang__) && !defined(IE_GCC_4_8) +# define IE_GCC_4_8 +#else +# include +#endif + +namespace vpu { + +void VPUScalesOption::validate(const std::string& value) {} + +void VPUScalesOption::validate(const PluginConfiguration& configuration) { + validate(configuration[key()]); +} + +std::string VPUScalesOption::key() { + return InferenceEngine::MYRIAD_SCALES_PATTERN; +} + +details::Access VPUScalesOption::access() { + return details::Access::Private; +} + +details::Category VPUScalesOption::category() { + return details::Category::CompileTime; +} + +std::string VPUScalesOption::defaultValue() { + return std::string(); +} + +VPUScalesOption::value_type VPUScalesOption::parse(const std::string& value) { + value_type vpuScaleMap; + #ifdef IE_GCC_4_8 + VPU_THROW_UNLESS(value.empty(), "It is not possible to parse the 'scale' value from the config because you are using a gcc version less than 4.9."); + #else + std::vector parsedStrings; + + auto delimiterToken = std::regex(";"); + auto regexScales = std::sregex_token_iterator(value.begin(), value.end(), delimiterToken, -1); + std::sregex_token_iterator end; + for ( ; regexScales != end; ++regexScales) { + parsedStrings.push_back(*regexScales); + } + + for (auto& paramStr : parsedStrings) { + paramStr.erase( + std::remove_if(paramStr.begin(), paramStr.end(), ::isspace), + paramStr.end()); + } + + parsedStrings.erase( + std::remove_if(parsedStrings.begin(), parsedStrings.end(), + [](std::string str) { return str.empty(); }), + parsedStrings.end()); + for (const auto& vpuScale : parsedStrings) { + const auto delimeterPos = vpuScale.find(':'); + VPU_THROW_UNLESS(delimeterPos != std::string::npos, "Unable to parse string \"{}\"", vpuScale); + vpuScaleMap.insert({std::string(vpuScale.substr(0, delimeterPos)), + std::stof(vpuScale.substr(delimeterPos + 1))}); + } + + #endif + return vpuScaleMap; +} + +} // namespace vpu diff --git a/inference-engine/src/vpu/graph_transformer/CMakeLists.txt b/inference-engine/src/vpu/graph_transformer/CMakeLists.txt index 8fdae7418b4174..4bcf6c3295b269 100644 --- a/inference-engine/src/vpu/graph_transformer/CMakeLists.txt +++ b/inference-engine/src/vpu/graph_transformer/CMakeLists.txt @@ -38,7 +38,7 @@ function(add_graph_transformer_target TARGET_NAME STATIC_IE) target_include_directories(${TARGET_NAME} PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/include") + $) target_include_directories(${TARGET_NAME} PUBLIC @@ -67,6 +67,7 @@ function(add_graph_transformer_target TARGET_NAME STATIC_IE) if(NOT STATIC_IE) add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME} CUSTOM_FILTERS "+runtime/explicit") openvino_developer_export_targets(COMPONENT inference_engine_vpu TARGETS ${TARGET_NAME}) + ov_install_static_lib(${TARGET_NAME} myriad) endif() set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) diff --git a/inference-engine/src/vpu/graph_transformer/src/frontend/unroll_loops.cpp b/inference-engine/src/vpu/graph_transformer/src/frontend/unroll_loops.cpp index 219c92a5772d82..1b86921fe7086e 100644 --- a/inference-engine/src/vpu/graph_transformer/src/frontend/unroll_loops.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/frontend/unroll_loops.cpp @@ -11,7 +11,7 @@ #include -#include +#include #include #include @@ -25,7 +25,7 @@ void FrontEnd::unrollLoops(ie::CNNNetwork& network) { env.log->trace("Unroll TensorIterator loops"); VPU_LOGGER_SECTION(env.log); - if (!env.config.get().empty()) { + if (!env.config.get().empty()) { // TODO: Scale dumps does not work with IR, which contain Tensor Iterator layers, because we cannot serialize them. #-23429 for (auto iterator = ie::details::CNNNetworkIterator(network); iterator != ie::details::CNNNetworkIterator(); ++iterator) { const auto& layer = *iterator; diff --git a/inference-engine/src/vpu/graph_transformer/src/graph_transformer.cpp b/inference-engine/src/vpu/graph_transformer/src/graph_transformer.cpp index c82a75515d0bd6..b23d401a09ff85 100644 --- a/inference-engine/src/vpu/graph_transformer/src/graph_transformer.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/graph_transformer.cpp @@ -50,7 +50,7 @@ #include #include #include -#include +#include namespace vpu { @@ -173,11 +173,6 @@ CompiledGraph::Ptr compileImpl(const ie::CNNNetwork& network, const std::shared_ middleEnd->run(model); - if (!env.config.get().empty()) { - network.serialize(env.config.get() + "/" + network.getName() + "_scales.xml", - env.config.get() + "/" + network.getName() + "_scales.bin"); - } - return backEnd->build(model, frontEnd->origLayers()); } diff --git a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/weights_analysis.cpp b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/weights_analysis.cpp index f29432aeaff56e..5caf439fa16737 100644 --- a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/weights_analysis.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/weights_analysis.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include @@ -28,6 +28,17 @@ #include #include +#if defined(__GNUC__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 9) && !defined(__clang__) && !defined(IE_GCC_4_8) +# define IE_GCC_4_8 +#endif + +#ifndef IE_GCC_4_8 +# include +# define STD_REGEX_SEARCH(SRC, PATTERN) std::regex_search(SRC, std::regex(PATTERN)) +#else +# define STD_REGEX_SEARCH(SRC, PATTERN) false +#endif + namespace vpu { namespace { @@ -206,6 +217,16 @@ void scaleWeightableStage(const Model& model, const Stage& stage, float factor) stage->attrs().set("scaleFactor", factor); } +float getScaleValue(const std::string layerName, const std::map& vpuScalemap) { + float scaleForAnyLayer = 0.0; + for (const auto& pair : vpuScalemap) { + if (STD_REGEX_SEARCH(layerName, pair.first)) { + return pair.second; + } + } + return scaleForAnyLayer; +} + class PassImpl final : public Pass { public: void run(const Model& model) override; @@ -227,9 +248,9 @@ void PassImpl::run(const Model& model) { continue; } IE_ASSERT(stage->origLayer() != nullptr); - - // Get scale from IR, compute if it was absent - auto scale = stage->origLayer()->GetParamAsFloat("vpu_scale", 0); + // Get scale from config, compute if it was absent + const auto map = env.config.get(); + auto scale = getScaleValue(stage->origLayerName(), map); if (!scale) { auto weights = stage->input(1); @@ -260,10 +281,6 @@ void PassImpl::run(const Model& model) { if (shift >= scaleThreshold) { scale = static_cast(1ULL << static_cast(shift)); } - - if (!env.config.get().empty()) { - stage->origLayer()->params["vpu_scale"] = toString(scale); - } } scaleWeightableStage(model, stage, scale); } diff --git a/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp b/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp index 1136f71f345803..6b6f88ab25ca09 100644 --- a/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp +++ b/inference-engine/src/vpu/myriad_plugin/myriad_plugin.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include @@ -208,7 +208,7 @@ Engine::Engine(std::shared_ptr mvnc) : _parsedConfig.registerOption(); _parsedConfig.registerOption(); _parsedConfig.registerOption(); - _parsedConfig.registerOption(); + _parsedConfig.registerOption(); _parsedConfig.registerOption(); _parsedConfig.registerOption(); _parsedConfig.registerOption(); diff --git a/inference-engine/tests/functional/inference_engine/CMakeLists.txt b/inference-engine/tests/functional/inference_engine/CMakeLists.txt index a107a133ca8b42..1aed4b84b0eea7 100644 --- a/inference-engine/tests/functional/inference_engine/CMakeLists.txt +++ b/inference-engine/tests/functional/inference_engine/CMakeLists.txt @@ -4,7 +4,7 @@ set(TARGET_NAME ieFuncTests) -set(INCLUDES ${IE_MAIN_SOURCE_DIR}/src/inference_engine/src) +set(INCLUDES $/src) set(LINK_LIBRARIES gmock @@ -123,32 +123,44 @@ function(ie_headers_compilation_with_custom_flags) cmake_parse_arguments(IE_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(IE_TEST_PLUGIN_API) - set(IE_TEST_INCLUDE_DIRECTORY - $) + set(include_dirs + "${OpenVINO_SOURCE_DIR}/inference-engine/src/plugin_api/") else() - set(IE_TEST_INCLUDE_DIRECTORY - $) + set(include_dirs + "${OpenVINO_SOURCE_DIR}/ngraph/core/include" + "${OpenVINO_SOURCE_DIR}/inference-engine/src/inference_engine/include/ie" + "${OpenVINO_SOURCE_DIR}/inference-engine/src/inference_engine/include/") endif() - file(GLOB_RECURSE header_files RELATIVE "${IE_TEST_INCLUDE_DIRECTORY}" - "${IE_TEST_INCLUDE_DIRECTORY}/*") + foreach(include_dir IN LISTS include_dirs) + file(GLOB_RECURSE header_files_local RELATIVE "${include_dir}" "${include_dir}/*.hpp") + list(APPEND header_files ${header_files_local}) + endforeach() if(NOT IE_TEST_CXX_STANDARD) set(IE_TEST_CXX_STANDARD ${CMAKE_CXX_STANDARD}) endif() if(NOT IE_TEST_PLUGIN_API) + list(APPEND IE_TEST_HEADERS_TO_SKIP "_tbl.hpp") if(NOT OPENCL_HEADERS_DIR) list(APPEND IE_TEST_HEADERS_TO_SKIP "gpu/gpu_ocl_wrapper.hpp" "gpu/gpu_context_api_ocl.hpp" "gpu/gpu_context_api_va.hpp" - "gpu/gpu_context_api_dx.hpp") + "gpu/gpu_context_api_dx.hpp" + "gpu/gpu_ocl_wrapper.hpp" + "openvino/runtime/gpu/ocl/ocl_wrapper.hpp" + "openvino/runtime/gpu/ocl/ocl.hpp" + "openvino/runtime/gpu/ocl/va.hpp" + "openvino/runtime/gpu/ocl/dx.hpp") endif() if(NOT WIN32) - list(APPEND IE_TEST_HEADERS_TO_SKIP "gpu/gpu_context_api_dx.hpp") + list(APPEND IE_TEST_HEADERS_TO_SKIP "gpu/gpu_context_api_dx.hpp" + "openvino/runtime/gpu/ocl/dx.hpp") endif() if(NOT LIBVA_FOUND) - list(APPEND IE_TEST_HEADERS_TO_SKIP "gpu/gpu_context_api_va.hpp") + list(APPEND IE_TEST_HEADERS_TO_SKIP "gpu/gpu_context_api_va.hpp" + "openvino/runtime/gpu/ocl/va.hpp") endif() endif() @@ -157,7 +169,7 @@ function(ie_headers_compilation_with_custom_flags) # skip user-passed headers set(skip_current_file OFF) foreach(skip_file IN LISTS IE_TEST_HEADERS_TO_SKIP) - if(header_file STREQUAL skip_file) + if("${header_file}" MATCHES "${skip_file}") set(skip_current_file ON) endif() endforeach() @@ -187,8 +199,7 @@ function(ie_headers_compilation_with_custom_flags) $ $) target_include_directories(${target_name} PRIVATE - $ - $) + $) else() # OpenCL headers if any if(OPENCL_HEADERS_DIR) @@ -233,12 +244,19 @@ endfunction() ie_headers_compilation_with_custom_flags(TEST_SUFFIX Cxx17 CXX_STANDARD 17) +if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) + ie_headers_compilation_with_custom_flags(TEST_SUFFIX Cxx20 + CXX_STANDARD 20) +endif() + if(UNIX) if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") ie_headers_compilation_with_custom_flags(TEST_SUFFIX WarningsAreErrors FLAGS -Wremarks -Wcheck -Werror-all -Werror -Wall) - else() - ie_headers_compilation_with_custom_flags(TEST_SUFFIX Pedantic FLAGS -Wpedantic) + elseif(BUILD_SHARED_LIBS) + # fix warnings wit RTTI + # ie_headers_compilation_with_custom_flags(TEST_SUFFIX Pedantic + # FLAGS -Wpedantic) endif() else() ie_headers_compilation_with_custom_flags(TEST_SUFFIX WindowsAreErrors @@ -260,14 +278,21 @@ endif() ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiCxx17 CXX_STANDARD 17 PLUGIN_API) +if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) + ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiCxx20 + CXX_STANDARD 20 PLUGIN_API) +endif() + if(UNIX) if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiWarningsAreErrors FLAGS -Werror-all -Werror -Wall PLUGIN_API) - else() - ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiPedantic FLAGS -Wpedantic - PLUGIN_API) + elseif(BUILD_SHARED_LIBS) + # fix warnings wit RTTI + # ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiPedantic + # FLAGS -Wpedantic + # PLUGIN_API) endif() else() ie_headers_compilation_with_custom_flags(TEST_SUFFIX PluginApiWindowsAreErrors diff --git a/inference-engine/tests/functional/inference_engine/core_threading.cpp b/inference-engine/tests/functional/inference_engine/core_threading.cpp index c59e3538bbce90..5540fc933dbfbe 100644 --- a/inference-engine/tests/functional/inference_engine/core_threading.cpp +++ b/inference-engine/tests/functional/inference_engine/core_threading.cpp @@ -87,6 +87,9 @@ TEST_F(CoreThreadingTests, RegisterPlugin) { }, 4000); } +// TODO: CVS-68982 +#ifndef OPENVINO_STATIC_LIBRARY + // tested function: RegisterPlugins TEST_F(CoreThreadingTests, RegisterPlugins) { InferenceEngine::Core ie; @@ -123,6 +126,8 @@ TEST_F(CoreThreadingTests, RegisterPlugins) { }, 1000); } +#endif // !OPENVINO_STATIC_LIBRARY + // tested function: GetAvailableDevices, UnregisterPlugin // TODO: some initialization (e.g. thread/dlopen) sporadically fails during such stress-test scenario TEST_F(CoreThreadingTests, DISABLED_GetAvailableDevices) { diff --git a/inference-engine/tests/functional/inference_engine/executable_network.cpp b/inference-engine/tests/functional/inference_engine/executable_network.cpp index 89653bdc5ee7f1..3ca191b529dcf6 100644 --- a/inference-engine/tests/functional/inference_engine/executable_network.cpp +++ b/inference-engine/tests/functional/inference_engine/executable_network.cpp @@ -35,13 +35,6 @@ TEST(ExecutableNetworkTests, throwsOnUninitializedGetExecGraphInfo) { ASSERT_THROW(exec.GetExecGraphInfo(), InferenceEngine::NotAllocated); } -TEST(ExecutableNetworkTests, throwsOnUninitializedQueryState) { - IE_SUPPRESS_DEPRECATED_START - ExecutableNetwork exec; - ASSERT_THROW(exec.QueryState(), InferenceEngine::NotAllocated); - IE_SUPPRESS_DEPRECATED_END -} - TEST(ExecutableNetworkTests, throwsOnUninitializedSetConfig) { ExecutableNetwork exec; ASSERT_THROW(exec.SetConfig({{}}), InferenceEngine::NotAllocated); diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/custom_ops.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/custom_ops.cpp index c5f779aebb7417..e5e130dbb0361c 100644 --- a/inference-engine/tests/functional/inference_engine/ir_serialization/custom_ops.cpp +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/custom_ops.cpp @@ -11,6 +11,7 @@ #include "common_test_utils/file_utils.hpp" #include "common_test_utils/ngraph_test_utils.hpp" #include "ie_core.hpp" +#include "openvino/runtime/core.hpp" #include "ngraph/ngraph.hpp" #include "transformations/serialize.hpp" @@ -27,6 +28,11 @@ static std::string get_extension_path() { {}, std::string("template_extension") + IE_BUILD_POSTFIX); } +static std::string get_ov_extension_path() { + return FileUtils::makePluginLibraryName( + {}, std::string("template_ov_extension") + IE_BUILD_POSTFIX); +} + class CustomOpsSerializationTest : public ::testing::Test { protected: std::string test_name = @@ -158,3 +164,25 @@ TEST_F(CustomOpsSerializationTest, CustomOpNoExtensions) { ASSERT_TRUE(success) << message; } + +TEST_F(CustomOpsSerializationTest, CustomOpOVExtensions) { + const std::string model = CommonTestUtils::getModelFromTestModelZoo( + IR_SERIALIZATION_MODELS_PATH "custom_identity.xml"); + + ov::runtime::Core core; + core.add_extension(get_ov_extension_path()); + auto expected = core.read_model(model); + ngraph::pass::Manager manager; + manager.register_pass( + m_out_xml_path, m_out_bin_path, + ngraph::pass::Serialize::Version::IR_V10); + manager.run_passes(expected); + auto result = core.read_model(m_out_xml_path, m_out_bin_path); + + bool success; + std::string message; + std::tie(success, message) = + compare_functions(result, expected, true, false, false, true, true); + + ASSERT_TRUE(success) << message; +} diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/models/custom_identity.xml b/inference-engine/tests/functional/inference_engine/ir_serialization/models/custom_identity.xml new file mode 100644 index 00000000000000..e7ae6bc8374a9f --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/models/custom_identity.xml @@ -0,0 +1,51 @@ + + + + + + + + + 2 + 2 + 2 + 1 + + + + + + + + 2 + 2 + 2 + 1 + + + + + 2 + 2 + 2 + 1 + + + + + + + 2 + 2 + 2 + 1 + + + + + + + + + + diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp index ad74c2bcb7842f..76cd2c7f9917ac 100644 --- a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_deserialization.cpp @@ -35,8 +35,8 @@ class RTInfoDeserialization : public testing::Test { std::istringstream modelStringStream(model); std::istream& modelStream = modelStringStream; - ngraph::frontend::FrontEnd::Ptr FE; - ngraph::frontend::InputModel::Ptr inputModel; + ov::frontend::FrontEnd::Ptr FE; + ov::frontend::InputModel::Ptr inputModel; ov::VariantVector params{ov::make_variant(&modelStream)}; @@ -51,7 +51,7 @@ class RTInfoDeserialization : public testing::Test { } private: - ngraph::frontend::FrontEndManager manager; + ov::frontend::FrontEndManager manager; }; TEST_F(RTInfoDeserialization, NodeV10) { @@ -553,6 +553,75 @@ TEST_F(RTInfoDeserialization, NodeV11) { } } +TEST_F(RTInfoDeserialization, NodeV11MultipleRTKeys) { + std::string model = R"V0G0N( + + + + + + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + + + + + + + + 1 + 3 + 22 + 22 + + + + + 1 + 3 + 22 + 22 + + + + + + + + + + 1 + 3 + 22 + 22 + + + + + + + + + +)V0G0N"; + ASSERT_ANY_THROW(getWithIRFrontend(model)); +} + TEST_F(RTInfoDeserialization, InputAndOutputV11) { std::string model = R"V0G0N( diff --git a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp index a851b27026f2e0..8b6841f1772566 100644 --- a/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp +++ b/inference-engine/tests/functional/inference_engine/ir_serialization/rt_info_serialization.cpp @@ -30,8 +30,8 @@ class RTInfoSerializationTest : public CommonTestUtils::TestsCommon { std::shared_ptr getWithIRFrontend(const std::string& model_path, const std::string& weights_path) { - ngraph::frontend::FrontEnd::Ptr FE; - ngraph::frontend::InputModel::Ptr inputModel; + ov::frontend::FrontEnd::Ptr FE; + ov::frontend::InputModel::Ptr inputModel; ov::VariantVector params{ov::make_variant(model_path), ov::make_variant(weights_path)}; @@ -46,7 +46,7 @@ class RTInfoSerializationTest : public CommonTestUtils::TestsCommon { } private: - ngraph::frontend::FrontEndManager manager; + ov::frontend::FrontEndManager manager; }; TEST_F(RTInfoSerializationTest, all_attributes_latest) { @@ -57,6 +57,7 @@ TEST_F(RTInfoSerializationTest, all_attributes_latest) { std::make_shared("priority"); info[ov::OldApiMap::get_type_info_static()] = std::make_shared( ov::OldApiMapAttr(std::vector{0, 2, 3, 1}, ngraph::element::Type_t::f32)); + info[ov::Decompression::get_type_info_static()] = std::make_shared(); }; std::shared_ptr function; @@ -100,6 +101,11 @@ TEST_F(RTInfoSerializationTest, all_attributes_latest) { auto old_api_map_attr_val = old_api_map_attr->get(); ASSERT_EQ(old_api_map_attr_val.get_order(), std::vector({0, 2, 3, 1})); ASSERT_EQ(old_api_map_attr_val.get_type(), ngraph::element::Type_t::f32); + + const std::string& dkey = ov::Decompression::get_type_info_static(); + ASSERT_TRUE(info.count(dkey)); + auto decompression_attr = std::dynamic_pointer_cast(info.at(dkey)); + ASSERT_TRUE(decompression_attr); }; auto add = f->get_results()[0]->get_input_node_ptr(0); diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/add_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/add_transformation.cpp index 88b133ad116271..ce2e69043e499b 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/add_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/add_transformation.cpp @@ -931,6 +931,28 @@ const std::vector testValues = { }, "" }, + // float path without subtract + { + false, + -1, + LayerTransformation::createParamsU8I8(), + { + ngraph::element::f32, + { }, + ngraph::element::u8, + { {ngraph::element::f32}, {}, { 4.f }}, + { } + }, + { + ngraph::element::f32, + { {ngraph::element::f32}, {}, { 0.25f } }, + ngraph::element::u8, + { }, + { {}, {}, { 4.f }}, + { } + }, + "" + }, }; INSTANTIATE_TEST_SUITE_P( diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/concat_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/concat_transformation.cpp index 64e71691075a20..3483d37fed1c3f 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/concat_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/concat_transformation.cpp @@ -967,7 +967,7 @@ const std::vector testValues = { { {element::f32}, {}, { 0.01f } }, } }, - // unexpected quantization levels, concat + // INT4+INT8 quantization levels, concat { LayerTransformation::createParamsU8I8(), false, @@ -990,16 +990,16 @@ const std::vector testValues = { ngraph::element::f32, {}, }, - false, + true, false, }, - // unexpected quantization levels, concat multi channels + // INT4+INT8 quantization levels, concat multi channels { LayerTransformation::createParamsU8I8(), true, 1, { - { 16ul, {}, {0.f}, {1.5f}, {0.f}, {15.f} }, + { 16ul, {}, {0.f}, {1.5f}, {0.f}, {1.5f} }, {}, {}, { 256ul, {}, {0.f}, {2.55f}, {0.f}, {2.55f} }, @@ -1007,16 +1007,16 @@ const std::vector testValues = { {} }, { - { 16ul, {}, {0.f}, {1.5f}, {0.f}, {15.f} }, - {}, + {16ul, {}, {0.f}, {1.5f}, {0.f}, {15.f}, ngraph::element::u8}, {}, - { 256ul, {}, {0.f}, {2.55f}, {0.f}, {2.55f} }, {}, + {256ul, {}, {0.f}, {2.55f}, {0.f}, {255.f}, ngraph::element::u8}, {}, - ngraph::element::f32, {}, + ngraph::element::u8, + { ngraph::element::f32, {}, {{ 0.1f, 0.1f, 0.1f, 0.01f, 0.01f, 0.01f }} } }, - false, + true, false } }; diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/fake_quantize_transformation.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/fake_quantize_transformation.cpp index 0e292336291a1c..f4e808bfd53bf4 100644 --- a/inference-engine/tests/functional/inference_engine/lp_transformations/fake_quantize_transformation.cpp +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/fake_quantize_transformation.cpp @@ -244,11 +244,22 @@ const std::vector fakeQuantizeTransformati { LayerTransformation::createParamsU8I8AndI8(), { 256ul, {}, { 0.f }, { 25.5f }, { -1.0686283872061019e-38 }, { 1.0686283872061019e-38 } }, - { 256ul, {}, { 0.f }, { 25.5f }, { 0.f }, { 255.f } }, + { 256ul, {}, { 0.f }, { 25.5f }, { -128.f }, { 127.f } }, + ngraph::element::i8, + { + { ngraph::element::f32, {{ngraph::element::f32}, {}, { 1e-32f }} }, + { ngraph::element::f16, {{ngraph::element::f16}, {}, { 1e-32f }} } + } + }, + // denormal values + { + LayerTransformation::createParamsU8I8AndI8(), + { 256ul, {}, { 0.f }, { 25.5f }, { 0.0 }, { 1.0686283872061019e-38 } }, + { 256ul, {}, { 0.f }, { 25.5f }, { 0.0 }, { 255 } }, ngraph::element::u8, { - { ngraph::element::f32, {{ngraph::element::f32}, { 127.5 }, { 1e-32f }} }, - { ngraph::element::f16, {{ngraph::element::f16}, { 127.5 }, { 1e-32f }} } + { ngraph::element::f32, {{ngraph::element::f32}, {}, { 1e-32f }} }, + { ngraph::element::f16, {{ngraph::element::f16}, {}, { 1e-32f }} } } }, // U16 @@ -311,6 +322,28 @@ const std::vector fakeQuantizeTransformati // { ngraph::element::f16, { {ngraph::element::f16}, {}, { {0.01f, 0.1f, 1.f} }} } // } //}, + // u4 through u8 + { + LayerTransformation::createParamsU8I8(), + { 16ul, {}, { 0.f }, { 1.5f }, { 0.f }, { 1.5f } }, + { 16ul, {}, { 0.f }, { 1.5f }, { 0.f }, { 15.f } }, + ngraph::element::u8, + { + { ngraph::element::f32, { {ngraph::element::f32}, {}, { 0.1f }} }, + { ngraph::element::f16, { {ngraph::element::f16}, {}, { 0.1f }} } + } + }, + // i4 through i8 + { + LayerTransformation::createParamsI8I8(), + { 16ul, {}, { -0.8f }, { 0.7f }, { -0.8f }, { 0.7f } }, + { 16ul, {}, { -0.8f }, { 0.7f }, { -8.f }, { 7.f } }, + ngraph::element::i8, + { + { ngraph::element::f32, {{ngraph::element::f32}, { }, { 0.1f }} }, + { ngraph::element::f16, {{ngraph::element::f16}, { }, { 0.1f }} } + } + }, }; INSTANTIATE_TEST_SUITE_P( diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/is_asymmetric_on_weights_dequantization.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/is_asymmetric_on_weights_dequantization.cpp new file mode 100644 index 00000000000000..e5caba16f00faa --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/is_asymmetric_on_weights_dequantization.cpp @@ -0,0 +1,128 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "layer_transformation.hpp" + +#include +#include +#include + +#include + +#include +#include +#include +#include "lpt_ngraph_functions/convolution_function.hpp" + +using namespace testing; +using namespace ngraph; +using namespace ngraph::pass; + +class IsAsymmetricOnWeightsDequantizationTestValues { +public: + ngraph::element::Type precisionBeforeDequantization; + ngraph::builder::subgraph::DequantizationOperations dequantizationOnActivations; + std::shared_ptr weights; + builder::subgraph::DequantizationOperations dequantizationOnWeights; + bool isAsymmetricOnWeights; +}; + +typedef std::tuple< + element::Type, + ngraph::PartialShape, + IsAsymmetricOnWeightsDequantizationTestValues> IsAsymmetricOnWeightsDequantizationParams; + +class IsAsymmetricOnWeightsDequantizationTransformation : + public LayerTransformation, + public testing::WithParamInterface { +public: + void SetUp() override { + const auto netPrecision = std::get<0>(GetParam()); + const auto inputShape = std::get<1>(GetParam()); + auto testValues = std::get<2>(GetParam()); + + actualFunction = ngraph::builder::subgraph::ConvolutionFunction::getOriginal( + netPrecision, + testValues.precisionBeforeDequantization, + inputShape, + testValues.dequantizationOnActivations, + testValues.weights, + {}, + testValues.dequantizationOnWeights); + } + + static std::string getTestCaseName(testing::TestParamInfo obj) { + const auto netPrecision = std::get<0>(obj.param); + auto inputShape = std::get<1>(obj.param); + IsAsymmetricOnWeightsDequantizationTestValues testValues = std::get<2>(obj.param); + + std::ostringstream result; + result << + netPrecision << "_" << + inputShape << "_" << + testValues.precisionBeforeDequantization << "_" << + testValues.dequantizationOnActivations << "_" << "_weights_" << + testValues.weights->get_element_type() << "_" << "{ " << + testValues.weights->cast_vector()[0] << " }_" << + testValues.dequantizationOnWeights; + return result.str(); + } +}; + +TEST_P(IsAsymmetricOnWeightsDequantizationTransformation, CompareFunctions) { + actualFunction->validate_nodes_and_infer_types(); + + const auto convolutions = LayerTransformation::get(actualFunction); + ASSERT_TRUE(convolutions.size() == 1ul) << "convolution was not found"; + + IsAsymmetricOnWeightsDequantizationTestValues testValues = std::get<2>(GetParam()); + + const auto isAsymmetricOnWeights = ngraph::pass::low_precision::WeightableLayerTransformation::isAsymmetricOnWeights(convolutions[0]); + ASSERT_EQ(testValues.isAsymmetricOnWeights, isAsymmetricOnWeights); +} + +const std::vector netPrecisions = { + element::f32 +}; + +const std::vector suitablePartialShapes = { + ngraph::PartialShape({ 1, 3, 72, 48 }), + ngraph::PartialShape({ 4, 3, 72, 48 }), + ngraph::PartialShape({ Dimension::dynamic(), 3, 72, 48 }), + ngraph::PartialShape({ 1, 3, Dimension::dynamic(), Dimension::dynamic() }), +}; + +const std::vector testValues = { + { + ngraph::element::u8, + {{ngraph::element::f32}, { 128.f }, { 0.02f }}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }), + { + {ngraph::element::f32}, + {{1, 2, 3, 4, 5, 6}, ngraph::element::f32, {6, 1, 1, 1}}, + {{1, 2, 3, 4, 5, 6}, ngraph::element::f32, {6, 1, 1, 1}} + }, + true + }, + { + ngraph::element::u8, + {{ngraph::element::f32}, { 128.f }, { 0.02f }}, + op::Constant::create(ngraph::element::i8, ngraph::Shape{}, std::vector{ 2.f }), + { + {ngraph::element::f32}, + {{0, 0, 1.e-7, 0, 0, 0}, ngraph::element::f32, {6, 1, 1, 1}}, + {{1, 2, 3, 4, 5, 6}, ngraph::element::f32, {6, 1, 1, 1}} + }, + false + } +}; + +INSTANTIATE_TEST_SUITE_P( + smoke_LPT, + IsAsymmetricOnWeightsDequantizationTransformation, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(suitablePartialShapes), + ::testing::ValuesIn(testValues)), + IsAsymmetricOnWeightsDequantizationTransformation::getTestCaseName); diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/is_asymmetric_on_weights_fq.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/is_asymmetric_on_weights_fq.cpp new file mode 100644 index 00000000000000..78bd7aa548320c --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/is_asymmetric_on_weights_fq.cpp @@ -0,0 +1,136 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "layer_transformation.hpp" + +#include +#include +#include + +#include + +#include +#include +#include +#include "lpt_ngraph_functions/convolution_function.hpp" + +using namespace testing; +using namespace ngraph; +using namespace ngraph::pass; + +class IsAsymmetricOnWeightsFakeQuantizeTestValues { +public: + ngraph::element::Type precisionBeforeDequantization; + ngraph::builder::subgraph::DequantizationOperations dequantizationOnActivations; + std::shared_ptr weights; + builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights; +}; + +typedef std::tuple< + element::Type, + ngraph::PartialShape, + IsAsymmetricOnWeightsFakeQuantizeTestValues, + std::pair, bool> > IsAsymmetricOnWeightsFakeQuantizeParams; + +class IsAsymmetricOnWeightsFakeQuantizeTransformation : + public LayerTransformation, + public testing::WithParamInterface { +public: + void SetUp() override { + const auto netPrecision = std::get<0>(GetParam()); + const auto inputShape = std::get<1>(GetParam()); + auto testValues = std::get<2>(GetParam()); + std::pair, bool> transposeAndIsAsymmetricOnWeights = std::get<3>(GetParam()); + + actualFunction = ngraph::builder::subgraph::ConvolutionFunction::getOriginal( + netPrecision, + testValues.precisionBeforeDequantization, + inputShape, + testValues.dequantizationOnActivations, + testValues.weights, + testValues.fakeQuantizeOnWeights, + {}, + transposeAndIsAsymmetricOnWeights.first[0], + transposeAndIsAsymmetricOnWeights.first[1], + transposeAndIsAsymmetricOnWeights.first[2], + transposeAndIsAsymmetricOnWeights.first[3], + transposeAndIsAsymmetricOnWeights.first[4]); + } + + static std::string getTestCaseName(testing::TestParamInfo obj) { + const auto netPrecision = std::get<0>(obj.param); + auto inputShape = std::get<1>(obj.param); + IsAsymmetricOnWeightsFakeQuantizeTestValues testValues = std::get<2>(obj.param); + std::pair, bool> transposeAndIsAsymmetricOnWeights = std::get<3>(obj.param); + + std::ostringstream result; + result << + netPrecision << "_" << + inputShape << "_" << + testValues.precisionBeforeDequantization << "_" << + testValues.dequantizationOnActivations << "_" << "_weights_" << + testValues.weights->get_element_type() << "_" << "{ " << + testValues.weights->cast_vector()[0] << " }_" << + testValues.fakeQuantizeOnWeights << "_" << + transposeAndIsAsymmetricOnWeights.first[0] << "_" << + transposeAndIsAsymmetricOnWeights.first[1] << "_" << + transposeAndIsAsymmetricOnWeights.first[2] << "_" << + transposeAndIsAsymmetricOnWeights.first[3] << "_" << + transposeAndIsAsymmetricOnWeights.first[4]; + return result.str(); + } +}; + +TEST_P(IsAsymmetricOnWeightsFakeQuantizeTransformation, CompareFunctions) { + actualFunction->validate_nodes_and_infer_types(); + + const auto convolutions = LayerTransformation::get(actualFunction); + ASSERT_TRUE(convolutions.size() == 1ul) << "convolution was not found"; + + const auto isAsymmetricOnWeights = ngraph::pass::low_precision::WeightableLayerTransformation::isAsymmetricOnWeights(convolutions[0]); + std::pair, bool> transposeAndIsAsymmetricOnWeights = std::get<3>(GetParam()); + ASSERT_EQ(transposeAndIsAsymmetricOnWeights.second, isAsymmetricOnWeights); +} + +const std::vector netPrecisions = { + element::f32 +}; + +const std::vector suitablePartialShapes = { + ngraph::PartialShape({ 1, 3, 72, 48 }), + ngraph::PartialShape({ 4, 3, 72, 48 }), + ngraph::PartialShape({ Dimension::dynamic(), 3, 72, 48 }), + ngraph::PartialShape({ 1, 3, Dimension::dynamic(), Dimension::dynamic() }), +}; + +const std::vector testValues = { + { + ngraph::element::u8, + {{ngraph::element::f32}, { 128.f }, { 0.02f }}, + op::Constant::create(ngraph::element::f32, ngraph::Shape{}, std::vector{ 2.f }), + { 255ul, Shape({ 1, 1, 1, 1 }), { 0.f }, { 254.f }, { -1.f }, { 1.27f } }, + } +}; + +const std::vector, bool> > transposeFlags = { + // asymmetric quantization + {{false, false, false, false, false}, true}, + {{true, false, false, false, false}, true}, + + // not supported FakeQuantize + {{false, true, false, false, false}, false}, + {{false, false, true, false, false}, false}, + {{false, false, false, true, false}, false}, + {{false, false, false, false, true}, false} +}; + +INSTANTIATE_TEST_SUITE_P( + smoke_LPT, + IsAsymmetricOnWeightsFakeQuantizeTransformation, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(suitablePartialShapes), + ::testing::ValuesIn(testValues), + ::testing::ValuesIn(transposeFlags)), + IsAsymmetricOnWeightsFakeQuantizeTransformation::getTestCaseName); diff --git a/inference-engine/tests/functional/inference_engine/lp_transformations/lpt_avoid_shapeof_propagation_test.cpp b/inference-engine/tests/functional/inference_engine/lp_transformations/lpt_avoid_shapeof_propagation_test.cpp new file mode 100644 index 00000000000000..a49749405fd741 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/lp_transformations/lpt_avoid_shapeof_propagation_test.cpp @@ -0,0 +1,734 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include + +#include "low_precision/add.hpp" +#include "low_precision/avg_pool.hpp" +#include "low_precision/clamp.hpp" +#include "low_precision/concat.hpp" +#include "low_precision/convolution.hpp" +#include "low_precision/convolution_backprop_data.hpp" +#include "low_precision/depth_to_space.hpp" +#include "low_precision/fake_quantize_decomposition.hpp" +#include "low_precision/group_convolution.hpp" +#include "low_precision/interpolate.hpp" +#include "low_precision/mat_mul.hpp" +#include "low_precision/max_pool.hpp" +#include "low_precision/multiply.hpp" +#include "low_precision/mvn.hpp" +#include "low_precision/normalize_l2.hpp" +#include "low_precision/pad.hpp" +#include "low_precision/prelu.hpp" +#include "low_precision/reduce_max.hpp" +#include "low_precision/reduce_mean.hpp" +#include "low_precision/reduce_min.hpp" +#include "low_precision/reduce_sum.hpp" +#include "low_precision/reshape.hpp" +#include "low_precision/relu.hpp" +#include "low_precision/squeeze.hpp" +#include "low_precision/split.hpp" +#include "low_precision/shuffle_channels.hpp" +#include "low_precision/strided_slice.hpp" +#include "low_precision/transpose.hpp" +#include "low_precision/unsqueeze.hpp" +#include "low_precision/variadic_split.hpp" + +#include "low_precision/network_helper.hpp" +#include "lpt_ngraph_functions/common/builders.hpp" + +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; +using namespace ngraph; +using namespace ngraph::pass; + +TEST(LPT, AvoidDequantizationToShapeOfPropagationAddTransformation) { + auto input1 = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto input2 = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + + auto convert1 = std::make_shared(input1, element::f32); + auto convert2 = std::make_shared(input2, element::f32); + + auto mul1 = std::make_shared(convert1, opset1::Constant::create(element::f32, {}, { 2.f })); + auto mul2 = std::make_shared(convert2, opset1::Constant::create(element::f32, {}, { 4.f })); + + auto add = std::make_shared(mul1, mul2); + auto shapeOf = std::make_shared(add); + + auto result1 = std::make_shared(add); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input1, input2 }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationAvgPoolTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto avgPool = std::make_shared(mul, Strides{ 1, 1 }, Shape{ 1, 1 }, Shape{ 0, 0 }, Shape{ 2, 2 }, true); + auto shapeOf = std::make_shared(avgPool); + + auto result1 = std::make_shared(avgPool); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationClampTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto clamp = std::make_shared(mul, 0.0, 6.0); + auto shapeOf = std::make_shared(clamp); + + auto result1 = std::make_shared(clamp); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationConcatTransformation) { + auto input1 = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto input2 = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + + auto convert1 = std::make_shared(input1, element::f32); + auto convert2 = std::make_shared(input2, element::f32); + + auto mul1 = std::make_shared(convert1, opset1::Constant::create(element::f32, {}, { 2.f })); + auto mul2 = std::make_shared(convert2, opset1::Constant::create(element::f32, {}, { 4.f })); + + auto concat = std::make_shared(OutputVector{ mul1, mul2 }, 1); + auto shapeOf = std::make_shared(concat); + + auto result1 = std::make_shared(concat); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input1, input2 }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationConvolutionTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto weights = opset1::Constant::create(element::i8, { 6, 3, 1, 1 }, { 3 }); + auto convertOnWeights = std::make_shared(weights, element::f32); + auto mulOnWeights = std::make_shared(convertOnWeights, opset1::Constant::create(element::f32, {}, { 4.f })); + + auto convolution = std::make_shared( + mul, + mulOnWeights, + ngraph::Strides{ 1, 1 }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::Strides{ 1, 1 }); + + auto shapeOf = std::make_shared(convolution); + + auto result1 = std::make_shared(convolution); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationConvolutionBackpropDataTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 8, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto weights = opset1::Constant::create(element::i8, { 8, 2, 1, 1 }, { 3 }); + auto convertOnWeights = std::make_shared(weights, element::f32); + auto mulOnWeights = std::make_shared(convertOnWeights, opset1::Constant::create(element::f32, {}, { 4.f })); + + auto convolutionBackpropData = std::make_shared( + mul, + mulOnWeights, + ngraph::Strides{ 1, 1 }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::Strides{ 1, 1 }); + + auto shapeOf = std::make_shared(convolutionBackpropData); + + auto result1 = std::make_shared(convolutionBackpropData); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationDepthToSpaceTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto d2s = std::make_shared(mul, op::v0::DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST); + auto shapeOf = std::make_shared(d2s); + + auto result1 = std::make_shared(d2s); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationFakeQuantizeDecompositionTransformation) { + auto input = std::make_shared(element::f32, PartialShape{ 1, 3, 16, 16 }); + + ngraph::builder::subgraph::FakeQuantizeOnData fqValues{ 256ul, {}, {0.f}, {2.55f}, {0.f}, {2.55f} }; + auto fakeQuantize = ngraph::builder::subgraph::makeFakeQuantize(input, element::f32, fqValues); + auto shapeOf = std::make_shared(fakeQuantize); + + auto& outInfo = fakeQuantize->output(0).get_rt_info(); + auto attribute = ngraph::pass::low_precision::make_shared_attribute(element::TypeVector{ element::u8, element::i8 }); + auto attributeWrapper = std::make_shared>>(attribute); + outInfo.emplace(ngraph::VariantWrapper>::type_info.name, attributeWrapper); + + auto result1 = std::make_shared(fakeQuantize); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationGroupConvolutionTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 2 * 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto weights = opset1::Constant::create(element::i8, { 6, 3, 7, 7 }, { 2 }); + auto convertOnWeights = std::make_shared(weights, element::f32); + auto mulOnWeights = std::make_shared(convertOnWeights, opset1::Constant::create(element::f32, {}, { 4.f })); + auto reshapeConst = opset1::Constant::create(element::i32, { 5 }, { 2, 3, 3, 7, 7 }); + auto reshapeOnWeights = std::make_shared(mulOnWeights, reshapeConst, true); + + auto groupConvolution = std::make_shared( + mul, + reshapeOnWeights, + ngraph::Strides{ 1, 1 }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::CoordinateDiff{ 0, 0 }, + ngraph::Strides{ 1, 1 }); + auto shapeOf = std::make_shared(groupConvolution); + + auto result1 = std::make_shared(groupConvolution); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationInterpolateTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto outShape = opset1::Constant::create(element::i32, { 4 }, { 1, 3, 18, 18}); + op::v0::InterpolateAttrs attributes; + attributes.align_corners = false; + attributes.antialias = false; + attributes.axes = AxisSet{ 2, 3 }; + attributes.mode = "nearest"; + attributes.pads_begin = { 0 }; + attributes.pads_end = { 0 }; + auto interpolate = std::make_shared(mul, outShape, attributes); + auto shapeOf = std::make_shared(interpolate); + + auto result1 = std::make_shared(interpolate); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationMatMulTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 1024 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto weights = opset1::Constant::create(element::i8, { 2048, 1024 }, { 3 }); + auto convertOnWeights = std::make_shared(weights, element::f32); + auto mulOnWeights = std::make_shared(convertOnWeights, opset1::Constant::create(element::f32, {}, { 4.f })); + + auto matmul = std::make_shared(mul, mulOnWeights, false, true); + auto shapeOf = std::make_shared(matmul); + + auto result1 = std::make_shared(matmul); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationMaxPoolTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto maxPool = std::make_shared(mul, Strides{ 1, 1 }, Shape{ 1, 1 }, Shape{ 0, 0 }, Shape{ 2, 2 }); + auto shapeOf = std::make_shared(maxPool); + + auto result1 = std::make_shared(maxPool); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationMultiplyTransformation) { + auto input1 = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto input2 = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + + auto convert1 = std::make_shared(input1, element::f32); + auto convert2 = std::make_shared(input2, element::f32); + + auto mul1 = std::make_shared(convert1, opset1::Constant::create(element::f32, {}, { 2.f })); + auto mul2 = std::make_shared(convert2, opset1::Constant::create(element::f32, {}, { 4.f })); + + auto mul = std::make_shared(mul1, mul2); + auto shapeOf = std::make_shared(mul); + + auto result1 = std::make_shared(mul); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input1, input2 }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationMVNTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto MVN = std::make_shared>(mul); + auto shapeOf = std::make_shared(MVN); + + auto result1 = std::make_shared(MVN); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationNormalizeL2Transformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axes = opset1::Constant::create(element::i32, { 2 }, { 2, 3 }); + auto normalize = std::make_shared(mul, axes, 0.01, ov::op::EpsMode::ADD); + auto shapeOf = std::make_shared(normalize); + + auto result1 = std::make_shared(normalize); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationPadTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto pads_begin = opset1::Constant::create(element::i32, { 4 }, { 0, 0, 1, 1 }); + auto pads_end = opset1::Constant::create(element::i32, { 4 }, { 0, 0, 1, 1 }); + auto pad = std::make_shared(mul, pads_begin, pads_end, op::PadMode::CONSTANT); + auto shapeOf = std::make_shared(pad); + + auto result1 = std::make_shared(pad); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationPReluTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto slope = opset1::Constant::create(element::f32, { 1, 3, 1, 1 }, { 0.01f }); + auto prelu = std::make_shared(mul, slope); + auto shapeOf = std::make_shared(prelu); + + auto result1 = std::make_shared(prelu); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationReduceMaxTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axes = opset1::Constant::create(element::i32, { 2 }, { 2, 3 }); + auto reduce = std::make_shared(mul, axes); + auto shapeOf = std::make_shared(reduce); + + auto result1 = std::make_shared(reduce); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationReduceMeanTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axes = opset1::Constant::create(element::i32, { 2 }, { 2, 3 }); + auto reduce = std::make_shared(mul, axes); + auto shapeOf = std::make_shared(reduce); + + auto result1 = std::make_shared(reduce); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationReduceMinTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axes = opset1::Constant::create(element::i32, { 2 }, { 2, 3 }); + auto reduce = std::make_shared(mul, axes); + auto shapeOf = std::make_shared(reduce); + + auto result1 = std::make_shared(reduce); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationReduceSumTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axes = opset1::Constant::create(element::i32, { 2 }, { 2, 3 }); + auto reduce = std::make_shared(mul, axes); + auto shapeOf = std::make_shared(reduce); + + auto result1 = std::make_shared(reduce); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationReshapeTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto outShape = opset1::Constant::create(element::i32, { 3 }, { 1, 3, -1 }); + auto reshape = std::make_shared(mul, outShape, true); + auto shapeOf = std::make_shared(reshape); + + auto result1 = std::make_shared(reshape); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationReluTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto relu = std::make_shared(mul); + auto shapeOf = std::make_shared(relu); + + auto result1 = std::make_shared(relu); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationSqueezeTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axes = opset1::Constant::create(element::i32, { 1 }, { 0 }); + auto squeeze = std::make_shared(mul, axes); + auto shapeOf = std::make_shared(squeeze); + + auto result1 = std::make_shared(squeeze); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationSplitTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axis = opset1::Constant::create(element::i32, {}, { 1 }); + auto split = std::make_shared(mul, axis, 3); + auto shapeOf = std::make_shared(split); + + auto result1 = std::make_shared(split->output(0)); + auto result2 = std::make_shared(split->output(1)); + auto result3 = std::make_shared(split->output(2)); + auto result4 = std::make_shared(shapeOf->output(0)); + + auto f = std::make_shared(ResultVector{ result1, result2, result3, result4 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationShuffleChannelsTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto shuffleChannels = std::make_shared(mul); + auto shapeOf = std::make_shared(shuffleChannels); + + auto result1 = std::make_shared(shuffleChannels); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationStridedSliceTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto beginParam = ngraph::op::Constant::create(ngraph::element::i64, ngraph::Shape{ 4 }, { 0, 0, 0, 0 }); + auto endParam = ngraph::op::Constant::create(ngraph::element::i64, ngraph::Shape{ 4 }, { 1, 2, 1, 1 }); + auto stridesParam = ngraph::op::Constant::create(ngraph::element::i64, ngraph::Shape{ 4 }, { 1, 1, 1, 1 }); + auto stridedSlice = std::make_shared( + mul, beginParam, endParam, stridesParam, + std::vector{ 1, 0, 1, 1 }, + std::vector{ 1, 0, 1, 1 }); + auto shapeOf = std::make_shared(stridedSlice); + + auto result1 = std::make_shared(stridedSlice); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationTransposeTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto constant = ngraph::op::Constant::create(ngraph::element::i64, ngraph::Shape{ 4 }, { 0, 1, 3, 2 }); + auto transpose = std::make_shared(mul, constant); + auto shapeOf = std::make_shared(transpose); + + auto result1 = std::make_shared(transpose); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationUnsqueezeTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axes = opset1::Constant::create(element::i32, { 1 }, { 3 }); + auto unsqueeze = std::make_shared(mul, axes); + auto shapeOf = std::make_shared(unsqueeze); + + auto result1 = std::make_shared(unsqueeze); + auto result2 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} + +TEST(LPT, AvoidDequantizationToShapeOfPropagationVariadicSplitTransformation) { + auto input = std::make_shared(element::u8, PartialShape{ 1, 3, 16, 16 }); + auto convert = std::make_shared(input, element::f32); + auto mul = std::make_shared(convert, opset1::Constant::create(element::f32, {}, { 2.f })); + + auto axis = opset1::Constant::create(element::i32, {}, { 1 }); + auto lengths = opset1::Constant::create(element::i32, { 2 }, { 1, 2 }); + auto variadicSplit = std::make_shared(mul, axis, lengths); + auto shapeOf = std::make_shared(variadicSplit->output(0)); + + auto result1 = std::make_shared(variadicSplit->output(0)); + auto result2 = std::make_shared(variadicSplit->output(1)); + auto result3 = std::make_shared(shapeOf); + + auto f = std::make_shared(ResultVector{ result1, result2, result3 }, ParameterVector{ input }); + pass::Manager m; + m.register_pass(); + m.run_passes(f); + + auto dqBeforeShapeOf = low_precision::NetworkHelper::getDequantization(result2->get_input_node_shared_ptr(0)); + ASSERT_TRUE(dqBeforeShapeOf.empty()); +} 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 1965bf6e86b5c0..e911a0829dcef4 100644 --- a/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/ngraph_reshape_tests.cpp @@ -119,6 +119,11 @@ TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLU) { ASSERT_EQ(changedFunction->get_results()[0]->get_shape(), ngraph::Shape({1, 3, 25, 25})); ASSERT_EQ(ngraph->get_parameters()[0]->get_shape(), ngraph::Shape({1, 3, 22, 22})); ASSERT_EQ(ngraph->get_results()[0]->get_shape(), ngraph::Shape({1, 3, 22, 22})); + + ASSERT_EQ(Layout::NCHW, cnnNetwork.getInputsInfo()["data"]->getLayout()); + IE_SUPPRESS_DEPRECATED_START + ASSERT_FALSE(cnnNetwork.getInputsInfo()["data"]->getInputData()->isDynamic()); + IE_SUPPRESS_DEPRECATED_END } TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUWithoutCloneFunction) { @@ -152,6 +157,11 @@ TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUWithoutCloneFunction) { ASSERT_EQ(changedFunction->get_results()[0]->get_shape(), ngraph::Shape({1, 3, 25, 25})); ASSERT_EQ(ngraph->get_parameters()[0]->get_shape(), ngraph::Shape({1, 3, 25, 25})); ASSERT_EQ(ngraph->get_results()[0]->get_shape(), ngraph::Shape({1, 3, 25, 25})); + + ASSERT_EQ(Layout::NCHW, cnnNetwork.getInputsInfo()["data"]->getLayout()); + IE_SUPPRESS_DEPRECATED_START + ASSERT_FALSE(cnnNetwork.getInputsInfo()["data"]->getInputData()->isDynamic()); + IE_SUPPRESS_DEPRECATED_END } TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUStaticToDynamic) { @@ -192,6 +202,11 @@ TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUStaticToDynamic) { ASSERT_EQ(changedFunction->get_results()[0]->get_output_partial_shape(0), refShape); ASSERT_EQ(ngraph->get_parameters()[0]->get_output_partial_shape(0), refShape); ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), refShape); + + ASSERT_EQ(Layout::NCHW, cnnNetwork.getInputsInfo()["data"]->getLayout()); + IE_SUPPRESS_DEPRECATED_START + ASSERT_TRUE(cnnNetwork.getInputsInfo()["data"]->getInputData()->isDynamic()); + IE_SUPPRESS_DEPRECATED_END } TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUStaticToFullyDynamic) { @@ -232,10 +247,16 @@ TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUStaticToFullyDynamic) { ASSERT_EQ(changedFunction->get_results()[0]->get_output_partial_shape(0), refShape); ASSERT_EQ(ngraph->get_parameters()[0]->get_output_partial_shape(0), refShape); ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), refShape); + + ASSERT_EQ(Layout::BLOCKED, cnnNetwork.getInputsInfo()["data"]->getLayout()); + IE_SUPPRESS_DEPRECATED_START + ASSERT_TRUE(cnnNetwork.getInputsInfo()["data"]->getInputData()->isDynamic()); + IE_SUPPRESS_DEPRECATED_END } TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUDynamicToDynamic) { const ngraph::PartialShape refShape{1, 3, ngraph::Dimension::dynamic(), 25}; + const Layout refLayout = Layout::NHWC; std::shared_ptr ngraph; { ngraph::PartialShape shape({1, 3, 22, ngraph::Dimension::dynamic()}); @@ -255,6 +276,7 @@ TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUDynamicToDynamic) { ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), ngraph::PartialShape({1, 3, 22, ngraph::Dimension::dynamic()})); CNNNetwork cnnNetwork(ngraph); + cnnNetwork.getInputsInfo()["data"]->setLayout(refLayout); std::map shapes; shapes["data"] = refShape; @@ -272,6 +294,11 @@ TEST_F(NGraphReshapeTests, CNNReshapeSpatialReLUDynamicToDynamic) { ASSERT_EQ(changedFunction->get_results()[0]->get_output_partial_shape(0), refShape); ASSERT_EQ(ngraph->get_parameters()[0]->get_output_partial_shape(0), refShape); ASSERT_EQ(ngraph->get_results()[0]->get_output_partial_shape(0), refShape); + + ASSERT_EQ(refLayout, cnnNetwork.getInputsInfo()["data"]->getLayout()); + IE_SUPPRESS_DEPRECATED_START + ASSERT_TRUE(cnnNetwork.getInputsInfo()["data"]->getInputData()->isDynamic()); + IE_SUPPRESS_DEPRECATED_END } class CustomTestOp: public ngraph::op::Op { diff --git a/inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp b/inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp index 8ae3850c0ee54a..30d7a7f0c92153 100644 --- a/inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp +++ b/inference-engine/tests/functional/inference_engine/ov_shared_object_test.cpp @@ -14,7 +14,7 @@ using namespace std; class SharedObjectOVTests : public ::testing::Test { protected: std::string get_mock_engine_name() { - return FileUtils::makePluginLibraryName(InferenceEngine::getIELibraryPath(), + return FileUtils::makePluginLibraryName({}, std::string("mock_engine") + IE_BUILD_POSTFIX); } diff --git a/inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp b/inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp index 3dfa33ed31cecf..d2ecec7e08282f 100644 --- a/inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp +++ b/inference-engine/tests/functional/inference_engine/ov_variable_state_test.cpp @@ -4,30 +4,30 @@ #include -#include "ie_blob.h" - #include #include using namespace ::testing; using namespace std; -TEST(VariableStateOVTests, throwsOnUninitializedReset) { +using VariableStateOVTests = ::testing::Test; + +TEST_F(VariableStateOVTests, throwsOnUninitializedReset) { ov::runtime::VariableState state; ASSERT_THROW(state.reset(), ov::Exception); } -TEST(VariableStateOVTests, throwsOnUninitializedGetname) { +TEST_F(VariableStateOVTests, throwsOnUninitializedGetname) { ov::runtime::VariableState state; ASSERT_THROW(state.get_name(), ov::Exception); } -TEST(VariableStateOVTests, throwsOnUninitializedGetState) { +TEST_F(VariableStateOVTests, throwsOnUninitializedGetState) { ov::runtime::VariableState state; ASSERT_THROW(state.get_state(), ov::Exception); } -TEST(VariableStateOVTests, throwsOnUninitializedSetState) { +TEST_F(VariableStateOVTests, throwsOnUninitializedSetState) { ov::runtime::VariableState state; ov::runtime::Tensor tensor; ASSERT_THROW(state.set_state(tensor), ov::Exception); diff --git a/inference-engine/tests/functional/inference_engine/pre_allocator_test.cpp b/inference-engine/tests/functional/inference_engine/pre_allocator_test.cpp index 3ac7e5a6ff6dfe..1b99b4e36ea148 100644 --- a/inference-engine/tests/functional/inference_engine/pre_allocator_test.cpp +++ b/inference-engine/tests/functional/inference_engine/pre_allocator_test.cpp @@ -3,7 +3,6 @@ // #include -#include #include "ie_allocator.hpp" #include "details/ie_pre_allocator.hpp" diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_bag_offsets_sum.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_bag_offsets_sum.cpp new file mode 100644 index 00000000000000..a6fde2c1453073 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_bag_offsets_sum.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/embedding_bag_offsets_sum.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + TEST_P(EmbeddingBagOffsetsSumLayerTest, Serialize) { + Serialize(); + } + + const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::U8}; + + const std::vector indPrecisions = { + InferenceEngine::Precision::I64, + InferenceEngine::Precision::I32}; + + const std::vector> emb_table_shape = {{5, 6}, {5, 4, 16}}; + const std::vector> indices = + {{0, 1, 2, 2, 3}, {4, 4, 3, 1, 0}, {1, 2, 1, 2, 1, 2, 1, 2, 1, 2}}; + const std::vector> offsets = {{0, 2}, {0, 0, 2, 2}, {2, 4}}; + const std::vector default_index = {0, 4}; + const std::vector with_weights = {false, true}; + const std::vector with_default_index = {false, true}; + + const auto EmbeddingBagOffsetsSumParams = ::testing::Combine( + ::testing::ValuesIn(emb_table_shape), + ::testing::ValuesIn(indices), + ::testing::ValuesIn(offsets), + ::testing::ValuesIn(default_index), + ::testing::ValuesIn(with_weights), + ::testing::ValuesIn(with_default_index)); + + INSTANTIATE_TEST_SUITE_P( + smoke_EmbeddingBagOffsetsSumLayerTest_Serialization, EmbeddingBagOffsetsSumLayerTest, + ::testing::Combine(EmbeddingBagOffsetsSumParams, + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(indPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + EmbeddingBagOffsetsSumLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_bag_packed_sum.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_bag_packed_sum.cpp new file mode 100644 index 00000000000000..7bb3327c9fa6bd --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_bag_packed_sum.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/embedding_bag_packed_sum.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + TEST_P(EmbeddingBagPackedSumLayerTest, Serialize) { + Serialize(); + } + + const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::U8}; + + const std::vector indPrecisions = { + InferenceEngine::Precision::I64, + InferenceEngine::Precision::I32}; + + const std::vector> emb_table_shape = {{5, 6}, {10, 35}, {5, 4, 16}}; + const std::vector>> indices = + {{{0, 1}, {2, 2}}, {{4, 4, 3}, {1, 0, 2}}, {{1, 2, 1, 2}}}; + const std::vector with_weights = {false, true}; + + const auto EmbeddingBagPackedSumParams = ::testing::Combine( + ::testing::ValuesIn(emb_table_shape), + ::testing::ValuesIn(indices), + ::testing::ValuesIn(with_weights)); + + INSTANTIATE_TEST_SUITE_P( + smoke_EmbeddingBagPackedSumLayerTest_Serialization, EmbeddingBagPackedSumLayerTest, + ::testing::Combine(EmbeddingBagPackedSumParams, + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(indPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + EmbeddingBagPackedSumLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_segments_sum.cpp b/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_segments_sum.cpp new file mode 100644 index 00000000000000..7b5d44f4354d47 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/serialization/single_layer/embedding_segments_sum.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "shared_test_classes/single_layer/embedding_segments_sum.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + TEST_P(EmbeddingSegmentsSumLayerTest, Serialize) { + Serialize(); + } + + const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::U8}; + + const std::vector indPrecisions = { + InferenceEngine::Precision::I64, + InferenceEngine::Precision::I32}; + + const std::vector> emb_table_shape = {{5, 6}, {5, 4, 16}}; + const std::vector> indices = + {{0, 1, 2, 2, 3}, {4, 4, 3, 1, 2}}; + const std::vector> segment_ids = {{0, 1, 2, 3, 4}, {0, 0, 2, 2, 4}}; + const std::vector num_segments = {5, 7}; + const std::vector default_index = {0, 4}; + const std::vector with_weights = {false, true}; + const std::vector with_default_index = {false, true}; + + const auto EmbeddingSegmentsSumParams = ::testing::Combine( + ::testing::ValuesIn(emb_table_shape), + ::testing::ValuesIn(indices), + ::testing::ValuesIn(segment_ids), + ::testing::ValuesIn(num_segments), + ::testing::ValuesIn(default_index), + ::testing::ValuesIn(with_weights), + ::testing::ValuesIn(with_default_index)); + + INSTANTIATE_TEST_SUITE_P( + smoke_EmbeddingSegmentsSumLayerTest_Serialization, EmbeddingSegmentsSumLayerTest, + ::testing::Combine(EmbeddingSegmentsSumParams, + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(indPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + EmbeddingSegmentsSumLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/inference_engine/shared_object_loader_test.cpp b/inference-engine/tests/functional/inference_engine/shared_object_loader_test.cpp index 411d87b3036548..fb1ab852c27305 100644 --- a/inference-engine/tests/functional/inference_engine/shared_object_loader_test.cpp +++ b/inference-engine/tests/functional/inference_engine/shared_object_loader_test.cpp @@ -15,7 +15,7 @@ using namespace InferenceEngine::details; class SharedObjectLoaderTests: public ::testing::Test { protected: std::string get_mock_engine_name() { - return FileUtils::makePluginLibraryName(getIELibraryPath(), + return FileUtils::makePluginLibraryName({}, std::string("mock_engine") + IE_BUILD_POSTFIX); } diff --git a/inference-engine/tests/functional/inference_engine/transformations/clamp_fusion.cpp b/inference-engine/tests/functional/inference_engine/transformations/clamp_fusion.cpp index 769c6d781d7734..4fd0353330e38f 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/clamp_fusion.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/clamp_fusion.cpp @@ -18,11 +18,9 @@ #include "common_test_utils/ngraph_test_utils.hpp" - using namespace testing; using namespace ngraph; - TEST_F(TransformationTestsF, ClampFusion) { { auto data = std::make_shared(element::f32, Shape{2, 2}); @@ -82,3 +80,64 @@ TEST_F(TransformationTestsF, ClampFusionNonConstMin) { function_ref = std::make_shared(NodeVector{min}, ParameterVector{data, min_val}); } } + +TEST_F(TransformationTestsF, ClampFusionMinMax) { + { + auto data = std::make_shared(element::f32, Shape{2, 2}); + auto min_const = opset5::Constant::create(element::f32, Shape{1}, {0.1}); + auto max_const = opset5::Constant::create(element::f32, Shape{1}, {5}); + auto min = std::make_shared(data, max_const); + auto max = std::make_shared(min, min_const); + + function = std::make_shared(NodeVector{max}, ParameterVector{data}); + + manager.register_pass(); + } + + { + auto data = std::make_shared(element::f32, Shape{2, 2}); + auto clamp = std::make_shared(data, 0.1, 5); + function_ref = std::make_shared(NodeVector{clamp}, ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, ClampFusionMinMaxScalars) { + { + auto data = std::make_shared(element::f32, Shape{2, 2}); + auto min_const = opset5::Constant::create(element::f32, Shape{}, {0.1}); + auto max_const = opset5::Constant::create(element::f32, Shape{}, {5}); + auto min = std::make_shared(data, max_const); + auto max = std::make_shared(min, min_const); + function = std::make_shared(NodeVector{max}, ParameterVector{data}); + + manager.register_pass(); + } + + { + auto data = std::make_shared(element::f32, Shape{2, 2}); + auto clamp = std::make_shared(data, 0.1, 5); + function_ref = std::make_shared(NodeVector{clamp}, ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, ClampFusionMinMaxNonConstMax) { + { + auto data = std::make_shared(element::f32, Shape{2, 2}); + auto max_val = std::make_shared(element::f32, Shape{}); + auto max_const = opset5::Constant::create(element::f32, Shape{}, {5}); + auto min = std::make_shared(data, max_const); + auto max = std::make_shared(min, max_val); + function = std::make_shared(NodeVector{max}, ParameterVector{data, max_val}); + + manager.register_pass(); + } + + { + auto data = std::make_shared(element::f32, Shape{2, 2}); + auto min_val = std::make_shared(element::f32, Shape{}); + auto max_const = opset5::Constant::create(element::f32, Shape{}, {5}); + auto min = std::make_shared(data, max_const); + auto max = std::make_shared(min, min_val); + function_ref = std::make_shared(NodeVector{max}, ParameterVector{data, min_val}); + } +} \ No newline at end of file diff --git a/inference-engine/tests/functional/inference_engine/transformations/compress_float_constants_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/compress_float_constants_test.cpp new file mode 100644 index 00000000000000..1c3b6bfe4396cd --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/compress_float_constants_test.cpp @@ -0,0 +1,138 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include + +#include "openvino/core/function.hpp" +#include "openvino/opsets/opset8.hpp" +#include "openvino/pass/manager.hpp" +#include "transformations/common_optimizations/compress_float_constants.hpp" +#include "transformations/common_optimizations/mark_precision_sensitive_subgraphs.hpp" +#include "transformations/init_node_info.hpp" +#include "transformations/utils/utils.hpp" + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; + +TEST(TransformationTests, CompressConstants_f32) { + std::shared_ptr f(nullptr), f_ref(nullptr); + { + auto input = std::make_shared(ov::element::f32, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f32, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto conv = std::make_shared(input, + const_weights, + ov::Strides{1, 1}, + ov::CoordinateDiff{0, 0}, + ov::CoordinateDiff{0, 0}, + ov::Strides{1, 1}); + auto const_scales = ov::opset8::Constant::create(ov::element::f32, ov::Shape{ 1 }, { 1.4 }); + + auto shape = std::make_shared(conv); + auto convert1 = std::make_shared(shape, ov::element::f32); + auto mul = std::make_shared(convert1, const_scales); + auto convert2 = std::make_shared(mul, ov::element::i32); + + auto default_scales_node = ov::opset8::Constant::create(ov::element::f32, ov::Shape{ 4 }, { 1., 1., 1.4, 1.4 }); + auto axes_node = ov::opset8::Constant::create(ov::element::i64, ov::Shape{ 4 }, { 0, 1, 2, 3 }); + + auto interpolate4_attr = ov::opset8::Interpolate::InterpolateAttrs(ov::opset8::Interpolate::InterpolateMode::NEAREST, + ov::opset8::Interpolate::ShapeCalcMode::SIZES, std::vector{0, 0, 0, 0}, std::vector{0, 0, 0, 0}, + ov::opset8::Interpolate::CoordinateTransformMode::ASYMMETRIC, ov::opset8::Interpolate::NearestMode::SIMPLE, + false, -0.75); + + auto resize = std::make_shared(conv, convert2, default_scales_node, axes_node, interpolate4_attr); + + f = std::make_shared(ov::NodeVector{ resize }, ov::ParameterVector{ input }); + + ov::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto input = std::make_shared(ov::element::f32, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f16, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto convert_ins1 = std::make_shared(const_weights, ov::element::f32); + auto conv = std::make_shared(input, + convert_ins1, + ov::Strides{ 1, 1 }, + ov::CoordinateDiff{ 0, 0 }, + ov::CoordinateDiff{ 0, 0 }, + ov::Strides{ 1, 1 }); + auto const_scales = ov::opset8::Constant::create(ov::element::f32, ov::Shape{ 1 }, { 1.4 }); + + auto shape = std::make_shared(conv); + auto convert1 = std::make_shared(shape, ov::element::f32); + auto mul = std::make_shared(convert1, const_scales); + auto convert2 = std::make_shared(mul, ov::element::i32); + + auto default_scales_node = ov::opset8::Constant::create(ov::element::f32, ov::Shape{ 4 }, { 1., 1., 1.4, 1.4 }); + auto axes_node = ov::opset8::Constant::create(ov::element::i64, ov::Shape{ 4 }, { 0, 1, 2, 3 }); + + auto interpolate4_attr = ov::opset8::Interpolate::InterpolateAttrs(ov::opset8::Interpolate::InterpolateMode::NEAREST, + ov::opset8::Interpolate::ShapeCalcMode::SIZES, std::vector{0, 0, 0, 0}, std::vector{0, 0, 0, 0}, + ov::opset8::Interpolate::CoordinateTransformMode::ASYMMETRIC, ov::opset8::Interpolate::NearestMode::SIMPLE, + false, -0.75); + + auto resize = std::make_shared(conv, convert2, default_scales_node, axes_node, interpolate4_attr); + + f_ref = std::make_shared(ov::NodeVector{ resize }, ov::ParameterVector{ input }); + } + + auto res = compare_functions(f, f_ref, true); + ASSERT_TRUE(res.first) << res.second; +} + +TEST(TransformationTests, CompressConstants_f64) { + std::shared_ptr f(nullptr), f_ref(nullptr); + { + auto input = std::make_shared(ov::element::f64, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f64, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto conv = std::make_shared(input, + const_weights, + ov::Strides{ 1, 1 }, + ov::CoordinateDiff{ 0, 0 }, + ov::CoordinateDiff{ 0, 0 }, + ov::Strides{ 1, 1 }); + f = std::make_shared(ov::NodeVector{ conv }, ov::ParameterVector{ input }); + + ov::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto input = std::make_shared(ov::element::f64, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f16, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto convert_ins1 = std::make_shared(const_weights, ov::element::f64); + auto conv = std::make_shared(input, + convert_ins1, + ov::Strides{ 1, 1 }, + ov::CoordinateDiff{ 0, 0 }, + ov::CoordinateDiff{ 0, 0 }, + ov::Strides{ 1, 1 }); + f_ref = std::make_shared(ov::NodeVector{ conv }, ov::ParameterVector{ input }); + } + + auto res = compare_functions(f, f_ref, true); + ASSERT_TRUE(res.first) << res.second; +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/const_folding_for_if.cpp b/inference-engine/tests/functional/inference_engine/transformations/const_folding_for_if.cpp index 84dea503137fc7..1cd9aebd685595 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/const_folding_for_if.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/const_folding_for_if.cpp @@ -14,6 +14,7 @@ #include "ngraph/opsets/opset8.hpp" #include +#include using namespace testing; using namespace std; using namespace ngraph; @@ -49,7 +50,9 @@ TEST(TransformationTests, DISABLED_if_constant_folding) { auto add = make_shared(if_res, param_add); auto add_res = make_shared(add); fun = make_shared(OutputVector{ add_res }, ParameterVector{ param_add }); - ngraph::pass::ConstantFolding().run_on_function(fun); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(fun); } std::shared_ptr f_ref(nullptr); { diff --git a/inference-engine/tests/functional/inference_engine/transformations/const_folding_prior_box.cpp b/inference-engine/tests/functional/inference_engine/transformations/const_folding_prior_box.cpp index cb77d6b6bbca84..a56ea2b612e9b0 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/const_folding_prior_box.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/const_folding_prior_box.cpp @@ -15,6 +15,7 @@ #include #include #include "common_test_utils/ngraph_test_utils.hpp" +#include using namespace testing; @@ -35,8 +36,10 @@ TEST(TransformationTests, ConstFoldingPriorBox) { auto pb = std::make_shared(layer_shape, image_shape, attrs); auto res = std::make_shared(pb); f = std::make_shared(ngraph::NodeVector{res}, ngraph::ParameterVector{in}); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::ConstantFolding().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); ASSERT_NO_THROW(check_rt_info(f)); } @@ -76,8 +79,10 @@ TEST(TransformationTests, ConstFoldingPriorBoxClustered) { auto pb = std::make_shared(layer_shape, image_shape, attrs); auto res = std::make_shared(pb); f = std::make_shared(ngraph::NodeVector{res}, ngraph::ParameterVector{in}); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::ConstantFolding().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); ASSERT_NO_THROW(check_rt_info(f)); } @@ -135,8 +140,10 @@ TEST(TransformationTests, ConstFoldingPriorBoxSubgraph) { auto pb = std::make_shared(ss_data, ss_image, attrs); auto res = std::make_shared(pb); f = std::make_shared(ngraph::NodeVector{res}, ngraph::ParameterVector{in, in_2}); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::ConstantFolding().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); ASSERT_NO_THROW(check_rt_info(f)); } @@ -185,8 +192,10 @@ TEST(TransformationTests, ConstFoldingPriorBoxClusteredSubgraph) { auto pb = std::make_shared(ss_data, ss_image, attrs); auto res = std::make_shared(pb); f = std::make_shared(ngraph::NodeVector{res}, ngraph::ParameterVector{in, in_2}); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::ConstantFolding().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); ASSERT_NO_THROW(check_rt_info(f)); } diff --git a/inference-engine/tests/functional/inference_engine/transformations/conv_fusion_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/conv_fusion_test.cpp index 389388f29584fa..0fa792b611537d 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/conv_fusion_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/conv_fusion_test.cpp @@ -23,6 +23,8 @@ #include "common_test_utils/ngraph_test_utils.hpp" +#include + using namespace ngraph; using namespace testing; @@ -50,7 +52,9 @@ class ConvFusionTests: public CommonTestUtils::TestsCommon, f_ref = get_initial_function(input_shape, weights_shape, eltwise_type, eltwise_shape); } else { f_ref = get_reference_function(input_shape, weights_shape, eltwise_type, eltwise_shape); - ngraph::pass::ConstantFolding().run_on_function(f_ref); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(f_ref); } } @@ -165,15 +169,15 @@ INSTANTIATE_TEST_SUITE_P(ConvAddFusion, ConvFusionTests, std::make_tuple(InputShape{3, 3, DYN}, WeightsShape{1, 3, 3}, add::get_type_info_static(), EltwiseShape{1, 1}, false))); -INSTANTIATE_TEST_SUITE_P(DISABLED_ConvAddFusionNegative, ConvFusionTests, +INSTANTIATE_TEST_SUITE_P(ConvAddFusionNegative, ConvFusionTests, testing::Values(std::make_tuple(InputShape{DYN, DYN, DYN, DYN, DYN}, WeightsShape{8, 3, 1, 2, 3}, add::get_type_info_static(), EltwiseShape{2, 1}, true), std::make_tuple(InputShape{DYN, 3, 64, 64, 64}, WeightsShape{8, 3, 1, 2, 3}, - add::get_type_info_static(), EltwiseShape{8, 1, 1}, true), + add::get_type_info_static(), EltwiseShape{8, 1, 1, 1, 1}, true), std::make_tuple(InputShape{2, DYN, 64, 64, 64}, WeightsShape{9, 3, 2, 3, 1}, - add::get_type_info_static(), EltwiseShape{9, 1, 1, 1, 1}, true))); + add::get_type_info_static(), EltwiseShape{2, 1, 1, 1, 1}, true))); -INSTANTIATE_TEST_SUITE_P(DISABLED_ConvMulFusion, ConvFusionTests, +INSTANTIATE_TEST_SUITE_P(ConvMulFusion, ConvFusionTests, testing::Values(std::make_tuple(InputShape{DYN, DYN, DYN, DYN, DYN}, WeightsShape{8, 3, 1, 2, 3}, mul::get_type_info_static(), EltwiseShape{8, 1, 1, 1}, false), std::make_tuple(InputShape{DYN, 3, 64, 64, 64}, WeightsShape{8, 3, 1, 2, 3}, @@ -207,12 +211,12 @@ INSTANTIATE_TEST_SUITE_P(DISABLED_ConvMulFusion, ConvFusionTests, std::make_tuple(InputShape{3, 3, DYN}, WeightsShape{1, 3, 3}, mul::get_type_info_static(), EltwiseShape{1, 1}, false))); -INSTANTIATE_TEST_SUITE_P(DISABLED_ConvMulFusionNegative, ConvFusionTests, +INSTANTIATE_TEST_SUITE_P(ConvMulFusionNegative, ConvFusionTests, testing::Values(std::make_tuple(InputShape{DYN, DYN, DYN, DYN, DYN}, WeightsShape{8, 3, 1, 2, 3}, mul::get_type_info_static(), EltwiseShape{2, 1}, true), - std::make_tuple(InputShape{DYN, 3, 64, 64}, WeightsShape{8, 3, 1, 2, 3}, - mul::get_type_info_static(), EltwiseShape{8, 1, 1}, true), - std::make_tuple(InputShape{2, DYN, 64, 64}, WeightsShape{9, 3, 2, 3, 1}, + std::make_tuple(InputShape{DYN, 3, 64, 64}, WeightsShape{ 3, 3, 2, 3}, + mul::get_type_info_static(), EltwiseShape{8, 1, 1, 1}, true), + std::make_tuple(InputShape{2, DYN, 64, 64}, WeightsShape{ 3, 2, 3, 1}, mul::get_type_info_static(), EltwiseShape{9, 1, 1, 1, 1}, true))); diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_compression_only_to_legacy_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_compression_only_to_legacy_test.cpp new file mode 100644 index 00000000000000..1ce8582ff95a3c --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_compression_only_to_legacy_test.cpp @@ -0,0 +1,106 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include + +#include "openvino/core/function.hpp" +#include "openvino/opsets/opset8.hpp" +#include "openvino/pass/manager.hpp" +#include "transformations/common_optimizations/convert_compression_only_to_legacy.hpp" +#include "transformations/rt_info/decompression.hpp" +#include "transformations/init_node_info.hpp" +#include "transformations/utils/utils.hpp" + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; + +TEST(TransformationTests, ConvertCompressionOnlyToLegacy) { + std::shared_ptr f(nullptr), f_ref(nullptr); + { + auto input = std::make_shared(ov::element::f32, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f16, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto convert_ins1 = std::make_shared(const_weights, ov::element::f32); + ov::mark_as_decompression(convert_ins1); + auto conv = std::make_shared(input, + convert_ins1, + ov::Strides{ 1, 1 }, + ov::CoordinateDiff{ 0, 0 }, + ov::CoordinateDiff{ 0, 0 }, + ov::Strides{ 1, 1 }); + + f = std::make_shared(ov::NodeVector{ conv }, ov::ParameterVector{ input }); + + ov::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto input = std::make_shared(ov::element::f16, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f16, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto conv = std::make_shared(input, + const_weights, + ov::Strides{ 1, 1 }, + ov::CoordinateDiff{ 0, 0 }, + ov::CoordinateDiff{ 0, 0 }, + ov::Strides{ 1, 1 }); + + f_ref = std::make_shared(ov::NodeVector{ conv }, ov::ParameterVector{ input }); + } + + auto res = compare_functions(f, f_ref, true); + ASSERT_TRUE(res.first) << res.second; +} + +TEST(TransformationTests, ConvertCompressionOnlyToLegacyNoConvertion) { + std::shared_ptr f(nullptr), f_ref(nullptr); + { + auto input = std::make_shared(ov::element::f32, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f32, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto conv = std::make_shared(input, + const_weights, + ov::Strides{ 1, 1 }, + ov::CoordinateDiff{ 0, 0 }, + ov::CoordinateDiff{ 0, 0 }, + ov::Strides{ 1, 1 }); + + f = std::make_shared(ov::NodeVector{ conv }, ov::ParameterVector{ input }); + + ov::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto input = std::make_shared(ov::element::f32, ov::Shape{ 1, 3, 12, 12 }); + auto const_weights = ov::opset8::Constant::create(ov::element::f32, + ov::Shape{ 1, 3, 3, 3 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + auto conv = std::make_shared(input, + const_weights, + ov::Strides{ 1, 1 }, + ov::CoordinateDiff{ 0, 0 }, + ov::CoordinateDiff{ 0, 0 }, + ov::Strides{ 1, 1 }); + + f_ref = std::make_shared(ov::NodeVector{ conv }, ov::ParameterVector{ input }); + } + + auto res = compare_functions(f, f_ref, true); + ASSERT_TRUE(res.first) << res.second; +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp index 1a8e196be5950e..27f173304d156c 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_convolution_test.cpp @@ -24,6 +24,8 @@ #include "common_test_utils/ngraph_test_utils.hpp" +#include + using namespace testing; using namespace ngraph; using namespace ngraph::opset1; @@ -71,9 +73,12 @@ class ConvertConvolutionTest: public CommonTestUtils::TestsCommon, }; TEST_P(ConvertConvolutionTest, CompareFunctions) { - const auto & orig_shape = f->get_output_partial_shape(0); - pass::InitNodeInfo().run_on_function(f); - pass::ConvertConvolutions().run_on_function(f); + const auto orig_shape = f->get_output_partial_shape(0); + pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); auto res = compare_functions(f, f_ref); ASSERT_TRUE(res.first) << res.second; diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp index 3c456c7f083c6d..242325390d248a 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_deconvolution_test.cpp @@ -24,6 +24,8 @@ #include "common_test_utils/ngraph_test_utils.hpp" +#include + using namespace testing; using InputShape = ngraph::PartialShape; @@ -67,9 +69,11 @@ class ConvertDeconvolutionTest: public CommonTestUtils::TestsCommon, }; TEST_P(ConvertDeconvolutionTest, CompareFunctions) { - const auto & orig_shape = f->get_output_partial_shape(0); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::ConvertConvolutions().run_on_function(f); + const auto orig_shape = f->get_output_partial_shape(0); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.run_passes(f); ASSERT_NO_THROW(check_rt_info(f)); auto res = compare_functions(f, f_ref); ASSERT_TRUE(res.first) << res.second; diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_divide.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_divide.cpp index 7a308b89a41ec0..b4df08a778b611 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_divide.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_divide.cpp @@ -32,10 +32,8 @@ TEST_F(TransformationTestsF, ConvertDivide) { { auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); - auto divide_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {1.5}); - auto pow = std::make_shared(divide_constant, - ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1})); - auto mul = std::make_shared(data, pow); + auto divide_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {1. / 1.5}); + auto mul = std::make_shared(data, divide_constant); function_ref = std::make_shared(ngraph::NodeVector{mul}, ngraph::ParameterVector{data}); } @@ -63,11 +61,11 @@ TEST_F(TransformationTestsF, ConvertDivideNegative) { TEST_F(TransformationTestsF, ConvertDivideScalar) { { - auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{}); - auto divide_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.5}); - auto divide = std::make_shared(data, divide_constant); + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto divide = std::make_shared(data1, data2); - function = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data}); + function = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data1, data2}); NGRAPH_CHECK(divide->get_output_partial_shape(0).rank().get_length() == 0); @@ -76,13 +74,51 @@ TEST_F(TransformationTestsF, ConvertDivideScalar) { { auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{}); - auto divide_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.5}); - auto pow = std::make_shared(divide_constant, + auto pow_input = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto pow = std::make_shared(pow_input, ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1})); auto mul = std::make_shared(data, pow); - function_ref = std::make_shared(ngraph::NodeVector{mul}, ngraph::ParameterVector{data}); + function_ref = std::make_shared(ngraph::NodeVector{mul}, ngraph::ParameterVector{data, pow_input}); NGRAPH_CHECK(mul->get_output_partial_shape(0).rank().get_length() == 0); } } + +TEST_F(TransformationTestsF, ConvertDivideWithConstantPositive) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto divide_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.5}); + auto divide = std::make_shared(data, divide_constant); + + function = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data}); + manager.register_pass(); + } + + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto divide_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1. / 1.5}); + auto mul = std::make_shared(data, divide_constant); + + function_ref = std::make_shared(ngraph::NodeVector{mul}, ngraph::ParameterVector{data}); + } +} + +TEST_F(TransformationTestsF, ConvertDivideWithConstantNegative) { + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto divide = std::make_shared(data1, data2); + + function = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data1, data2}); + manager.register_pass(); + } + + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{}); + auto divide = std::make_shared(data1, data2); + + function_ref = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data1, data2}); + } +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_ngraph_to_cnn_network_tests.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_ngraph_to_cnn_network_tests.cpp index 44caeeb1a4b141..c62de865091744 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_ngraph_to_cnn_network_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_ngraph_to_cnn_network_tests.cpp @@ -23,6 +23,8 @@ #include #include +#include + using namespace testing; using namespace InferenceEngine; @@ -37,7 +39,9 @@ TEST(ConvertFunctionToCNNNetworkTests, ConvertPReLUNetwork) { f = std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{param1, param2}); - ngraph::pass::InitNodeInfo().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(f); } InferenceEngine::CNNNetwork nGraphImpl(f); @@ -66,7 +70,9 @@ TEST(ConvertFunctionToCNNNetworkTests, ConvertConvolutionNetwork) { f = std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{param1, param2}); - ngraph::pass::InitNodeInfo().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(f); } InferenceEngine::CNNNetwork nGraphImpl(f); @@ -162,7 +168,9 @@ TEST(ConvertFunctionToCNNNetworkTests, ConvertTopKWithOneInput) { f = std::make_shared(ngraph::ResultVector{result}, ngraph::ParameterVector{param}); - ngraph::pass::InitNodeInfo().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(f); } ngraph::pass::Manager manager; diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_reduce_to_pooling_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_reduce_to_pooling_test.cpp index fec70c317badeb..866f8a8bcc31f7 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_reduce_to_pooling_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_reduce_to_pooling_test.cpp @@ -21,6 +21,8 @@ #include "common_test_utils/ngraph_test_utils.hpp" +#include + using namespace testing; using InputShape = ngraph::PartialShape; @@ -149,7 +151,9 @@ INSTANTIATE_TEST_SUITE_P(ReduceToReshapePoolReshape, ConvertReduceToPoolingTests TEST(ConvertReduceToPooling, Negative) { auto f = ConvertReduceToPoolingTests::get_initial_function(ngraph::PartialShape::dynamic(), {3}, MAX, true); - ASSERT_NO_THROW(ngraph::pass::ConvertReduceToPooling().run_on_function(f)); + ngraph::pass::Manager manager; + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); } #undef MAX diff --git a/inference-engine/tests/functional/inference_engine/transformations/convert_scatter_elements_to_scatter_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/convert_scatter_elements_to_scatter_test.cpp index b40c4dc4e6cc80..31fbb691f8493f 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/convert_scatter_elements_to_scatter_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/convert_scatter_elements_to_scatter_test.cpp @@ -22,6 +22,8 @@ #include "common_test_utils/ngraph_test_utils.hpp" +#include + using namespace testing; std::shared_ptr get_initial_function(const ngraph::PartialShape & data_shape, @@ -82,9 +84,11 @@ void test(std::shared_ptr f, std::shared_ptr manager.register_pass(); manager.register_pass(); manager.register_pass(unh); - manager.run_passes(f); - ASSERT_NO_THROW(check_rt_info(f)); - ngraph::pass::ConstantFolding().run_on_function(f); + manager.register_pass([](std::shared_ptr f) { + check_rt_info(f); + }); + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); auto fc = FunctionsComparator::no_default().enable(FunctionsComparator::PRECISIONS); auto res = fc.compare(f, f_ref); diff --git a/inference-engine/tests/functional/inference_engine/transformations/divide_fusion.cpp b/inference-engine/tests/functional/inference_engine/transformations/divide_fusion.cpp new file mode 100644 index 00000000000000..841697532eb0b4 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/divide_fusion.cpp @@ -0,0 +1,88 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; + +TEST(TransformationTests, DivideFusion) { + std::shared_ptr f, f_ref; + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto pow_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {-1}); + auto pow = std::make_shared(data2, pow_constant); + auto mul = std::make_shared(data1, pow); + + f = std::make_shared(ngraph::NodeVector{mul}, ngraph::ParameterVector{data1, data2}); + + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto divide = std::make_shared(data1, data2); + + f_ref = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data1, data2}); + } + + const auto res = FunctionsComparator::with_default() + .enable(FunctionsComparator::CONST_VALUES) + .enable(FunctionsComparator::ATTRIBUTES) + .compare(f, f_ref); + ASSERT_TRUE(res.valid) << res.message; +} + +TEST(TransformationTests, DivideFusionNegative) { + std::shared_ptr f, f_ref; + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto pow_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {-1.01}); + auto pow = std::make_shared(data2, pow_constant); + auto mul = std::make_shared(data1, pow); + + f = std::make_shared(ngraph::NodeVector{mul}, ngraph::ParameterVector{data1, data2}); + + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto pow_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {-1.01}); + auto pow = std::make_shared(data2, pow_constant); + auto mul = std::make_shared(data1, pow); + + f_ref = std::make_shared(ngraph::NodeVector{mul}, ngraph::ParameterVector{data1, data2}); + } + + const auto res = FunctionsComparator::with_default() + .enable(FunctionsComparator::CONST_VALUES) + .enable(FunctionsComparator::ATTRIBUTES) + .compare(f, f_ref); + ASSERT_TRUE(res.valid) << res.message; +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/eliminate_split_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/eliminate_split_test.cpp new file mode 100644 index 00000000000000..e6f17ba777428f --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/eliminate_split_test.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; + +TEST_F(TransformationTestsF, EliminateSplit) { + { + auto input = std::make_shared(ngraph::element::f32, ngraph::PartialShape::dynamic()); + auto mul_constant = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {89.2}); + auto mul = std::make_shared(input, mul_constant); + auto axis_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {2}); + auto split = std::make_shared(mul, axis_const, 1); + auto res = std::make_shared(split); + function = std::make_shared(ngraph::NodeVector{res}, ngraph::ParameterVector{input}); + + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, ngraph::PartialShape::dynamic()); + auto mul_constant = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {89.2}); + auto mul = std::make_shared(input, mul_constant); + auto res = std::make_shared(mul); + function_ref = std::make_shared(ngraph::NodeVector{res}, ngraph::ParameterVector{input}); + } +} + +TEST_F(TransformationTestsF, EliminateSplitNegative) { + { + auto input = std::make_shared(ngraph::element::f32, ngraph::PartialShape::dynamic()); + auto mul_constant = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {89.2}); + auto mul = std::make_shared(input, mul_constant); + auto axis_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {2}); + auto split = std::make_shared(mul, axis_const, 3); + auto res1 = std::make_shared(split->output(0)); + auto res2 = std::make_shared(split->output(1)); + auto res3 = std::make_shared(split->output(2)); + function = std::make_shared(ngraph::NodeVector{res1, res2, res3}, ngraph::ParameterVector{input}); + + manager.register_pass(); + } +} + +TEST_F(TransformationTestsF, EliminateSequenceOfSplits) { + { + auto input = std::make_shared(ngraph::element::f32, ngraph::PartialShape::dynamic()); + auto axis_const1 = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}); + auto axis_const2 = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto axis_const3 = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {2}); + auto split1 = std::make_shared(input, axis_const1, 1); + auto split2 = std::make_shared(split1, axis_const2, 1); + auto split3 = std::make_shared(split2, axis_const3, 1); + auto axis_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {2}); + auto true_split = std::make_shared(split3, axis_const, 3); + auto res1 = std::make_shared(true_split->output(0)); + auto res2 = std::make_shared(true_split->output(1)); + auto res3 = std::make_shared(true_split->output(2)); + function = std::make_shared(ngraph::NodeVector{res1, res2, res3}, ngraph::ParameterVector{input}); + + manager.register_pass(); + } + + { + auto input = std::make_shared(ngraph::element::f32, ngraph::PartialShape::dynamic()); + auto axis_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {2}); + auto split = std::make_shared(input, axis_const, 3); + auto res1 = std::make_shared(split->output(0)); + auto res2 = std::make_shared(split->output(1)); + auto res3 = std::make_shared(split->output(2)); + function_ref = std::make_shared(ngraph::NodeVector{res1, res2, res3}, ngraph::ParameterVector{input}); + } +} \ No newline at end of file diff --git a/inference-engine/tests/functional/inference_engine/transformations/keep_constant_inputs_tests.cpp b/inference-engine/tests/functional/inference_engine/transformations/keep_constant_inputs_tests.cpp index 93f91995506b88..bb97268d787eb8 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/keep_constant_inputs_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/keep_constant_inputs_tests.cpp @@ -23,6 +23,8 @@ #include #include "shared_test_classes/base/low_precision_transformations/layer_transformation.hpp" +#include + using namespace testing; using namespace InferenceEngine; @@ -44,10 +46,12 @@ int numberOfInputsForLayerInCNNNetwork(const InferenceEngine::CNNNetwork & netwo void transformNetwork(InferenceEngine::CNNNetwork & clonedNetwork, bool keep_constant_inputs) { if (clonedNetwork.getFunction()) { auto nGraphFunc = clonedNetwork.getFunction(); - ngraph::pass::CommonOptimizations().run_on_function(nGraphFunc); - ngraph::pass::ConvertOpSet3ToOpSet2().run_on_function(nGraphFunc); - ngraph::pass::ConvertOpSet2ToOpSet1().run_on_function(nGraphFunc); - ngraph::pass::ConvertOpSet1ToLegacy().run_on_function(nGraphFunc); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.register_pass(); + manager.register_pass(); + manager.run_passes(nGraphFunc); IE_SUPPRESS_DEPRECATED_START clonedNetwork = InferenceEngine::CNNNetwork( InferenceEngine::details::convertFunctionToICNNNetwork(nGraphFunc, clonedNetwork, keep_constant_inputs)); diff --git a/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp index d2e8dd0cb4f464..9358886a63afc7 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/mul_add_conversion_test.cpp @@ -28,6 +28,8 @@ #include "common_test_utils/ngraph_test_utils.hpp" #include "lpt_ngraph_functions/common/builders.hpp" +#include + using namespace testing; using InputShape = ngraph::PartialShape; @@ -148,9 +150,11 @@ TEST_P(MulAddConversionTests, CompareFunctions) { manager.register_pass(); manager.register_pass(); manager.register_pass(unh); - manager.run_passes(f); - ASSERT_NO_THROW(check_rt_info(f)); - ngraph::pass::ConstantFolding().run_on_function(f); + manager.register_pass([](std::shared_ptr f) { + check_rt_info(f); + }); + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); f->validate_nodes_and_infer_types(); auto fc = FunctionsComparator::no_default().enable(FunctionsComparator::PRECISIONS); @@ -166,9 +170,12 @@ TEST_P(MulOrAddConversionTests, CompareFunctions) { manager.register_pass(); manager.register_pass(); manager.register_pass(unh); - manager.run_passes(f); - ASSERT_NO_THROW(check_rt_info(f)); - ngraph::pass::ConstantFolding().run_on_function(f); + manager.register_pass([](std::shared_ptr f) { + check_rt_info(f); + }); + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); + f->validate_nodes_and_infer_types(); auto fc = FunctionsComparator::no_default().enable(FunctionsComparator::PRECISIONS); diff --git a/inference-engine/tests/functional/inference_engine/transformations/ngraph_1d_ops_reshape_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/ngraph_1d_ops_reshape_test.cpp index 841f310318780f..72bbbcf64a5023 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/ngraph_1d_ops_reshape_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/ngraph_1d_ops_reshape_test.cpp @@ -21,6 +21,8 @@ #include #include "common_test_utils/ngraph_test_utils.hpp" +#include + using namespace testing; using namespace ngraph; @@ -36,10 +38,14 @@ TEST(TransformationTests, ConvReshapeTest1) { auto conv = std::make_shared(input, w, strides, dilations, pads_begin, pads_end, ngraph::element::f32, 1); f = std::make_shared(ngraph::NodeVector{conv}, ngraph::ParameterVector{}); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::Reshape1DOps().run_on_function(f); - ASSERT_NO_THROW(check_rt_info(f)); - ngraph::pass::ConstantFolding().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.register_pass([](std::shared_ptr f) { + check_rt_info(f); + }); + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); } std::vector ref_shape{1, 6, 1, 62}; @@ -69,10 +75,14 @@ TEST(TransformationTests, ConvBiasReshapeTest1) { auto conv = std::make_shared(input, w, b, strides, dilations, pads_begin, pads_end, ngraph::element::f32, 1); f = std::make_shared(ngraph::NodeVector{conv}, ngraph::ParameterVector{}); - ngraph::pass::InitNodeInfo().run_on_function(f); - ngraph::pass::Reshape1DOps().run_on_function(f); - ASSERT_NO_THROW(check_rt_info(f)); - ngraph::pass::ConstantFolding().run_on_function(f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.register_pass(); + manager.register_pass([](std::shared_ptr f) { + check_rt_info(f); + }); + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); } std::vector ref_shape{1, 6, 1, 62}; diff --git a/inference-engine/tests/functional/inference_engine/transformations/ngraph_fq_transpose_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/ngraph_fq_transpose_test.cpp index 6b5f2d82b6a1b8..822c575ac11faf 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/ngraph_fq_transpose_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/ngraph_fq_transpose_test.cpp @@ -56,28 +56,28 @@ TEST_F(TransformationTestsF, FQTransposeTest1) { } } -TEST(TransformationTests, FQTransposeDynamic) { - auto data = std::make_shared(ngraph::element::f32, ngraph::PartialShape::dynamic()); - auto input_low = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {2}); - auto input_high = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {3}); - auto output_low = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {2}); - auto output_high = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {3}); - auto transpose_order = ngraph::op::Constant::create(ngraph::element::i64, ngraph::Shape{3}, {0, 2, 1}); +TEST_F(TransformationTestsF, FQTransposeNegativeCase) { + auto create_graph = []() -> std::shared_ptr { + auto data = std::make_shared(ngraph::element::f32, ngraph::PartialShape{1, 3, 1}); + auto sigmoid = std::make_shared(data); + auto input_low = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {2}); + auto input_high = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {3}); + auto output_low = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {2}); + auto output_high = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {3}); + auto transpose_order = ngraph::op::Constant::create(ngraph::element::i64, ngraph::Shape{3}, {0, 2, 1}); - std::shared_ptr f(nullptr); - { - auto fq = std::make_shared(data, input_low, input_high, output_low, output_high, 1); + auto fq = std::make_shared(sigmoid, input_low, input_high, output_low, output_high, 1); auto transpose = std::make_shared(fq, transpose_order); - f = std::make_shared(ngraph::NodeVector{transpose}, ngraph::ParameterVector{data}); + return std::make_shared(ngraph::NodeVector{transpose}, ngraph::ParameterVector{data}); + }; + function = create_graph(); - ngraph::pass::Manager manager; - manager.register_pass(); - manager.register_pass(); - manager.register_pass([](std::shared_ptr f) { - check_rt_info(f); - }); - manager.register_pass(); - ASSERT_NO_THROW(manager.run_passes(f)); - } + manager.register_pass(); + manager.register_pass(); + manager.register_pass([](std::shared_ptr f) { + check_rt_info(f); + }); + + function_ref = create_graph(); } diff --git a/inference-engine/tests/functional/inference_engine/transformations/nop_elimination.cpp b/inference-engine/tests/functional/inference_engine/transformations/nop_elimination.cpp index 1bab10d9b4a3cf..ef654188194878 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/nop_elimination.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/nop_elimination.cpp @@ -21,6 +21,8 @@ #include "common_test_utils/ngraph_test_utils.hpp" +#include + using namespace ngraph; using namespace std; @@ -559,7 +561,9 @@ TEST(nop_elimination, unsqueeze_squeeze_elimination) { auto check_usecase = [&](const Shape& shape, const std::vector& axes_val) { auto baseline_f = generate_func(shape, axes_val); auto optimized_f = generate_func(shape, axes_val); - pass::NopElimination().run_on_function(optimized_f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 1); ASSERT_EQ(count_ops_of_type(baseline_f), 1); @@ -589,7 +593,9 @@ TEST(nop_elimination, reshape_unsqueeze_elimination) { auto B1 = make_shared(B, axes); auto baseline_f = make_shared(make_shared(B1), ParameterVector{A}); auto optimized_f = clone_function(*baseline_f); - pass::NopElimination().run_on_function(optimized_f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 1); ASSERT_EQ(count_ops_of_type(baseline_f), 1); @@ -618,7 +624,9 @@ TEST(nop_elimination, reshape_squeeze_elimination) { auto B1 = make_shared(B, axes); auto baseline_f = make_shared(make_shared(B1), ParameterVector{A}); auto optimized_f = clone_function(*baseline_f); - pass::NopElimination().run_on_function(optimized_f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 1); ASSERT_EQ(count_ops_of_type(baseline_f), 1); @@ -644,7 +652,9 @@ TEST(nop_elimination, reshape_reshape_elimination) { auto B1 = make_shared(B, pat2, true); auto baseline_f = make_shared(make_shared(B1), ParameterVector{A}); auto optimized_f = clone_function(*baseline_f); - pass::NopElimination().run_on_function(optimized_f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 2); ASSERT_EQ(count_ops_of_type(optimized_f), 1); @@ -669,7 +679,9 @@ TEST(nop_elimination, squeeze_reshape_elimination) { auto B1 = make_shared(B, pat2, false); auto baseline_f = make_shared(make_shared(B1), ParameterVector{A}); auto optimized_f = clone_function(*baseline_f); - pass::NopElimination().run_on_function(optimized_f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 1); ASSERT_EQ(count_ops_of_type(baseline_f), 1); @@ -695,7 +707,9 @@ TEST(nop_elimination, unsqueeze_reshape_elimination) { auto B1 = make_shared(B, pat2, false); auto baseline_f = make_shared(make_shared(B1), ParameterVector{A}); auto optimized_f = clone_function(*baseline_f); - pass::NopElimination().run_on_function(optimized_f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 1); ASSERT_EQ(count_ops_of_type(baseline_f), 1); @@ -716,8 +730,9 @@ TEST(nop_elimination, squeeze_unsqueeze_elimination_negative) { auto squeeze = make_shared(input, indices); auto baseline_f = make_shared(squeeze, ParameterVector{input}); auto optimized_f = clone_function(*baseline_f); - pass::NopElimination().run_on_function(optimized_f); - + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 1); ASSERT_EQ(count_ops_of_type(optimized_f), 1); }; @@ -733,7 +748,9 @@ TEST(nop_elimination, topk_convert_elimination) { auto C = make_shared(B->output(0), B->output(0).get_element_type()); auto baseline_f = make_shared(make_shared(C), ParameterVector{A}); auto optimized_f = clone_function(*baseline_f); - pass::NopElimination().run_on_function(optimized_f); + ngraph::pass::Manager manager; + manager.register_pass(); + manager.run_passes(optimized_f); ASSERT_EQ(count_ops_of_type(baseline_f), 1); ASSERT_EQ(count_ops_of_type(optimized_f), 0); diff --git a/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp index 9c64bd308cec7e..de7b78bda9d014 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/optimize_strided_slice_test.cpp @@ -15,9 +15,11 @@ #include #include #include +#include #include #include #include +#include "openvino/core/partial_shape.hpp" #include "common_test_utils/ngraph_test_utils.hpp" @@ -277,3 +279,707 @@ TEST_F(TransformationTestsF, OptimizeSS_Groupped_Test) { function_ref = std::make_shared(ngraph::NodeVector{concat}, ngraph::ParameterVector{source}); } } + +TEST_F(TransformationTestsF, OptimizeSS_UselessDeletion_use_shapes_false) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{5, 5, 5, 5}); + auto relu = std::make_shared(data); + auto begin = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto stride = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + + std::vector begin_mask = {0, 0, 0, 0}; + std::vector end_mask = {1, 1, 1, 1}; // ignoring end -- slicing to the end + + auto ss = std::make_shared(relu, begin, end, stride, begin_mask, end_mask); + + function = std::make_shared(ngraph::NodeVector{ss}, ngraph::ParameterVector{data}); + manager.register_pass(false); + manager.register_pass(); + } + // No UselessStridedSliceEraser transformation if use_shapes == false +} + +TEST_F(TransformationTestsF, OptimizeSS_Shared_Test_use_shapes_false) { + { + auto source = std::make_shared(ngraph::element::f32, ngraph::Shape{5, 5, 5, 5}); + + auto begin1 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end1 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto stride1 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + std::vector begin_mask1 = {0, 0, 0, 0}; + std::vector end_mask1 = {0, 0, 0, 0}; + auto ss1 = std::make_shared(source, begin1, end1, stride1, begin_mask1, end_mask1); + + auto begin2 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end2 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto stride2 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + std::vector begin_mask2 = {0, 0, 0, 0}; + std::vector end_mask2 = {0, 0, 0, 0}; + auto ss2 = std::make_shared(source, begin2, end2, stride2, begin_mask2, end_mask2); + + auto concat = std::make_shared(ngraph::NodeVector{ss1, ss2}, 0); + + function = std::make_shared(ngraph::NodeVector{concat}, ngraph::ParameterVector{source}); + manager.register_pass(false); + manager.register_pass(); + } + // No SharedStridedSliceEraser transformation if use_shapes == false +} + +TEST_F(TransformationTestsF, OptimizeSS_Groupped_Test_use_shapes_false) { + { + auto source = std::make_shared(ngraph::element::f32, ngraph::Shape{5, 5, 5, 5}); + + auto begin1 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end1 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {5, 3, 5, 5}); + auto stride1 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + std::vector begin_mask1 = {0, 0, 0, 0}; + std::vector end_mask1 = {0, 0, 0, 0}; + auto ss1 = std::make_shared(source, begin1, end1, stride1, begin_mask1, end_mask1); + + auto begin2 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 3, 0, 0}); + auto end2 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {5, 5, 5, 5}); + auto stride2 = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + std::vector begin_mask2 = {0, 0, 0, 0}; + std::vector end_mask2 = {0, 0, 0, 0}; + auto ss2 = std::make_shared(source, begin2, end2, stride2, begin_mask2, end_mask2); + + auto concat = std::make_shared(ngraph::NodeVector{ss1, ss2}, 1); + + function = std::make_shared(ngraph::NodeVector{concat}, ngraph::ParameterVector{source}); + manager.register_pass(false); + manager.register_pass(); + } + // No GroupedStridedSliceOptimizer transformation if use_shapes == false +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_default_axes) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1, 1, 1, 1}); + + auto slice = std::make_shared(data, begin, end, step); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data}); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1, 1, 1, 1}); + + std::vector begin_mask = {0, 0, 0, 0}; + std::vector end_mask = {0, 0, 0, 0}; + + auto strided_slice = std::make_shared(data, begin, end, stride, begin_mask, end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_axes_const_sorted_full) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1, 1, 1, 1}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 1, 2, 3}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data}); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1, 1, 1, 1}); + + std::vector begin_mask = {0, 0, 0, 0}; + std::vector end_mask = {0, 0, 0, 0}; + + auto strided_slice = std::make_shared(data, begin, end, stride, begin_mask, end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_all_const) { + { + auto data = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{4}, {2, 3, 4, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {-1}); + auto step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {-1}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{}); + manager.register_pass(); + } + { + auto data = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{4}, {2, 3, 4, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {-1}); + auto stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + + std::vector begin_end_mask = {0}; + auto strided_slice = std::make_shared(data, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_all_const_fold) { + { + auto data = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{4}, {2, 3, 4, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {-1}); + auto step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {-1}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{}); + manager.register_pass(); + manager.register_pass(); + } + { + auto sliced_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, {3, 4}); + function_ref = std::make_shared(ngraph::NodeVector{sliced_const}, ngraph::ParameterVector{}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_sss_params_axes_const_sorted_less) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {1, 2}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin, end, step}); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto start = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto stop = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {1, 2}); + auto zero = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{1}, {0}); + + const auto default_begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, {0}); + const auto begin = std::make_shared(default_begin, + axes, + start, + zero); + + const auto default_end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, {0}); + const auto end = std::make_shared(default_end, + axes, + stop, + zero); + + const auto default_stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, {1}); + const auto stride = std::make_shared(default_stride, + axes, + step, + zero); + std::vector begin_end_mask = {1, 0, 0}; + auto strided_slice = std::make_shared(data, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data, start, stop, step}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_sss_params_axes_const_unsorted) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {3, 1}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin, end, step}); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto start = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto stop = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + + auto zero = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{1}, {0}); + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {3, 1}); + + const auto default_begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + const auto begin = std::make_shared(default_begin, + axes, + start, + zero); + + const auto default_end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + const auto end = std::make_shared(default_end, + axes, + stop, + zero); + + const auto default_stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + const auto stride = std::make_shared(default_stride, + axes, + step, + zero); + + std::vector begin_end_mask = {1, 0, 1, 0}; + auto strided_slice = std::make_shared(data, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data, start, stop, step}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_sss_params_axes_const_negative_sorted) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, -3, 2, -1}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin, end, step}); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto stride = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + + std::vector begin_mask = {0, 0, 0, 0}; + std::vector end_mask = {0, 0, 0, 0}; + + auto strided_slice = std::make_shared(data, begin, end, stride, begin_mask, end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data, begin, end, stride}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_sss_params_dyn_shape_axes_const_negative_unsorted) { + { + auto data_shape = ov::PartialShape{ov::Dimension(-1), ov::Dimension(2, 6), 4, ov::Dimension(-1)}; + auto data = std::make_shared(ngraph::element::f32, data_shape); + auto begin = std::make_shared(ngraph::element::i64, ngraph::PartialShape{ov::Dimension(-1)}); + auto end = std::make_shared(ngraph::element::i64, ngraph::PartialShape{ov::Dimension(-1)}); + auto step = std::make_shared(ngraph::element::i64, ngraph::PartialShape{ov::Dimension(-1)}); + + auto axes = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {-1, -3}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin, end, step}); + manager.register_pass(); + } + { + auto data_shape = ov::PartialShape{ov::Dimension(-1), ov::Dimension(2, 6), 4, ov::Dimension(-1)}; + auto data = std::make_shared(ngraph::element::f32, data_shape); + auto start = std::make_shared(ngraph::element::i64, ngraph::PartialShape{ov::Dimension(-1)}); + auto stop = std::make_shared(ngraph::element::i64, ngraph::PartialShape{ov::Dimension(-1)}); + auto step = std::make_shared(ngraph::element::i64, ngraph::PartialShape{ov::Dimension(-1)}); + + auto zero = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{1}, {0}); + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {3, 1}); + + const auto default_begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + const auto begin = std::make_shared(default_begin, + axes, + start, + zero); + + const auto default_end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + const auto end = std::make_shared(default_end, + axes, + stop, + zero); + + const auto default_stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + const auto stride = std::make_shared(default_stride, + axes, + step, + zero); + + std::vector begin_end_mask = {1, 0, 1, 0}; + auto strided_slice = std::make_shared(data, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data, start, stop, step}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_sss_params_static_shape_axes_const_negative_unsorted) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + + auto axes = ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {-1, -3}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin, end, step}); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto start = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto stop = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{2}); + + auto zero = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{1}, {0}); + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {3, 1}); + + const auto default_begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + const auto begin = std::make_shared(default_begin, + axes, + start, + zero); + + const auto default_end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + const auto end = std::make_shared(default_end, + axes, + stop, + zero); + + const auto default_stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + const auto stride = std::make_shared(default_stride, + axes, + step, + zero); + + std::vector begin_end_mask = {1, 0, 1, 0}; + auto strided_slice = std::make_shared(data, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data, start, stop, step}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_dyn_rank_axes_const_positive) { + { + auto data = std::make_shared(ngraph::element::f32, ov::PartialShape::dynamic()); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 1, 2, 3}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin, end, step}); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ov::PartialShape::dynamic()); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto stride = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + + std::vector begin_mask = {0, 0, 0, 0}; + std::vector end_mask = {0, 0, 0, 0}; + + auto strided_slice = std::make_shared(data, begin, end, stride, begin_mask, end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data, begin, end, stride}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_dyn_rank_axes_const_negative) { + { + auto data = std::make_shared(ngraph::element::f32, ov::PartialShape::dynamic()); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto end = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + auto step = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + + auto axes = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, -3, 2, -1}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin, end, step}); + manager.register_pass(); + manager.register_pass(); + } + // No transformation for negative axes and dynamic data rank +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_axes_param) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 4, 3, 5}); + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0, 0, 0, 0}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {-1, -1, -1, -1}); + auto step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1, 1, 1, 1}); + + auto axes = std::make_shared(ngraph::element::i64, ngraph::Shape{4}); + + auto slice = std::make_shared(data, begin, end, step, axes); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, axes}); + manager.register_pass(); + manager.register_pass(); + } + // No transformation for non-const axes input +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_begin_param_shape_of_use_shapes_true) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto shape_of_data = std::make_shared(data, ngraph::element::i64); + auto data_rank = std::make_shared(shape_of_data, ngraph::element::i64); + + auto zero_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}); + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto three_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {3}); + + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{1}); + auto end = std::make_shared(three_const, begin); + auto step = std::make_shared(one_const, begin); + + auto axes = std::make_shared(zero_const, one_const, one_const, ngraph::element::i64); + + auto slice = std::make_shared(shape_of_data, begin, end, step, axes); + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin}); + + manager.register_pass(true); + manager.register_pass(); + } + { + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto three_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {3}); + + auto data = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {2, 3, 4, 5}); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{1}); + auto end = std::make_shared(three_const, begin); + auto stride = std::make_shared(one_const, begin); + + std::vector begin_end_mask = {0}; + auto strided_slice = std::make_shared(data, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{begin}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_begin_param_shape_of_use_shapes_false) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto shape_of_data = std::make_shared(data, ngraph::element::i64); + auto data_rank = std::make_shared(shape_of_data, ngraph::element::i64); + + auto zero_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}); + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto three_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {3}); + + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{1}); + auto end = std::make_shared(three_const, begin); + auto step = std::make_shared(one_const, begin); + + auto axes = std::make_shared(zero_const, one_const, one_const, ngraph::element::i64); + + auto slice = std::make_shared(shape_of_data, begin, end, step, axes); + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data, begin}); + + manager.register_pass(); + manager.register_pass(false); + manager.register_pass(); + } + { + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto three_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {3}); + + auto data = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {2, 3, 4, 5}); + auto begin = std::make_shared(ngraph::element::i64, ngraph::Shape{1}); + auto end = std::make_shared(three_const, begin); + auto stride = std::make_shared(one_const, begin); + + std::vector begin_end_mask = {0}; + auto strided_slice = std::make_shared(data, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{begin}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_const_fold_params_slice_shape_of_use_shapes_true) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto shape_of_data = std::make_shared(data, ngraph::element::i64); + auto data_rank = std::make_shared(shape_of_data, ngraph::element::i64); + + auto zero_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}); + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto three_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {3}); + + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + auto end = std::make_shared(three_const, begin); + auto step = std::make_shared(one_const, begin); + + auto axes = std::make_shared(zero_const, one_const, one_const, ngraph::element::i64); + + auto slice = std::make_shared(shape_of_data, begin, end, step, axes); + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data}); + + manager.register_pass(); + manager.register_pass(true); + manager.register_pass(); + } + { + auto sliced_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {3, 4}); + function_ref = std::make_shared(ngraph::NodeVector{sliced_const}, ngraph::ParameterVector{}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_const_fold_params_slice_shape_of_use_shapes_false) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto shape_of_data = std::make_shared(data, ngraph::element::i64); + auto data_rank = std::make_shared(shape_of_data, ngraph::element::i64); + + auto zero_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}); + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + auto three_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {3}); + + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{1}, {1}); + auto end = std::make_shared(three_const, begin); + auto step = std::make_shared(one_const, begin); + + auto axes = std::make_shared(zero_const, one_const, one_const, ngraph::element::i64); + + auto slice = std::make_shared(shape_of_data, begin, end, step, axes); + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data}); + + manager.register_pass(); + manager.register_pass(false); + manager.register_pass(); + } + { + auto sliced_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {3, 4}); + function_ref = std::make_shared(ngraph::NodeVector{sliced_const}, ngraph::ParameterVector{}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_slice_all_use_shapes_true) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto relu = std::make_shared(data); + + auto shape_of_data = std::make_shared(relu, ngraph::element::i64); + auto data_rank = std::make_shared(shape_of_data, ngraph::element::i64); + + auto zero_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}); + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + + auto begin = std::make_shared(zero_const, data_rank); + auto end = std::make_shared(data_rank, data_rank); + auto step = std::make_shared(one_const, data_rank); + + auto slice = std::make_shared(relu, begin, end, step); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data}); + manager.register_pass(true); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto relu = std::make_shared(data); + + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {4}); + auto stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + + std::vector begin_end_mask = {0, 0, 0, 0}; + auto strided_slice = std::make_shared(relu, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} + +TEST_F(TransformationTestsF, SliceToStridedSlice_slice_all_use_shapes_false) { + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto relu = std::make_shared(data); + + auto shape_of_data = std::make_shared(relu, ngraph::element::i64); + auto data_rank = std::make_shared(shape_of_data, ngraph::element::i64); + + auto zero_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {0}); + auto one_const = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, {1}); + + auto begin = std::make_shared(zero_const, data_rank); + auto end = std::make_shared(data_rank, data_rank); + auto step = std::make_shared(one_const, data_rank); + + auto slice = std::make_shared(relu, begin, end, step); + + function = std::make_shared(ngraph::NodeVector{slice}, ngraph::ParameterVector{data}); + manager.register_pass(false); + manager.register_pass(); + } + { + auto data = std::make_shared(ngraph::element::f32, ngraph::Shape{2, 3, 4, 5}); + auto relu = std::make_shared(data); + + auto begin = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {0}); + auto end = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {4}); + auto stride = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, {1}); + + std::vector begin_end_mask = {0, 0, 0, 0}; + auto strided_slice = std::make_shared(relu, begin, end, stride, begin_end_mask, begin_end_mask); + + function_ref = std::make_shared(ngraph::NodeVector{strided_slice}, ngraph::ParameterVector{data}); + } + comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES); + comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES); +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/subtract_fusion.cpp b/inference-engine/tests/functional/inference_engine/transformations/subtract_fusion.cpp new file mode 100644 index 00000000000000..a271061bf5da0f --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/subtract_fusion.cpp @@ -0,0 +1,121 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; + +TEST(TransformationTests, SubtractFusionMultiply) { + std::shared_ptr f, f_ref; + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto mul_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {-1}); + auto mul = std::make_shared(data2, mul_constant); + auto add = std::make_shared(data1, mul); + + f = std::make_shared(ngraph::NodeVector{add}, ngraph::ParameterVector{data1, data2}); + + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto divide = std::make_shared(data1, data2); + + f_ref = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data1, data2}); + } + + const auto res = FunctionsComparator::with_default() + .enable(FunctionsComparator::CONST_VALUES) + .enable(FunctionsComparator::ATTRIBUTES) + .compare(f, f_ref); + ASSERT_TRUE(res.valid) << res.message; +} + +TEST(TransformationTests, SubtractFusionMultiplyNegative) { + std::shared_ptr f, f_ref; + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto mul_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {-1.01}); + auto mul = std::make_shared(data2, mul_constant); + auto add = std::make_shared(data1, mul); + + f = std::make_shared(ngraph::NodeVector{add}, ngraph::ParameterVector{data1, data2}); + + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto mul_constant = ngraph::opset1::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {-1.01}); + auto mul = std::make_shared(data2, mul_constant); + auto add = std::make_shared(data1, mul); + + f_ref = std::make_shared(ngraph::NodeVector{add}, ngraph::ParameterVector{data1, data2}); + } + + const auto res = FunctionsComparator::with_default() + .enable(FunctionsComparator::CONST_VALUES) + .enable(FunctionsComparator::ATTRIBUTES) + .compare(f, f_ref); + ASSERT_TRUE(res.valid) << res.message; +} + +TEST(TransformationTests, SubtractFusionNeg) { + std::shared_ptr f, f_ref; + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto neg = std::make_shared(data2); + auto add = std::make_shared(neg, data1); + + f = std::make_shared(ngraph::NodeVector{add}, ngraph::ParameterVector{data1, data2}); + + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(f); + ASSERT_NO_THROW(check_rt_info(f)); + } + + { + auto data1 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto data2 = std::make_shared(ngraph::element::f32, ngraph::Shape{3, 1, 2}); + auto divide = std::make_shared(data1, data2); + + f_ref = std::make_shared(ngraph::NodeVector{divide}, ngraph::ParameterVector{data1, data2}); + } + + const auto res = FunctionsComparator::with_default() + .enable(FunctionsComparator::CONST_VALUES) + .enable(FunctionsComparator::ATTRIBUTES) + .compare(f, f_ref); + ASSERT_TRUE(res.valid) << res.message; +} diff --git a/inference-engine/tests/functional/inference_engine/transformations/transpose_sinking_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/transpose_sinking_test.cpp index acef05b876dd6f..56007f814b4536 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/transpose_sinking_test.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/transpose_sinking_test.cpp @@ -265,3 +265,17 @@ TEST_F(TransformationTestsF, TransposeFuses) { function_ref = std::make_shared(ngraph::NodeVector{ add }, ngraph::ParameterVector{ input }); } } + +TEST_F(TransformationTestsF, TransposeReduceNegative) { + { + auto input = std::make_shared(ngraph::element::f32, ngraph::Shape{ 1, 3, 64}); + auto order = ngraph::opset6::Constant::create(ngraph::element::i64, ngraph::Shape{ 3 }, { 0, 2, 1}); + auto transpose = std::make_shared(input, order); + auto axes = ngraph::opset6::Constant::create(ngraph::element::i64, ngraph::Shape{}, {-1}); + auto reduce_mean = std::make_shared(transpose, axes, true); + auto sub = std::make_shared(transpose, reduce_mean); + + function = std::make_shared(ngraph::NodeVector{ sub }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } +} \ No newline at end of file diff --git a/inference-engine/tests/functional/inference_engine/transformations/type_relaxed_tests.cpp b/inference-engine/tests/functional/inference_engine/transformations/type_relaxed_tests.cpp index 810fa36999e8a9..2aac98140907e9 100644 --- a/inference-engine/tests/functional/inference_engine/transformations/type_relaxed_tests.cpp +++ b/inference-engine/tests/functional/inference_engine/transformations/type_relaxed_tests.cpp @@ -8,6 +8,7 @@ #include #include +#include namespace element = ngraph::element; using std::make_shared; @@ -328,8 +329,9 @@ TEST_F(TypeRelaxedTests, ConstantFoldingCheck) { auto relaxed_equal = make_shared>(equal, TypeVector{}, TypeVector{ element::u8 }); f = make_shared(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{}); - - ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f)); + ngraph::pass::Manager manager; + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0); ASSERT_TRUE(ngraph::is_type(layer_before_result)); } @@ -344,8 +346,9 @@ TEST_F(TypeRelaxedTests, ConstantFoldingCheck1) { auto relaxed_equal = make_shared>(equal, TypeVector{}, TypeVector{ element::boolean }); f = make_shared(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{}); - - ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f)); + ngraph::pass::Manager manager; + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0); ASSERT_TRUE(ngraph::is_type(layer_before_result)); } @@ -365,8 +368,9 @@ TEST_F(TypeRelaxedTests, ConstantFoldingCheck2) { ngraph::op::TemporaryReplaceOutputType(const2, element::i32).get()); f = make_shared(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{}); - - ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f)); + ngraph::pass::Manager manager; + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0); ASSERT_TRUE(ngraph::is_type(layer_before_result)); } @@ -383,8 +387,9 @@ TEST_F(TypeRelaxedTests, ConstantFoldingCheck3) { auto relaxed_equal = make_shared>(equal, original_input_types, TypeVector{ element::u8 }); f = make_shared(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{}); - - ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f)); + ngraph::pass::Manager manager; + manager.register_pass(); + ASSERT_NO_THROW(manager.run_passes(f)); auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0); ASSERT_TRUE(ngraph::is_type(layer_before_result)); } diff --git a/inference-engine/tests/functional/inference_engine/transformations/wrap_interpolate_into_transposes_test.cpp b/inference-engine/tests/functional/inference_engine/transformations/wrap_interpolate_into_transposes_test.cpp new file mode 100644 index 00000000000000..5a2c3f055ef3c4 --- /dev/null +++ b/inference-engine/tests/functional/inference_engine/transformations/wrap_interpolate_into_transposes_test.cpp @@ -0,0 +1,564 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common_test_utils/ngraph_test_utils.hpp" + +using namespace testing; + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes4DScales) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SCALES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 2}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{2, 3}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 3, 1, 2 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 2, 3, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes4DSizes) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SIZES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 2}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{2, 3}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 3, 1, 2 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 2, 3, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes5DScales) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SCALES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150, 18 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 2, 3}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{2, 3, 4}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 4, 1, 2, 3 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 2, 3, 4, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes5DSizes) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SIZES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150, 18 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 2, 3}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{2, 3, 4}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 4, 1, 2, 3 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 2, 3, 4, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes4DScalesDynamic) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SCALES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::PartialShape input_shape { 1, ngraph::Dimension::dynamic(), 120, ngraph::Dimension::dynamic() }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 2}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{2, 3}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 3, 1, 2 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 2, 3, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes4DSizesDynamic) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SIZES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::PartialShape input_shape { 1, ngraph::Dimension::dynamic(), 120, ngraph::Dimension::dynamic() }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 2}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 60 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{2, 3}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 3, 1, 2 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{4}, { 0, 2, 3, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes5DScalesDynamic) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SCALES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::PartialShape input_shape { ngraph::Dimension::dynamic(), 100, ngraph::Dimension::dynamic(), ngraph::Dimension::dynamic(), 18 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 2, 3}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{2, 3, 4}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 4, 1, 2, 3 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 2, 3, 4, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes5DSizesDynamic) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SIZES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::PartialShape input_shape { ngraph::Dimension::dynamic(), 100, ngraph::Dimension::dynamic(), ngraph::Dimension::dynamic(), 18 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 2, 3}); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, axis_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 60, 240, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.6, 2.0, 0.5 }); + auto axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{2, 3, 4}); + + auto first_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 4, 1, 2, 3 }); + auto last_transpose_perm = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{5}, { 0, 2, 3, 4, 1 }); + + auto first_transpose = std::make_shared(input, first_transpose_perm); + auto interpolate = std::make_shared(first_transpose, sizes_node, scales_node, axis_node, attrs); + auto last_transpose = std::make_shared(interpolate, last_transpose_perm); + + function_ref = std::make_shared(ngraph::NodeVector{ last_transpose }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes4DScalesNotApplicable) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SCALES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 4 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 3}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 4 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 3}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function_ref = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes4DSizesNotApplicable) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SIZES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 4 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 3}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{2}, { 50, 75 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{2}, { 0.5, 0.5 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 4 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {2}, std::vector{1, 3}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function_ref = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes5DScalesNotApplicable) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SCALES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150, 800 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 50, 75, 600 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.5, 0.5, 0.75 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 5 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 3, 4}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 50, 75, 600 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.5, 0.5, 0.75 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 5 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 3, 4}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function_ref = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + } +} + +TEST_F(TransformationTestsF, WrapInterpolateIntoTransposes5DSizesNotApplicable) { + ngraph::opset8::Interpolate::InterpolateAttrs attrs; + + attrs.mode = ngraph::opset8::Interpolate::InterpolateMode::NEAREST; + attrs.shape_calculation_mode = ngraph::opset8::Interpolate::ShapeCalcMode::SIZES; + attrs.nearest_mode = ngraph::opset8::Interpolate::NearestMode::ROUND_PREFER_FLOOR; + attrs.pads_begin = std::vector{0}; + attrs.pads_end = std::vector{0}; + attrs.antialias = false; + attrs.coordinate_transformation_mode = ngraph::opset8::Interpolate::CoordinateTransformMode::HALF_PIXEL; + attrs.cube_coeff = -0.75f; + + ngraph::Shape input_shape { 1, 100, 120, 150, 800 }; + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 50, 75, 600 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.5, 0.5, 0.75 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 5 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 3, 4}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + manager.register_pass(); + } + { + auto input = std::make_shared(ngraph::element::f32, input_shape); + auto sizes_node = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{3}, { 50, 75, 600 }); + auto scales_node = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, { 0.5, 0.5, 0.75 }); + + auto range_start = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 0 }); + auto range_stop = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 5 }); + auto range_step = ngraph::opset8::Constant::create(ngraph::element::i64, ngraph::Shape{}, { 1 }); + auto range = std::make_shared(range_start, range_stop, range_step, ngraph::element::i64); + + auto indices = ngraph::opset8::Constant::create(ngraph::element::i64, {3}, std::vector{1, 3, 4}); + auto gather_axis_node = ngraph::opset8::Constant::create(ngraph::element::i64, {1}, std::vector{0}); + auto gather_node = std::make_shared(range, indices, gather_axis_node); + + auto interpolate = std::make_shared(input, sizes_node, scales_node, gather_node, attrs); + + function_ref = std::make_shared(ngraph::NodeVector{ interpolate }, ngraph::ParameterVector{ input }); + } +} diff --git a/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt b/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt index 5e973d1f57ade3..6535fca61e3712 100644 --- a/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt +++ b/inference-engine/tests/functional/plugin/cpu/CMakeLists.txt @@ -8,13 +8,14 @@ add_library(cpuSpecificRtInfo STATIC ${IE_MAIN_SOURCE_DIR}/src/mkldnn_plugin/uti ${IE_MAIN_SOURCE_DIR}/src/mkldnn_plugin/utils/rt_info/memory_formats_attribute.cpp) target_link_libraries(cpuSpecificRtInfo PRIVATE ngraph) -set(INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${IE_MAIN_SOURCE_DIR}/src/mkldnn_plugin) +set(INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} $) set(DEPENDENCIES MKLDNNPlugin) set(LINK_LIBRARIES funcSharedTests cpuSpecificRtInfo) if (NGRAPH_ONNX_FRONTEND_ENABLE) list(APPEND INCLUDES "${OpenVINO_SOURCE_DIR}/docs/onnx_custom_op") list(APPEND LINK_LIBRARIES onnx_custom_op) list(APPEND DEPENDENCIES template_extension onnx_custom_op) + list(APPEND DEFINES TEST_MODELS="${TEST_MODEL_ZOO}") else() set(EXCLUDED_SOURCE_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/extension ${CMAKE_CURRENT_SOURCE_DIR}/onnx) endif() @@ -24,6 +25,7 @@ addIeTargetTest( ROOT ${CMAKE_CURRENT_SOURCE_DIR} INCLUDES ${INCLUDES} EXCLUDED_SOURCE_PATHS ${EXCLUDED_SOURCE_PATHS} + DEFINES ${DEFINES} DEPENDENCIES ${DEPENDENCIES} LINK_LIBRARIES ${LINK_LIBRARIES} ADD_CPPLINT diff --git a/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp b/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp index 1f9a430a24d1d7..baf3dc3e7f8ca7 100644 --- a/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp +++ b/inference-engine/tests/functional/plugin/cpu/extension/extension.cpp @@ -119,10 +119,8 @@ class CustomAbsExtension : public InferenceEngine::IExtension { } }; -void infer_model(InferenceEngine::Core& ie, const std::string& model, +static void infer_model(InferenceEngine::Core& ie, InferenceEngine::CNNNetwork& network, const std::vector& input_values, const std::vector& expected) { - InferenceEngine::Blob::CPtr weights; - auto network = ie.ReadNetwork(model, weights); auto function = network.getFunction(); auto network_inputs = network.getInputsInfo(); @@ -150,53 +148,11 @@ void infer_model(InferenceEngine::Core& ie, const std::string& model, ASSERT_EQ(expected, computed_values); } - -TEST(Extension, OnnxModelWithCustomAbs) { - std::string model = R"V0G0N( -ir_version: 3 -producer_name: "nGraph ONNX Importer" -graph { - node { - input: "A" - output: "Y" - name: "customrelu" - op_type: "CustomAbs" - domain: "custom_domain" - } - name: "test_graph" - input { - name: "A" - type { - tensor_type { - elem_type: 1 - shape { - dim { - dim_value: 10 - } - } - } - } - } - output { - name: "Y" - type { - tensor_type { - elem_type: 1 - shape { - dim { - dim_value: 10 - } - } - } - } - } -} -opset_import { - version: 1 - domain: "custom_domain" +static std::string model_full_path(const char* path) { + return FileUtils::makePath(TEST_MODELS, path); } -)V0G0N"; +TEST(Extension, OnnxModelWithCustomAbs) { std::vector input_values{1, -2, 3, -4, 5, -6, 7, -8, 9, -10}; std::vector expected{1, 4, 3, 8, 5, 12, 7, 16, 9, 20}; InferenceEngine::Core ie; @@ -207,7 +163,8 @@ opset_import { return {std::make_shared(ng_inputs.at(0))}; }); - infer_model(ie, model, input_values, expected); + auto network = ie.ReadNetwork(model_full_path("func_tests/models/custom_abs_op.onnx")); + infer_model(ie, network, input_values, expected); ngraph::onnx_import::unregister_operator(CustomAbs::get_type_info_static().name, 1, "custom_domain"); } @@ -255,7 +212,9 @@ TEST(Extension, XmlModelWithCustomAbs) { std::vector expected{1, 4, 3, 8, 5, 12, 7, 16, 9, 20}; InferenceEngine::Core ie; ie.AddExtension(std::make_shared()); - infer_model(ie, model, input_values, expected); + InferenceEngine::Blob::CPtr weights; + auto network = ie.ReadNetwork(model, weights); + infer_model(ie, network, input_values, expected); } @@ -320,84 +279,19 @@ TEST(Extension, XmlModelWithExtensionFromDSO) { std::vector expected{12, 13, 14, 15, 16, 17, 18, 19}; InferenceEngine::Core ie; ie.AddExtension(std::make_shared(get_extension_path())); - infer_model(ie, model, input_values, expected); + InferenceEngine::Blob::CPtr weights; + auto network = ie.ReadNetwork(model, weights); + infer_model(ie, network, input_values, expected); } TEST(Extension, OnnxModelWithExtensionFromDSO) { - std::string model = R"V0G0N( -ir_version: 3 -producer_name: "nGraph ONNX Importer" -graph { - node { - input: "A" - output: "Y" - name: "operation" - op_type: "Template" - domain: "custom_domain" - attribute { - name: "add" - type: INT - i: 11 - } - } - name: "test_graph" - input { - name: "A" - type { - tensor_type { - elem_type: 1 - shape { - dim { - dim_value: 2 - } - dim { - dim_value: 2 - } - dim { - dim_value: 2 - } - dim { - dim_value: 1 - } - } - } - } - } - output { - name: "Y" - type { - tensor_type { - elem_type: 1 - shape { - dim { - dim_value: 2 - } - dim { - dim_value: 2 - } - dim { - dim_value: 2 - } - dim { - dim_value: 1 - } - } - } - } - } -} -opset_import { - version: 1 - domain: "com.example" -} -)V0G0N"; - std::vector input_values{1, 2, 3, 4, 5, 6, 7, 8}; std::vector expected{12, 13, 14, 15, 16, 17, 18, 19}; InferenceEngine::Core ie; ie.AddExtension(std::make_shared(get_extension_path())); - infer_model(ie, model, input_values, expected); + auto network = ie.ReadNetwork(model_full_path("func_tests/models/custom_template_op.onnx")); + infer_model(ie, network, input_values, expected); } @@ -407,6 +301,7 @@ TEST(Extension, OnnxModelWithCustomReluDocsExample) { register_custom_relu_operator(); InferenceEngine::Core ie; - infer_model(ie, custom_relu_model(), input_values, expected); + auto network = ie.ReadNetwork(model_full_path("docs/models/custom_relu_model.onnx")); + infer_model(ie, network, input_values, expected); unregister_custom_relu_operator(); } diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/plugin/configuration_tests.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/plugin/configuration_tests.cpp index c90cd8b7249eee..a772c660d5b1d7 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/plugin/configuration_tests.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/behavior/plugin/configuration_tests.cpp @@ -63,6 +63,14 @@ namespace { {InferenceEngine::PluginConfigParams::KEY_PERFORMANCE_HINT, InferenceEngine::PluginConfigParams::THROUGHPUT}}, {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, {InferenceEngine::PluginConfigParams::KEY_PERFORMANCE_HINT, InferenceEngine::PluginConfigParams::LATENCY}}, + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, + {InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, InferenceEngine::PluginConfigParams::YES}}, + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, + {InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, + {InferenceEngine::PluginConfigParams::KEY_EXCLUSIVE_ASYNC_REQUESTS, InferenceEngine::PluginConfigParams::YES}}, + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, + {InferenceEngine::PluginConfigParams::KEY_EXCLUSIVE_ASYNC_REQUESTS, InferenceEngine::PluginConfigParams::NO}}, {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, {InferenceEngine::PluginConfigParams::KEY_PERFORMANCE_HINT, InferenceEngine::PluginConfigParams::LATENCY}, {InferenceEngine::PluginConfigParams::KEY_PERFORMANCE_HINT_NUM_REQUESTS, "1"}} @@ -106,6 +114,10 @@ namespace { {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, {InferenceEngine::PluginConfigParams::KEY_PERFORMANCE_HINT, InferenceEngine::PluginConfigParams::THROUGHPUT}, {InferenceEngine::PluginConfigParams::KEY_PERFORMANCE_HINT_NUM_REQUESTS, "should be int"}}, + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, + {InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, "OFF"}}, + {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, + {InferenceEngine::PluginConfigParams::KEY_EXCLUSIVE_ASYNC_REQUESTS, "OFF"}}, {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, {InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, "OFF"}}, {{InferenceEngine::MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES , CommonTestUtils::DEVICE_CPU}, @@ -170,6 +182,10 @@ namespace { {{InferenceEngine::PluginConfigParams::KEY_CPU_THROUGHPUT_STREAMS, "8"}}, {{InferenceEngine::PluginConfigParams::KEY_CPU_BIND_THREAD, InferenceEngine::PluginConfigParams::NO}}, {{InferenceEngine::PluginConfigParams::KEY_CPU_BIND_THREAD, InferenceEngine::PluginConfigParams::YES}}, + {{InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, InferenceEngine::PluginConfigParams::YES}}, + {{InferenceEngine::PluginConfigParams::KEY_EXCLUSIVE_ASYNC_REQUESTS, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::PluginConfigParams::KEY_EXCLUSIVE_ASYNC_REQUESTS, InferenceEngine::PluginConfigParams::YES}}, {{InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_LIMIT, "10"}} }; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/hetero/synthetic.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/hetero/synthetic.cpp index 8c531cb2c151fb..7fdb749714146a 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/hetero/synthetic.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/hetero/synthetic.cpp @@ -11,6 +11,9 @@ namespace { using namespace HeteroTests; +// this tests load plugin by library name: this is not available during static linkage +#ifndef OPENVINO_STATIC_LIBRARY + INSTANTIATE_TEST_SUITE_P(smoke_SingleMajorNode, HeteroSyntheticTest, ::testing::Combine( ::testing::Values(std::vector{{"CPU0", "MKLDNNPlugin"}, {"CPU1", "MKLDNNPlugin"}}), @@ -22,4 +25,7 @@ INSTANTIATE_TEST_SUITE_P(nightly_RandomMajorNodes, HeteroSyntheticTest, ::testing::Values(std::vector{{"CPU0", "MKLDNNPlugin"}, {"CPU1", "MKLDNNPlugin"}}), ::testing::ValuesIn(HeteroTests::HeteroSyntheticTest::_randomMajorNodeFunctions)), HeteroSyntheticTest::getTestCaseName); + +#endif // !OPENVINO_STATIC_LIBRARY + } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/concat_transformation.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/concat_transformation.cpp index ffd5c2b1d43d80..818ebe8ec32d40 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/concat_transformation.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/concat_transformation.cpp @@ -38,10 +38,20 @@ const std::vector testValues = { { 256ul, ngraph::Shape({}), {0.f}, {2.55f}, {0.f}, {2.55f} } }, // FQ with unexpected quantizationLevels + { + { 14ul, ngraph::Shape({}), {0.f}, {15.f}, {0.f}, {1.5f} }, + { 14ul, ngraph::Shape({}), {0.f}, {15.f}, {0.f}, {1.5f} } + }, + // FQ with INT4 quantizationLevels { { 16ul, ngraph::Shape({}), {0.f}, {15.f}, {0.f}, {1.5f} }, { 16ul, ngraph::Shape({}), {0.f}, {15.f}, {0.f}, {1.5f} } }, + // FQ with INT4+INT8 quantizationLevels + { + { 16ul, ngraph::Shape({}), {0.f}, {15.f}, {0.f}, {1.5f} }, + { 256ul, ngraph::Shape({}), {0.f}, {2.55f}, {0.f}, {2.55f} } + }, }; const std::vector shapes = { diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp index 4662a7648ccfd3..b2d223c8f317a4 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp @@ -13,12 +13,11 @@ using namespace LayerTestsDefinitions; namespace { const std::vector netPrecisions = { ngraph::element::f32, - // ngraph::element::f16 + // ngraph::element::f16, }; const std::vector trasformationParamValues = { - LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(true), - LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(false), + LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams() }; const std::vector params = { @@ -55,15 +54,15 @@ const std::vector params "U8" }, { - { 16ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } }, + { 14ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } }, false, - { 16ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 254.f }, { -12.7f }, { 12.7f } }, + { 14ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 254.f }, { -12.7f }, { 12.7f } }, false, "Convolution", "FP32" }, { - { 16ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } }, + { 14ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 25.5f }, { 0.f }, { 25.5f } }, false, { 255ul, ngraph::Shape { 1, 1, 1, 1 }, { -12.7f }, { 12.7f }, { -12.7f }, { 12.7f } }, false, @@ -73,7 +72,7 @@ const std::vector params { { 256ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 255.f }, { 0.f }, { 25.5f } }, false, - { 16ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 254.f }, { -12.7f }, { 12.7f } }, + { 14ul, ngraph::Shape { 1, 1, 1, 1 }, { 0.f }, { 254.f }, { -12.7f }, { 12.7f } }, false, "Convolution", "FP32" @@ -97,8 +96,22 @@ const std::vector params { { 256ul, ngraph::Shape { 1 }, { 0.f }, { 255.f }, { -18.7f }, { 18.8f } }, true, - { 255ul, ngraph::Shape { 6, 1, 1, 1 }, { -0.6f }, { 0.6f }, - { -1.52806e-39f, -0.2, -0.3, -0.3, -0.2, -0.1 }, { 1.52806e-39f, 0.2, 0.3, 0.3, 0.2, 0.1 } }, + { + 255ul, ngraph::Shape { 6, 1, 1, 1 }, { -0.6f }, { 0.6f }, + { -1.52806e-39f, -0.2, -0.3, -0.3, -0.2, -0.1 }, { 1.52806e-39f, 0.2, 0.3, 0.3, 0.2, 0.1 } + }, + false, + "Convolution", + "U8" + }, + { + { 256ul, ngraph::Shape { 1 }, { 0.f }, { 255.f }, { -18.7f }, { 18.8f } }, + true, + { + 255ul, ngraph::Shape { 6, 1, 1, 1 }, { -0.6f }, { 0.6f }, + { -1.52806e-39f, -1.52806e-39f, -1.52806e-39f, -1.52806e-39f, -1.52806e-39f, -1.52806e-39f }, + { 1.52806e-39f, 1.52806e-39f, 1.52806e-39f, 1.52806e-39f, 1.52806e-39f, 1.52806e-39f } + }, false, "Convolution", "U8" diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp index 4ed701efeca1f0..5b1166b1577e15 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp @@ -46,14 +46,13 @@ const std::vector fakeQuantizeOnDataValues = { { 256ul, {}, { -127.5f }, { 0.f }, { -127.5f }, { 0.f } }, "Pooling", "U8" }, - // INT4 FQ's are not transformed and inferred via FP32 { { 16ul, {}, { 0.f }, { 1.5f }, { 0.f }, { 1.5f } }, - "Pooling", "FP32" + "Pooling", "U8" }, { - { 16ul, {}, { -8.f }, { 7.f }, { -0.8f }, { 0.7f } }, - "Pooling", "FP32" + { 16ul, {}, { -0.8f }, { 0.7f }, { -0.8f }, { 0.7f } }, + "Pooling", "I8" }, // INT16, INT32 FQ's are transformed, but updatePrecision = false for inference on CPU Plugin and inferred via FP32 { diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/experimental_detectron_roifeatureextractor.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/experimental_detectron_roifeatureextractor.cpp new file mode 100644 index 00000000000000..c2746ef43f6cb9 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/experimental_detectron_roifeatureextractor.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "single_layer_tests/experimental_detectron_roifeatureextractor.hpp" + +using namespace ov::test; +using namespace ov::test::subgraph; + +namespace { + +const std::vector outputSize = {7, 14}; +const std::vector samplingRatio = {1, 2, 3}; + +const std::vector> pyramidScales = { + {8, 16, 32, 64}, + {4, 8, 16, 32}, + {2, 4, 8, 16} +}; + +const std::vector> staticInputShape = { + static_shapes_to_test_representation({{1000, 4}, {1, 8, 200, 336}, {1, 8, 100, 168}, {1, 8, 50, 84}, {1, 8, 25, 42}}), + static_shapes_to_test_representation({{1000, 4}, {1, 16, 200, 336}, {1, 16, 100, 168}, {1, 16, 50, 84}, {1, 16, 25, 42}}), + static_shapes_to_test_representation({{1200, 4}, {1, 8, 200, 42}, {1, 8, 100, 336}, {1, 8, 50, 168}, {1, 8, 25, 84}}) +}; + +INSTANTIATE_TEST_SUITE_P(smoke_ExperimentalROI_static, ExperimentalDetectronROIFeatureExtractorLayerTest, + ::testing::Combine( + ::testing::ValuesIn(staticInputShape), + ::testing::ValuesIn(outputSize), + ::testing::ValuesIn(samplingRatio), + ::testing::ValuesIn(pyramidScales), + ::testing::Values(false), + ::testing::Values(ov::element::Type_t::f32), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ExperimentalDetectronROIFeatureExtractorLayerTest::getTestCaseName); + +const std::vector> dynamicInputShape = { + { + { + {{-1, 4}, {{1000, 4}, {1500, 4}, {2000, 4}}}, + {{1, 8, -1, -1}, {{1, 8, 200, 336}, {1, 8, 200, 42}, {1, 8, 200, 84}}}, + {{1, 8, -1, -1}, {{1, 8, 100, 168}, {1, 8, 100, 336}, {1, 8, 25, 42}}}, + {{1, 8, -1, -1}, {{1, 8, 50, 84}, {1, 8, 50, 168}, {1, 8, 100, 336}}}, + {{1, 8, -1, -1}, {{1, 8, 25, 42}, {1, 8, 25, 84}, {1, 8, 50, 168}}} + } + }, + { + { + {{-1, 4}, {{1000, 4}, {1100, 4}, {1200, 4}}}, + {{1, {8, 16}, -1, -1}, {{1, 8, 200, 336}, {1, 12, 200, 336}, {1, 16, 200, 336}}}, + {{1, {8, 16}, -1, -1}, {{1, 8, 100, 168}, {1, 12, 100, 168}, {1, 16, 100, 168}}}, + {{1, {8, 16}, -1, -1}, {{1, 8, 50, 84}, {1, 12, 50, 84}, {1, 16, 50, 84}}}, + {{1, {8, 16}, -1, -1}, {{1, 8, 25, 42}, {1, 12, 25, 42}, {1, 16, 25, 42}}} + } + } +}; + +INSTANTIATE_TEST_SUITE_P(smoke_ExperimentalROI_dynamic, ExperimentalDetectronROIFeatureExtractorLayerTest, + ::testing::Combine( + ::testing::ValuesIn(dynamicInputShape), + ::testing::ValuesIn(outputSize), + ::testing::ValuesIn(samplingRatio), + ::testing::ValuesIn(pyramidScales), + ::testing::Values(false), + ::testing::Values(ov::element::Type_t::f32), + ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ExperimentalDetectronROIFeatureExtractorLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp index 1639dabcb557d6..b85c7f4e646cec 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp @@ -31,7 +31,8 @@ const auto gatherNDArgsSubset1 = ::testing::Combine( {{2, 1}, {2, 1, 1}})), // Indices shape ::testing::ValuesIn(std::vector({0, 1})) // Batch dims ); -INSTANTIATE_TEST_SUITE_P(smoke_Set1, GatherNDLayerTest, + +INSTANTIATE_TEST_SUITE_P(smoke_GatherND5_Set1, GatherNDLayerTest, ::testing::Combine( gatherNDArgsSubset1, ::testing::ValuesIn(dPrecisions), @@ -40,6 +41,15 @@ INSTANTIATE_TEST_SUITE_P(smoke_Set1, GatherNDLayerTest, ::testing::Values({})), GatherNDLayerTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_GatherND8_Set1, GatherNDLayerTest, + ::testing::Combine( + gatherNDArgsSubset1, + ::testing::ValuesIn(dPrecisions), + ::testing::ValuesIn(iPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::Values({})), + GatherNDLayerTest::getTestCaseName); + const auto gatherNDArgsSubset2 = ::testing::Combine( ::testing::ValuesIn(std::vector>( {{15, 12, 20, 15, 2}, {15, 12, 18, 7, 17}})), // Data shape @@ -47,7 +57,8 @@ const auto gatherNDArgsSubset2 = ::testing::Combine( {{15, 12, 2}, {15, 12, 5, 9, 1, 3}})), // Indices shape ::testing::ValuesIn(std::vector({0, 1, 2})) // Batch dims ); -INSTANTIATE_TEST_SUITE_P(smoke_Set2, GatherNDLayerTest, + +INSTANTIATE_TEST_SUITE_P(smoke_GatherND5_Set2, GatherNDLayerTest, ::testing::Combine( gatherNDArgsSubset2, ::testing::ValuesIn(dPrecisions), @@ -55,4 +66,14 @@ INSTANTIATE_TEST_SUITE_P(smoke_Set2, GatherNDLayerTest, ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values({})), GatherNDLayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_GatherND8_Set2, GatherNDLayerTest, + ::testing::Combine( + gatherNDArgsSubset2, + ::testing::ValuesIn(dPrecisions), + ::testing::ValuesIn(iPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::Values({})), + GatherNDLayerTest::getTestCaseName); + } // namespace diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/slice.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/slice.cpp new file mode 100644 index 00000000000000..2543d44f99dd6f --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/slice.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "single_layer_tests/slice.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + +const std::vector inputPrecision = { + InferenceEngine::Precision::I8, + InferenceEngine::Precision::U8, + InferenceEngine::Precision::I16, + InferenceEngine::Precision::I32, + InferenceEngine::Precision::FP32 +}; + +std::vector test_cases = { + SliceSpecificParams{ { 16 }, { 4 }, { 12 }, { 1 }, { 0 } }, + SliceSpecificParams{ { 16 }, { 0 }, { 8 }, { 2 }, { 0 } }, + SliceSpecificParams{ { 20, 10, 5 }, { 0, 0}, { 10, 20}, { 1, 1 }, { 1, 0 } }, + SliceSpecificParams{ { 1, 2, 12, 100 }, { 0, 1, 0, 1 }, { 1, 2, 5, 100 }, { 1, 1, 1, 10 }, {} }, + SliceSpecificParams{ { 1, 12, 100 }, { 0, 9, 0 }, { 1, 11, 1 }, { 1, 1, 1 }, {} }, + SliceSpecificParams{ { 1, 12, 100 }, { 0, 1, 0 }, { 10, -1, 10 }, { 1, 1, 1 }, {} }, + SliceSpecificParams{ { 2, 12, 100 }, { 1, 12, 100 }, { 0, 7, 0 }, { -1, -1, -1 }, {} }, + SliceSpecificParams{ { 2, 12, 100 }, { 1, 4, 99 }, { 0, 9, 0 }, { -1, 2, -1 }, {} }, + SliceSpecificParams{ { 2, 12, 100 }, { -1, -1, -1 }, { 0, 4, 0 }, { -1, -2, -1 }, {} }, + SliceSpecificParams{ { 2, 12, 100 }, { -1, -1, -1 }, { 0, 0, 4 }, { -1, -1, -1 }, {2, 0, 1} }, + SliceSpecificParams{ { 2, 12, 100 }, { 0, 0, 4 }, { -5, -1, -1 }, { 1, 2, 1 }, {2, 0, 1} }, + SliceSpecificParams{ { 2, 2, 2, 2 }, { 0, 0, 0, 0 }, { 2, 2, 2, 2 }, { 1, 1, 1, 1 }, {} }, + SliceSpecificParams{ { 2, 2, 2, 2 }, { 1, 1, 1, 1 }, { 2, 2, 2, 2 }, { 1, 1, 1, 1 }, {} }, + SliceSpecificParams{ { 2, 2, 4, 3 }, { 0, 0, 0, 0 }, { 2, 2, 4, 3 }, { 1, 1, 2, 1 }, {} }, + SliceSpecificParams{ { 2, 2, 4, 2 }, { 1, 0, 0, 1 }, { 2, 2, 4, 2 }, { 1, 1, 2, 1 }, {} }, + SliceSpecificParams{ { 1, 2, 4, 2 }, { 0, 1, 0, 1 }, { 10, 2, 4, 2 }, { 1, 1, 2, 1 }, {} }, + SliceSpecificParams{ { 10, 2, 4, 2 }, { 9, 1, 3, 0 }, { 0, 0, 0, 1 }, { -1, -1, -1, 1 }, {} }, + SliceSpecificParams{ { 10, 2, 4, 2 }, { 19, 1, -1, 0 }, { -10, 0, 0, -1 }, { -1, -1, -1, 1 }, {} }, + SliceSpecificParams{ { 3, 2, 4, 200 }, { 0, 1, -1, -1 }, { 3, 2, 0, 0 }, { 1, 1, -2, -1 }, {} }, + SliceSpecificParams{ { 2, 4, 5, 5, 68 }, { 0, 1, 0, 0, 0 }, { + std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max() }, { 1, 1, 1, 1, 16 }, {} }, + SliceSpecificParams{ { 10, 12 }, { -1, 1 }, { -9999, 10 }, { -1, 1 }, {} }, + SliceSpecificParams{ { 5, 5, 5, 5 }, { -1, 0, -1, 0 }, { -50, -1, -60, -1 }, { -1, 1, -1, 1 }, {} }, + SliceSpecificParams{ { 1, 5, 32, 32 }, { 0, 2, 5, 4 }, { 1, 4, 28, 27 }, { 1, 1, 1, 1 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 1, 5, 32, 20 }, { 0, 1, 0, 0 }, { 1, 3, 32, 20 }, { 1, 1, 1, 1 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 2, 5, 32, 20 }, { 0, 0, 10, 0 }, { 1, 3, 20, 20 }, { 1, 1, 1, 1 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 1, 5, 32, 32 }, { 0, 0, 20, 20 }, { 1, 5, 25, 26 }, { 1, 1, 1, 2 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 2, 5, 32, 32 }, { 0, 0, 0, 20 }, { 1, 2, 30, 30 }, { 1, 1, 2, 1 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 1, 5, 32, 20 }, { 0, 0, 2, 10 }, { 1, 3, 32, 20 }, { 1, 1, 1, 1 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 2, 5, 32, 32 }, { 0, 1, 0, 10 }, { 1, 5, 32, 30 }, { 1, 1, 1, 1 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 1, 5, 32, 20 }, { 0, 1, 2, 10 }, { 1, 5, 32, 18 }, { 1, 1, 1, 2 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 2, 8, 32, 20 }, { 0, 0, 2, 10 }, { 1, 8, 32, 18 }, { 1, 2, 1, 2 }, { 0, 1, 2, 3 } }, + SliceSpecificParams{ { 2, 8, 32, 20 }, { 0, -20, -15 }, { 2, -5, 3 }, { 1, 1, 1 }, { 0, 2, 1 } }, + + // Plugin Error: Slice has zero dimension which is not allowed + // SliceSpecificParams{ { 2, 8, 32, 20 }, { 0, 0, 10 }, { 0, 32, 18 }, { 1, 1, 1 }, { 0, 1, 2 } }, + // SliceSpecificParams{ { 2, 8, 32, 20 }, { 0, 0, 10 }, { 1, 0, 20 }, { 1, 1, 1 }, { 0, 1, 2 } }, + // SliceSpecificParams{ { 2, 8, 32, 20 }, { 0, 4, 10 }, { 2, 8, 0 }, { 1, 1, 1 }, { 0, 1, 2 } }, + // SliceSpecificParams{ { 2, 8, 32, 20 }, { 0, 4, 10 }, { 2, 8, 0 }, { 1, 1, 1 }, { 0, 2, 1 } }, + // SliceSpecificParams{ { 2, 8, 32, 20 }, { 0, 4, 10 }, { 2, 8, 0 }, { 1, 1, 1 }, { 0, -2, -1 } }, +}; + +INSTANTIATE_TEST_SUITE_P( + smoke_MKLDNN, SliceLayerTest, + ::testing::Combine( + ::testing::ValuesIn(test_cases), + ::testing::ValuesIn(inputPrecision), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(InferenceEngine::Layout::ANY), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::Values(std::map())), + SliceLayerTest::getTestCaseName); + +} // namespace 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 32bd52a790b0fd..291d564533fd0c 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 @@ -39,7 +39,7 @@ std::vector disabledTestPatterns() { // 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|ref).*)", + R"(.*(BF|bf)16.*(jit_avx(?!5)|jit_sse|ref).*)", // TODO: Incorrect blob sizes for node BinaryConvolution_X R"(.*BinaryConvolutionLayerTest.*)", R"(.*ClampLayerTest.*netPrc=(I64|I32).*)", @@ -84,8 +84,6 @@ std::vector disabledTestPatterns() { R"(.*(Auto|Multi).*Behavior.*IncorrectConfigTests.*CanNotLoadNetworkWithIncorrectConfig.*)", R"(.*OVExecutableNetworkBaseTest.*(CanGetInputsInfoAndCheck|CanSetConfigToExecNet|canLoadCorrectNetworkToGetExecutableWithIncorrectConfig).*)", R"(.*Behavior.*CorrectConfigCheck.*(canSetConfigAndCheckGetConfig|canSetConfigTwiceAndCheckGetConfig).*CPU_BIND_THREAD=YES.*)", - // azure is failing after #6199 - R"(.*/NmsLayerTest.*)", // TODO: 56520 Accuracy mismatch R"(.*ReduceOpsLayerTest.*type=Mean_.*netPRC=(I64|I32).*)", R"(.*ReduceOpsLayerTest.*type=Mean_.*netPRC=U64.*)", @@ -103,8 +101,6 @@ std::vector disabledTestPatterns() { // CPU plugin does not support some precisions R"(smoke_CachingSupportCase_CPU/LoadNetworkCacheTestBase.CompareWithRefImpl/ReadConcatSplitAssign_f32_batch1_CPU)", - // Issue 66685 - R"(smoke_PrePostProcess.*resize_linear_nhwc.*)", // CPU plugin does not support some precisions R"(.*Behavior.*OVExecGraphImportExportTest.*elementType=(i8|u32).*)", R"(.*Behavior.*OVExecGraphImportExportTest.*elementType=(f16).*)", @@ -153,6 +149,8 @@ std::vector disabledTestPatterns() { // bad accuracy R"(.*smoke_FakeQuantizeLayerCPUTest_Decompos. *IS=_TS=\(\(4\.5\.6\.7\)\)_RS=\(\(1\.1\.6\.1\)\)_\(\(1\.5\.6\.1\)\)_\(\(1\.1\.1\.1\)\)_\(\(1\.1\.6\.1\)\).*)", + // Issue: 71121 + R"(.*smoke_Proposal*.*TS=\(2.*)", }; #define FIX_62820 0 @@ -167,7 +165,7 @@ std::vector disabledTestPatterns() { if (!InferenceEngine::with_cpu_x86_avx512_core()) { // on platforms which do not support bfloat16, we are disabling bf16 tests since there are no bf16 primitives, // tests are useless on such platforms - retVector.emplace_back(R"(.*BF16.*)"); + retVector.emplace_back(R"(.*(BF|bf)16.*)"); retVector.emplace_back(R"(.*bfloat16.*)"); } diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/activation.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/activation.cpp index c7342e95517800..f767af4a310f9a 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/activation.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/activation.cpp @@ -3,72 +3,118 @@ // #include +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "functional_test_utils/ov_tensor_utils.hpp" #include "test_utils/cpu_test_utils.hpp" using namespace InferenceEngine; using namespace CPUTestUtils; using namespace ngraph::helpers; +using namespace ov::test; namespace CPULayerTestsDefinitions { -typedef std::tuple< - LayerTestsDefinitions::activationParams, - CPUSpecificParams> - ActivationLayerCPUTestParamSet; +using ActivationLayerCPUTestParamSet = std::tuple< + std::vector, // Input shapes + std::vector, // Activation shapes + std::pair>, // Activation type and constant value + InferenceEngine::Precision, // Net precision + InferenceEngine::Precision, // Input precision + InferenceEngine::Precision, // Output precision + CPUSpecificParams>; class ActivationLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { + virtual public SubgraphBaseTest, public CPUTestsBase { public: ActivationTypes activationType; static std::string getTestCaseName(const testing::TestParamInfo &obj) { - LayerTestsDefinitions::activationParams basicParamsSet; + std::vector inputShapes; + std::vector activationShapes; + std::pair> activationTypeAndConstValue; + Precision netPrecision, inPrecision, outPrecision; CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = obj.param; + std::tie(inputShapes, activationShapes, activationTypeAndConstValue, netPrecision, inPrecision, outPrecision, cpuParams) = obj.param; std::ostringstream result; - result << LayerTestsDefinitions::ActivationLayerTest::getTestCaseName(testing::TestParamInfo( - basicParamsSet, 0)); - + result << LayerTestsDefinitions::activationNames[activationTypeAndConstValue.first] << "_"; + if (inputShapes.front().first.size() != 0) { + result << "IS=("; + for (const auto &shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result.seekp(-1, result.cur); + result << ")_"; + } + result << "TS="; + for (const auto& shape : inputShapes) { + for (const auto& item : shape.second) { + result << CommonTestUtils::vec2str(item) << "_"; + } + } + result << "AS=" << CommonTestUtils::vec2str(activationShapes) << "_"; + result << "ConstantsValue=" << CommonTestUtils::vec2str(activationTypeAndConstValue.second) << "_"; + result << "netPRC=" << netPrecision.name() << "_"; + result << "inPRC=" << inPrecision.name() << "_"; + result << "outPRC=" << outPrecision.name() << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); return result.str(); } - InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override { - int32_t data_start_from; - uint32_t data_range; + void generate_inputs(const std::vector& targetInputStaticShapes) override { + int32_t startFrom; + uint32_t range; int32_t resolution; - if (activationType == ActivationTypes::Exp && netPrecision == Precision::BF16) { - data_start_from = 0; - data_range = 2; + startFrom = 0; + range = 2; resolution = 32768; + } else if (activationType == ActivationTypes::Acosh) { + startFrom = 2; + range = 2; + resolution = 128; } else { - data_start_from = 0; - data_range = 15; + startFrom = 0; + range = 15; resolution = 32768; } - - return FuncTestUtils::createAndFillBlob(info.getTensorDesc(), data_range, data_start_from, resolution); + inputs.clear(); + const auto& funcInputs = function->inputs(); + for (int i = 0; i < funcInputs.size(); ++i) { + const auto& funcInput = funcInputs[i]; + ov::runtime::Tensor tensor; + if (funcInput.get_element_type().is_real()) { + tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(), targetInputStaticShapes[i], + range, startFrom, resolution); + } else { + tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(), targetInputStaticShapes[i]); + } + inputs.insert({funcInput.get_node_shared_ptr(), tensor}); + } } protected: void SetUp() override { - LayerTestsDefinitions::activationParams basicParamsSet; - CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = this->GetParam(); + targetDevice = CommonTestUtils::DEVICE_CPU; + std::vector inputShapes; + std::vector activationShapes; + std::pair> activationTypeAndConstValue; + Precision inPrecision, outPrecision; + CPUSpecificParams cpuParams; + std::tie(inputShapes, activationShapes, activationTypeAndConstValue, netPrecision, inPrecision, outPrecision, cpuParams) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; + activationType = activationTypeAndConstValue.first; + auto constantsValue = activationTypeAndConstValue.second; - std::pair, std::vector> shapes; - std::pair> activationDecl; - std::tie(activationDecl, netPrecision, inPrc, outPrc, inLayout, outLayout, shapes, targetDevice) = basicParamsSet; + inType = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inPrecision); + outType = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(outPrecision); selectedType = getPrimitiveType() + "_" + netPrecision.name(); - activationType = activationDecl.first; - auto constantsValue = activationDecl.second; + init_input_shapes(inputShapes); + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(ngPrc, {shapes.first}); - auto activation = ngraph::builder::makeActivation(params[0], ngPrc, activationType, shapes.second, constantsValue); + auto params = ngraph::builder::makeDynamicParams(ngPrc, {inputDynamicShapes.front()}); + auto activation = ngraph::builder::makeActivation(params[0], ngPrc, activationType, activationShapes, constantsValue); activation->get_rt_info() = getCPUInfo(); function = std::make_shared(ngraph::NodeVector{activation}, params, "Activation"); } @@ -79,13 +125,16 @@ class ActivationLayerCPUTest : public testing::WithParamInterface activationShapes = {}; + const std::map>> activationTypes = { {Sqrt, {{}}}, {Sigmoid, {{}}}, @@ -97,7 +146,7 @@ const std::map>> activationTypes {Swish, {{0.1f}}}, {HSwish, {{}}}, {Mish, {{}}}, - {PReLu, {{-0.01f}}}, + {PReLu, {{-0.01f}}}, {GeluErf, {{}}}, {GeluTanh, {{}}} }; @@ -108,24 +157,25 @@ std::vector cpuParams_4D = { CPUSpecificParams({nchw}, {nchw}, {}, {}) }; -std::map, std::vector>> basic4D = { - {{2, 4, 4, 1}, {{}}}, - {{2, 17, 5, 4}, {{}}}, +std::vector> basic4D = { + {{2, 4, 4, 1}}, + {{2, 17, 5, 4}} }; -std::vector netPrc = {Precision::BF16, Precision::FP32}; +std::vector netPrc = { + // TODO: Should be uncommented after PR #8339 merge + // Precision::BF16 + Precision::FP32 +}; const auto basicCases4D = ::testing::Combine( - ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation(basic4D)), + ::testing::Values(activationShapes), ::testing::ValuesIn(CommonTestUtils::combineParams(activationTypes)), ::testing::ValuesIn(netPrc), ::testing::Values(Precision::FP32), ::testing::Values(Precision::FP32), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::ValuesIn(CommonTestUtils::combineParams(basic4D)), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUSpecificParams(cpuParams_4D)) + ::testing::ValuesIn(filterCPUSpecificParams(cpuParams_4D)) ); INSTANTIATE_TEST_SUITE_P(smoke_Activation4D_Eltwise_CPU_BF16, ActivationLayerCPUTest, basicCases4D, ActivationLayerCPUTest::getTestCaseName); @@ -136,24 +186,67 @@ std::vector cpuParams_5D = { CPUSpecificParams({ncdhw}, {ncdhw}, {}, {}) }; -std::map, std::vector>> basic5D = { - {{2, 4, 3, 4, 1}, {{}}}, - {{2, 17, 7, 5, 4}, {{}}}, +std::vector> basic5D = { + {{2, 4, 3, 4, 1}}, + {{2, 17, 7, 5, 4}} }; const auto basicCases5D = ::testing::Combine( - ::testing::Combine( - ::testing::ValuesIn(CommonTestUtils::combineParams(activationTypes)), - ::testing::ValuesIn(netPrc), - ::testing::Values(Precision::FP32), - ::testing::Values(Precision::FP32), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::ValuesIn(CommonTestUtils::combineParams(basic5D)), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::ValuesIn(static_shapes_to_test_representation(basic5D)), + ::testing::Values(activationShapes), + ::testing::ValuesIn(CommonTestUtils::combineParams(activationTypes)), + ::testing::ValuesIn(netPrc), + ::testing::Values(Precision::FP32), + ::testing::Values(Precision::FP32), ::testing::ValuesIn(filterCPUSpecificParams(cpuParams_5D)) ); INSTANTIATE_TEST_SUITE_P(smoke_Activation5D_Eltwise_CPU_BF16, ActivationLayerCPUTest, basicCases5D, ActivationLayerCPUTest::getTestCaseName); + +const std::map>> activationTypesDynamicMath = { + {Log, {{}}}, + {Sign, {{}}}, + {Acos, {{}}}, + {Acosh, {{}}}, + {Asin, {{}}}, + {Asinh, {{}}}, + {Atan, {{}}}, + {Atanh, {{}}}, + {Cos, {{}}}, + {Cosh, {{}}}, + {Tan, {{}}}, + {HardSigmoid, {{0.2f, 0.5f}}}, + {Selu, {{1.6732f, 1.0507f}}}, + {Ceiling, {{}}} +}; + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32 +}; + +std::vector cpuParamsDynamicMath = { + CPUSpecificParams({}, {}, {}, {}) +}; + +std::vector> dynamicMathBasic = { + { + {{{-1, -1}, {{1, 50}, {5, 128}, {3, 64}}}}, + {{{-1, -1, -1, -1, -1, -1, -1, -1}, {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 3, 2, 3, 2, 3, 2, 3}, {3, 3, 3, 3, 3, 3, 3, 3}}}}, + {{{{1, 5}, 128}, {{1, 128}, {3, 128}, {5, 128}}}} + } +}; + +const auto dynamicMathBasicCases = ::testing::Combine( + ::testing::ValuesIn(dynamicMathBasic), + ::testing::Values(activationShapes), + ::testing::ValuesIn(CommonTestUtils::combineParams(activationTypesDynamicMath)), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(Precision::FP32), + ::testing::Values(Precision::FP32), + ::testing::ValuesIn(cpuParamsDynamicMath) +); + +INSTANTIATE_TEST_SUITE_P(smoke_Activation5D_dynamicMath_CPU, ActivationLayerCPUTest, dynamicMathBasicCases, ActivationLayerCPUTest::getTestCaseName); + } // namespace } // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/batch_to_space.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/batch_to_space.cpp index a1c583adfcc1b2..44f4a882e50c41 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/batch_to_space.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/batch_to_space.cpp @@ -2,56 +2,81 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include "shared_test_classes/base/ov_subgraph.hpp" #include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" using namespace InferenceEngine; using namespace CPUTestUtils; using namespace ngraph::opset3; +using namespace ov::test; namespace CPULayerTestsDefinitions { -typedef std::tuple< - LayerTestsDefinitions::batchToSpaceParamsTuple, - CPUSpecificParams> BatchToSpaceLayerCPUTestParamSet; +using BatchToSpaceLayerTestCPUParams = std::tuple< + std::vector, // Input shapes + std::vector, // block shape + std::vector, // crops begin + std::vector, // crops end + Precision , // Network precision + CPUSpecificParams>; -class BatchToSpaceCPULayerTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { +class BatchToSpaceCPULayerTest : public testing::WithParamInterface, + virtual public SubgraphBaseTest, public CPUTestsBase { public: - static std::string getTestCaseName(const testing::TestParamInfo &obj) { - LayerTestsDefinitions::batchToSpaceParamsTuple basicParamsSet; + static std::string getTestCaseName(const testing::TestParamInfo &obj) { + std::vector inputShapes; + std::vector blockShape, cropsBegin, cropsEnd; + Precision netPrecision; CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = obj.param; + std::tie(inputShapes, blockShape, cropsBegin, cropsEnd, netPrecision, cpuParams) = obj.param; std::ostringstream result; - result << LayerTestsDefinitions::BatchToSpaceLayerTest::getTestCaseName( - testing::TestParamInfo(basicParamsSet, 0)); + if (inputShapes.front().first.size() != 0) { + result << "IS=("; + for (const auto &shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result.seekp(-1, result.cur); + result << ")_"; + } + result << "TS="; + for (const auto& shape : inputShapes) { + for (const auto& item : shape.second) { + result << CommonTestUtils::vec2str(item) << "_"; + } + } + result << "blockShape=" << CommonTestUtils::vec2str(blockShape) << "_"; + result << "cropsBegin=" << CommonTestUtils::vec2str(cropsBegin) << "_"; + result << "cropsEnd=" << CommonTestUtils::vec2str(cropsEnd) << "_"; + result << "netPRC=" << netPrecision.name() << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); return result.str(); } protected: void SetUp() override { - LayerTestsDefinitions::batchToSpaceParamsTuple basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; + + std::vector inputShapes; + std::vector blockShape, cropsBegin, cropsEnd; + Precision netPrecision; CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = this->GetParam(); + std::tie(inputShapes, blockShape, cropsBegin, cropsEnd, netPrecision, cpuParams) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::vector inputShape; - std::vector blockShape, cropsBegin, cropsEnd; - InferenceEngine::Precision netPrecision; - std::tie(blockShape, cropsBegin, cropsEnd, inputShape, netPrecision, inPrc, outPrc, inLayout, outLayout, targetDevice) = basicParamsSet; - inPrc = outPrc = netPrecision; + + auto ngPrec = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + inType = outType = ngPrec; + + init_input_shapes(inputShapes); if (strcmp(netPrecision.name(), "U8") == 0) selectedType = std::string("ref_any_") + "I8"; else selectedType = std::string("ref_any_") + netPrecision.name(); - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); - auto paramOuts = ngraph::helpers::convert2OutputVector( - ngraph::helpers::castOps2Nodes(params)); - auto b2s = ngraph::builder::makeBatchToSpace(paramOuts[0], ngPrc, blockShape, cropsBegin, cropsEnd); + auto params = ngraph::builder::makeDynamicParams(ngPrec, {inputDynamicShapes.front()}); + auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); + auto b2s = ngraph::builder::makeBatchToSpace(paramOuts[0], ngPrec, blockShape, cropsBegin, cropsEnd); b2s->get_rt_info() = getCPUInfo(); ngraph::ResultVector results{std::make_shared(b2s)}; function = std::make_shared(results, params, "BatchToSpace"); @@ -61,119 +86,270 @@ class BatchToSpaceCPULayerTest : public testing::WithParamInterface precisions = { +const std::vector netPrecision = { Precision::U8, Precision::I8, Precision::I32, Precision::FP32, - Precision::BF16 + // TODO: Should be uncommented after PR #8339 merge + // Precision::BF16 }; const std::vector> blockShape4D1 = {{1, 1, 1, 2}, {1, 2, 2, 1}}; const std::vector> cropsBegin4D1 = {{0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 2, 0}}; const std::vector> cropsEnd4D1 = {{0, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 1, 1}}; -const std::vector> inputShapes4D1 = {{8, 16, 10, 10}, {16, 64, 13, 16}}; + +std::vector> staticInputShapes4D1 = { + {{8, 16, 10, 10}} +}; + +std::vector> dynamicInputShapes4D1 = { + { + {{{-1, -1, -1, -1}, {{8, 8, 6, 7}, {4, 10, 5, 5}, {12, 9, 7, 5}}}}, + {{{{4, 12}, {8, 16}, 6, -1}, {{8, 8, 6, 7}, {4, 10, 6, 5}, {12, 9, 6, 5}}}} + } +}; + +std::vector> dynamicInputShapes4D1Blocked = { + { + {{{-1, 16, -1, -1}, {{4, 16, 5, 8}, {8, 16, 7, 6}, {12, 16, 4, 5}}}} + } +}; const std::vector> blockShape4D2 = {{1, 2, 3, 4}, {1, 3, 4, 2}}; const std::vector> cropsBegin4D2 = {{0, 0, 0, 1}, {0, 0, 1, 2}}; const std::vector> cropsEnd4D2 = {{0, 0, 1, 0}, {0, 0, 3, 1}}; -const std::vector> inputShapes4D2 = {{48, 16, 7, 8}, {24, 32, 6, 6}}; -const std::vector cpuParams_4D = { +std::vector> staticInputShapes4D2 = { + {{24, 16, 7, 8}} +}; + +std::vector> dynamicInputShapes4D2 = { + { + {{{-1, -1, -1, -1}, {{48, 4, 7, 8}, {24, 8, 6, 7}, {24, 16, 5, 5}}}}, + {{{24, {4, 10}, -1, -1}, {{24, 8, 6, 7}, {24, 6, 7, 5}, {24, 4, 5, 5}}}} + } +}; + +std::vector> dynamicInputShapes4D2Blocked = { + { + {{-1, 16, -1, -1}, {{24, 16, 5, 5}, {24, 16, 6, 7}, {48, 16, 4, 4}}} + } +}; + +const std::vector cpuParamsWithBlock_4D = { CPUSpecificParams({nChw16c}, {nChw16c}, {}, {}), CPUSpecificParams({nChw8c}, {nChw8c}, {}, {}), CPUSpecificParams({nhwc}, {nhwc}, {}, {}), CPUSpecificParams({nchw}, {nchw}, {}, {}) }; -const auto batchToSpaceParamsSet4D1 = ::testing::Combine( - ::testing::Combine( - ::testing::ValuesIn(std::vector>({blockShape4D1})), - ::testing::ValuesIn(std::vector>({cropsBegin4D1})), - ::testing::ValuesIn(std::vector>({cropsEnd4D1})), - ::testing::ValuesIn(std::vector> ({inputShapes4D1})), - ::testing::ValuesIn(precisions), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(cpuParams_4D)); - -const auto batchToSpaceParamsSet4D2 = ::testing::Combine( - ::testing::Combine( - ::testing::ValuesIn(std::vector>({blockShape4D2})), - ::testing::ValuesIn(std::vector>({cropsBegin4D2})), - ::testing::ValuesIn(std::vector>({cropsEnd4D2})), - ::testing::ValuesIn(std::vector> ({inputShapes4D2})), - ::testing::ValuesIn(precisions), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), +const std::vector cpuParams_4D = { + CPUSpecificParams({nhwc}, {nhwc}, {}, {}), + CPUSpecificParams({nchw}, {nchw}, {}, {}) +}; + +const auto staticBatchToSpaceParamsSet4D1 = ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation(staticInputShapes4D1)), + ::testing::ValuesIn(blockShape4D1), + ::testing::ValuesIn(cropsBegin4D1), + ::testing::ValuesIn(cropsEnd4D1), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_4D)); + +const auto dynamicBatchToSpaceParamsSet4D1 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes4D1), + ::testing::ValuesIn(blockShape4D1), + ::testing::ValuesIn(cropsBegin4D1), + ::testing::ValuesIn(cropsEnd4D1), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParams_4D)); + +const auto dynamicBatchToSpaceParamsWithBlockedSet4D1 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes4D1Blocked), + ::testing::ValuesIn(blockShape4D1), + ::testing::ValuesIn(cropsBegin4D1), + ::testing::ValuesIn(cropsEnd4D1), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_4D)); + +const auto staticBatchToSpaceParamsSet4D2 = ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation(staticInputShapes4D2)), + ::testing::ValuesIn(blockShape4D2), + ::testing::ValuesIn(cropsBegin4D2), + ::testing::ValuesIn(cropsEnd4D2), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_4D)); + +const auto dynamicBatchToSpaceParamsSet4D2 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes4D2), + ::testing::ValuesIn(blockShape4D2), + ::testing::ValuesIn(cropsBegin4D2), + ::testing::ValuesIn(cropsEnd4D2), + ::testing::ValuesIn(netPrecision), ::testing::ValuesIn(cpuParams_4D)); -INSTANTIATE_TEST_SUITE_P(smoke_BatchToSpaceCPULayerTestCase1_4D, BatchToSpaceCPULayerTest, - batchToSpaceParamsSet4D1, BatchToSpaceCPULayerTest::getTestCaseName); +const auto dynamicBatchToSpaceParamsWithBlockedSet4D2 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes4D2Blocked), + ::testing::ValuesIn(blockShape4D2), + ::testing::ValuesIn(cropsBegin4D2), + ::testing::ValuesIn(cropsEnd4D2), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_4D)); + +INSTANTIATE_TEST_SUITE_P(smoke_StaticBatchToSpaceCPULayerTestCase1_4D, BatchToSpaceCPULayerTest, + staticBatchToSpaceParamsSet4D1, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCase1_4D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsSet4D1, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCaseWithBlocked1_4D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsWithBlockedSet4D1, BatchToSpaceCPULayerTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_BatchToSpaceCPULayerTestCase2_4D, BatchToSpaceCPULayerTest, - batchToSpaceParamsSet4D2, BatchToSpaceCPULayerTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_StaticBatchToSpaceCPULayerTestCase2_4D, BatchToSpaceCPULayerTest, + staticBatchToSpaceParamsSet4D2, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCase2_4D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsSet4D2, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCaseWithBlocked2_4D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsWithBlockedSet4D2, BatchToSpaceCPULayerTest::getTestCaseName); const std::vector> blockShape5D1 = {{1, 1, 2, 2, 1}, {1, 2, 1, 2, 2}}; const std::vector> cropsBegin5D1 = {{0, 0, 0, 0, 0}, {0, 0, 0, 3, 3}}; const std::vector> cropsEnd5D1 = {{0, 0, 0, 0, 0}, {0, 0, 1, 0, 1}}; -const std::vector> inputShapes5D1 = {{8, 16, 4, 10, 10}, {16, 32, 5, 8, 12}}; + +std::vector> staticInputShapes5D1 = { + {{8, 16, 4, 10, 10}} +}; + +std::vector> dynamicInputShapes5D1 = { + { + {{{-1, -1, -1, -1, -1}, {{8, 16, 4, 10, 10}, {16, 10, 5, 11, 9}, {24, 6, 6, 8, 8}}}}, + {{{{8, 16}, {8, 16}, {2, 7}, -1, -1}, {{8, 16, 2, 6, 8}, {8, 10, 4, 7, 5}, {16, 8, 7, 5, 10}}}} + } +}; + +std::vector> dynamicInputShapes5D1Blocked = { + { + {{{-1, 16, -1, -1, -1}, {{24, 16, 3, 6, 7}, {48, 16, 4, 5, 5}, {24, 16, 5, 8, 5}}}} + } +}; const std::vector> blockShape5D2 = {{1, 2, 4, 3, 1}, {1, 1, 2, 4, 3}}; const std::vector> cropsBegin5D2 = {{0, 0, 1, 2, 0}, {0, 0, 1, 0, 1}}; const std::vector> cropsEnd5D2 = {{0, 0, 1, 0, 1}, {0, 0, 1, 1, 1}}; -const std::vector> inputShapes5D2 = {{48, 16, 3, 3, 3}, {24, 32, 5, 3, 5}}; -const std::vector cpuParams_5D = { +std::vector> staticInputShapes5D2 = { + {{48, 16, 3, 3, 3}} +}; + +std::vector> dynamicInputShapes5D2 = { + { + {{{-1, -1, -1, -1, -1}, {{48, 4, 3, 3, 3}, {24, 16, 5, 3, 5}, {24, 8, 7, 5, 5}}}}, + {{{24, {8, 16}, {3, 5}, -1, -1}, {{24, 16, 3, 4, 3}, {24, 12, 5, 3, 5}, {24, 8, 4, 5, 5}}}}, + // special case + { + {{{1, 24}, {1, 16}, {1, 10}, {1, 10}, {1, 10}}, + { + {24, 16, 5, 3, 5}, + {24, 16, 5, 3, 5}, + {24, 16, 7, 5, 5} + }} + } + } +}; + +std::vector> dynamicInputShapes5D2Blocked = { + { + {{{-1, 16, -1, -1, -1}, {{24, 16, 4, 5, 5}, {48, 16, 3, 4, 3}, {24, 16, 5, 3, 5}}}} + } +}; + +const std::vector cpuParamsWithBlock_5D = { CPUSpecificParams({nCdhw16c}, {nCdhw16c}, {}, {}), CPUSpecificParams({nCdhw8c}, {nCdhw8c}, {}, {}), CPUSpecificParams({ndhwc}, {ndhwc}, {}, {}), CPUSpecificParams({ncdhw}, {ncdhw}, {}, {}) }; -const auto batchToSpaceParamsSet5D1 = ::testing::Combine( - ::testing::Combine( - ::testing::ValuesIn(blockShape5D1), - ::testing::ValuesIn(cropsBegin5D1), - ::testing::ValuesIn(cropsEnd5D1), - ::testing::ValuesIn(inputShapes5D1), - ::testing::ValuesIn(precisions), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), ::testing::ValuesIn(cpuParams_5D)); - -const auto batchToSpaceParamsSet5D2 = ::testing::Combine( - ::testing::Combine( - ::testing::ValuesIn(blockShape5D2), - ::testing::ValuesIn(cropsBegin5D2), - ::testing::ValuesIn(cropsEnd5D2), - ::testing::ValuesIn(inputShapes5D2), - ::testing::ValuesIn(precisions), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Precision::UNSPECIFIED), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), ::testing::ValuesIn(cpuParams_5D)); - -INSTANTIATE_TEST_SUITE_P(smoke_BatchToSpaceCPULayerTestCase1_5D, BatchToSpaceCPULayerTest, - batchToSpaceParamsSet5D1, BatchToSpaceCPULayerTest::getTestCaseName); - -INSTANTIATE_TEST_SUITE_P(smoke_BatchToSpaceCPULayerTestCase2_5D, BatchToSpaceCPULayerTest, - batchToSpaceParamsSet5D2, BatchToSpaceCPULayerTest::getTestCaseName); +const std::vector cpuParams_5D = { + CPUSpecificParams({ndhwc}, {ndhwc}, {}, {}), + CPUSpecificParams({ncdhw}, {ncdhw}, {}, {}) +}; + +const auto staticBatchToSpaceParamsSet5D1 = ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation(staticInputShapes5D1)), + ::testing::ValuesIn(blockShape5D1), + ::testing::ValuesIn(cropsBegin5D1), + ::testing::ValuesIn(cropsEnd5D1), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_5D)); + +const auto dynamicBatchToSpaceParamsSet5D1 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes5D1), + ::testing::ValuesIn(blockShape5D1), + ::testing::ValuesIn(cropsBegin5D1), + ::testing::ValuesIn(cropsEnd5D1), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParams_5D)); + +const auto dynamicBatchToSpaceParamsWithBlockedSet5D1 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes5D1Blocked), + ::testing::ValuesIn(blockShape5D1), + ::testing::ValuesIn(cropsBegin5D1), + ::testing::ValuesIn(cropsEnd5D1), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_5D)); + +const auto staticBatchToSpaceParamsSet5D2 = ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation(staticInputShapes5D2)), + ::testing::ValuesIn(blockShape5D2), + ::testing::ValuesIn(cropsBegin5D2), + ::testing::ValuesIn(cropsEnd5D2), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_5D)); + +const auto dynamicBatchToSpaceParamsSet5D2 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes5D2), + ::testing::ValuesIn(blockShape5D2), + ::testing::ValuesIn(cropsBegin5D2), + ::testing::ValuesIn(cropsEnd5D2), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParams_5D)); + +const auto dynamicBatchToSpaceParamsWithBlockedSet5D2 = ::testing::Combine( + ::testing::ValuesIn(dynamicInputShapes5D2Blocked), + ::testing::ValuesIn(blockShape5D2), + ::testing::ValuesIn(cropsBegin5D2), + ::testing::ValuesIn(cropsEnd5D2), + ::testing::ValuesIn(netPrecision), + ::testing::ValuesIn(cpuParamsWithBlock_5D)); + +INSTANTIATE_TEST_SUITE_P(smoke_StaticBatchToSpaceCPULayerTestCase1_5D, BatchToSpaceCPULayerTest, + staticBatchToSpaceParamsSet5D1, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCase1_5D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsSet5D1, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCaseWithBlocked1_5D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsWithBlockedSet5D1, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_StaticBatchToSpaceCPULayerTestCase2_5D, BatchToSpaceCPULayerTest, + staticBatchToSpaceParamsSet5D2, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCase2_5D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsSet5D2, BatchToSpaceCPULayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_DynamicBatchToSpaceCPULayerTestCaseWithBlocked2_5D, BatchToSpaceCPULayerTest, + dynamicBatchToSpaceParamsWithBlockedSet5D2, BatchToSpaceCPULayerTest::getTestCaseName); } // namespace } // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/concat.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/concat.cpp index 786abb33e4587e..d7281975f06670 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/concat.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/concat.cpp @@ -2,68 +2,82 @@ // SPDX-License-Identifier: Apache-2.0 // +#include "shared_test_classes/base/ov_subgraph.hpp" #include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" -using namespace InferenceEngine; +using namespace ov::test; using namespace CPUTestUtils; namespace CPULayerTestsDefinitions { typedef std::tuple< - size_t, // Concat axis - std::vector>, // Input shapes - InferenceEngine::Precision, // Network precision - std::string, // Device name + size_t, // Concat axis + std::vector, // Input shapes + ElementType, // Network precision CPUSpecificParams > concatCPUTestParams; class ConcatLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { + virtual public SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(testing::TestParamInfo obj) { int axis; - std::vector> inputShapes; - InferenceEngine::Precision netPrecision; - std::string targetName; + std::vector inputShapes; + ElementType netPrecision; CPUSpecificParams cpuParams; - std::tie(axis, inputShapes, netPrecision, targetName, cpuParams) = obj.param; + std::tie(axis, inputShapes, netPrecision, cpuParams) = obj.param; std::ostringstream result; - result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_"; + result << "IS="; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result << "TS="; + for (const auto& shape : inputShapes) { + result << "("; + if (!shape.second.empty()) { + for (const auto& itr : shape.second) { + result << CommonTestUtils::vec2str(itr); + } + } + result << ")_"; + } result << "axis=" << axis << "_"; - result << "netPRC=" << netPrecision.name() << "_"; - result << "trgDev=" << targetName << "_"; + result << "netPRC=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); return result.str(); } + protected: void SetUp() override { + targetDevice = CommonTestUtils::DEVICE_CPU; + int axis; - std::vector> inputShape; - InferenceEngine::Precision netPrecision; + std::vector inputShape; + ElementType netPrecision; CPUSpecificParams cpuParams; - std::tie(axis, inputShape, netPrecision, targetDevice, cpuParams) = this->GetParam(); - inPrc = outPrc = netPrecision; + std::tie(axis, inputShape, netPrecision, cpuParams) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - selectedType += std::string("_") + inPrc.name(); + selectedType += std::string("_") + InferenceEngine::details::convertPrecision(netPrecision).name(); + + init_input_shapes(inputShape); - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(ngPrc, inputShape); + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); auto paramOuts = ngraph::helpers::convert2OutputVector( ngraph::helpers::castOps2Nodes(params)); auto concat = std::make_shared(paramOuts, axis); - function = makeNgraphFunction(ngPrc, params, concat, "concat"); + function = makeNgraphFunction(netPrecision, params, concat, "ConcatCPU"); } }; TEST_P(ConcatLayerCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); - CheckPluginRelatedResults(executableNetwork, "Concatenation"); + run(); +// CheckPluginRelatedresult(executableNetwork, "Concatenation"); } namespace { @@ -89,151 +103,520 @@ const auto blocked16_4D_ref = CPUSpecificParams{{nChw16c}, {nChw16c}, {}, "ref"} const auto blocked16_5D_ref = CPUSpecificParams{{nCdhw16c}, {nCdhw16c}, {}, "ref"}; // List of precisions natively supported by mkldnn. -const std::vector netPrecisions = { - Precision::I8, - Precision::I32, - Precision::FP32, - Precision::BF16 +const std::vector netPrecisions = { + ElementType::i8, + ElementType::i32, + ElementType::f32, + ElementType::bf16 }; -INSTANTIATE_TEST_SUITE_P(concat_Concat4D_CPU_Block8inPlace, ConcatLayerCPUTest, +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block8_static, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(0, 1), - ::testing::Values(std::vector>{{1, 8, 3, 5}, - {1, 8, 3, 5}}), + ::testing::Values(1, 2, 3), + ::testing::Values(static_shapes_to_test_representation({{2, 16, 3, 5}, {2, 16, 3, 5}})), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_4D, planarChannels_4D, blocked8_4D)), + ::testing::Values(planar_4D_ref, planarChannels_4D, blocked8_4D_ref)), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block8, ConcatLayerCPUTest, +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block16_static, ConcatLayerCPUTest, ::testing::Combine( ::testing::Values(1, 2, 3), - ::testing::Values(std::vector>{{2, 16, 3, 5}, - {2, 16, 3, 5}}), + ::testing::Values(static_shapes_to_test_representation({{3, 32, 3, 5}, {3, 32, 3, 5}})), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_4D_ref, planarChannels_4D, blocked8_4D_ref)), + ::testing::Values(blocked16_4D_ref)), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block16inPlace, ConcatLayerCPUTest, +const std::vector> inputShapes4D_Block_axis1 = { + { + // {{dynamic shape}, {{static shape case1}, {static shape case2}, ...} + {{-1, 32, -1, -1}, {{2, 32, 5, 7}, {1, 32, 10, 2}, {3, 32, 1, 8}}}, // input 0 + {{-1, 16, -1, -1}, {{2, 16, 5, 7}, {1, 16, 10, 2}, {3, 16, 1, 8}}}, // input 1 + {{-1, 64, -1, -1}, {{2, 64, 5, 7}, {1, 64, 10, 2}, {3, 64, 1, 8}}} // input 2 + }, + { + {{{1, 5}, 32, {1, 10}, {2, 8}}, {{2, 32, 5, 7}, {1, 32, 10, 2}, {3, 32, 1, 8}}}, + {{{1, 3}, 16, {1, 10}, {2, 8}}, {{2, 16, 5, 7}, {1, 16, 10, 2}, {3, 16, 1, 8}}}, + {{{1, 3}, 64, {1, 10}, {2, 8}}, {{2, 64, 5, 7}, {1, 64, 10, 2}, {3, 64, 1, 8}}} + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block_dynamic_axis_1, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(0, 1), - ::testing::Values(std::vector>{{1, 32, 3, 5}, - {1, 32, 3, 5}}), + ::testing::Values(1), + ::testing::ValuesIn(inputShapes4D_Block_axis1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(blocked16_4D)), + ::testing::Values(blocked8_4D_ref, blocked16_4D_ref)), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block16, ConcatLayerCPUTest, +const std::vector> inputShapes4D_axis1 = { + { + {{-1, -1, -1, -1}, {{2, 32, 5, 7}, {1, 18, 10, 2}, {3, 8, 1, 8}}}, + {{-1, -1, -1, -1}, {{2, 16, 5, 7}, {1, 5, 10, 2}, {3, 3, 1, 8}}}, + {{-1, -1, -1, -1}, {{2, 64, 5, 7}, {1, 45, 10, 2}, {3, 1, 1, 8}}} + }, + { + {{{1, 3}, {8, 32}, {1, 10}, {2, 8}}, {{2, 32, 5, 7}, {1, 18, 10, 2}, {3, 8, 1, 8}}}, + {{{1, 3}, {3, 16}, {1, 10}, {2, 8}}, {{2, 16, 5, 7}, {1, 5, 10, 2}, {3, 3, 1, 8}}}, + {{{1, 3}, {1, 64}, {1, 10}, {2, 8}}, {{2, 64, 5, 7}, {1, 45, 10, 2}, {3, 1, 1, 8}}} + }, + { + {{{1, 18, 10, 2}}, {{1, 18, 10, 2}, {1, 18, 10, 2}}}, + {{-1, -1, -1, -1}, {{1, 3, 10, 2}, {1, 5, 10, 2}}}, + {{{1, 5, 10, 2}}, {{1, 5, 10, 2}, {1, 5, 10, 2}}} + }, + { + {{{-1, 8, -1, -1}}, {{2, 8, 5, 7}, {1, 8, 10, 2}}}, + {{{-1, 3, -1, -1}}, {{2, 3, 5, 7}, {1, 3, 10, 2}}}, + {{{-1, -1, -1, -1}}, {{2, 16, 5, 7}, {1, 7, 10, 2}}} + } +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_dynamic_axis_1, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(1, 2, 3), - ::testing::Values(std::vector>{{3, 32, 3, 5}, - {3, 32, 3, 5}}), + ::testing::Values(1), + ::testing::ValuesIn(inputShapes4D_axis1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(blocked16_4D_ref)), + ::testing::Values(planar_4D_ref, planarChannels_4D)), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(concat_Concat5D_CPU_Block8inPlace, ConcatLayerCPUTest, +const std::vector> inputShapes4D_Block_axis2 = { + { + {{-1, 16, -1, -1}, {{2, 16, 5, 7}, {1, 16, 16, 2}, {3, 16, 2, 8}}}, + {{-1, 16, -1, -1}, {{2, 16, 1, 7}, {1, 16, 3, 2}, {3, 16, 11, 8}}}, + {{-1, 16, -1, -1}, {{2, 16, 10, 7}, {1, 16, 5, 2}, {3, 16, 1, 8}}}, + }, + { + {{{1, 3}, 16, {2, 16}, {2, 8}}, {{2, 16, 5, 7}, {1, 16, 16, 2}, {3, 16, 2, 8}}}, + {{{1, 3}, 16, {1, 11}, {2, 8}}, {{2, 16, 1, 7}, {1, 16, 3, 2}, {3, 16, 11, 8}}}, + {{{1, 3}, 16, {1, 10}, {2, 8}}, {{2, 16, 10, 7}, {1, 16, 5, 2}, {3, 16, 1, 8}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block_dynamic_axis_2, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(0, 1), - ::testing::Values(std::vector>{{1, 16, 3, 5, 7}, - {1, 16, 3, 5, 7}}), + ::testing::Values(2), + ::testing::ValuesIn(inputShapes4D_Block_axis2), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_5D, planarChannels_5D, blocked8_5D)), + ::testing::Values(blocked8_4D_ref, blocked16_4D_ref)), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block8, ConcatLayerCPUTest, +const std::vector> inputShapes4D_axis2 = { + { + {{-1, -1, -1, -1}, {{2, 16, 5, 7}, {1, 16, 16, 2}, {3, 16, 2, 8}}}, + {{-1, -1, -1, -1}, {{2, 16, 1, 7}, {1, 16, 3, 2}, {3, 16, 11, 8}}}, + {{-1, -1, -1, -1}, {{2, 16, 10, 7}, {1, 16, 5, 2}, {3, 16, 1, 8}}}, + }, + { + {{{1, 3}, {1, 16}, {2, 16}, {2, 8}}, {{2, 16, 5, 7}, {1, 16, 16, 2}, {3, 16, 2, 8}}}, + {{{1, 3}, {1, 16}, {1, 11}, {2, 8}}, {{2, 16, 1, 7}, {1, 16, 3, 2}, {3, 16, 11, 8}}}, + {{{1, 3}, {1, 16}, {1, 10}, {2, 8}}, {{2, 16, 10, 7}, {1, 16, 5, 2}, {3, 16, 1, 8}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_dynamic_axis_2, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(2, 3, 4), - ::testing::Values(std::vector>{{2, 16, 3, 5, 7}, - {2, 16, 3, 5, 7}}), + ::testing::Values(2), + ::testing::ValuesIn(inputShapes4D_axis2), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_5D_ref, planarChannels_5D, blocked8_5D_ref)), + ::testing::Values(planar_4D_ref, planarChannels_4D)), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block16inPlace, ConcatLayerCPUTest, +const std::vector> inputShapes4D_Block_axis3 = { + { + {{-1, 32, -1, -1}, {{2, 32, 4, 5}, {1, 32, 1, 16}, {3, 32, 7, 2}, }}, + {{-1, 32, -1, -1}, {{2, 32, 4, 1}, {1, 32, 1, 3}, {3, 32, 7, 11}}}, + {{-1, 32, -1, -1}, {{2, 32, 4, 10}, {1, 32, 1, 5}, {3, 32, 7, 1}}}, + }, + { + {{{1, 3}, 32, {1, 7}, {2, 16}}, {{2, 32, 4, 5}, {1, 32, 1, 16}, {3, 32, 7, 2}}}, + {{{1, 3}, 32, {1, 7}, {1, 11}}, {{2, 32, 4, 1}, {1, 32, 1, 3}, {3, 32, 7, 11}}}, + {{{1, 3}, 32, {1, 7}, {1, 10}}, {{2, 32, 4, 10}, {1, 32, 1, 5}, {3, 32, 7, 1}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block_dynamic_axis_3, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(0, 1), - ::testing::Values(std::vector>{{1, 32, 3, 5, 7}, - {1, 32, 3, 5, 7}}), + ::testing::Values(3), + ::testing::ValuesIn(inputShapes4D_Block_axis3), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(blocked16_5D)), + ::testing::Values(blocked8_4D_ref, blocked16_4D_ref)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes4D_axis3 = { + { + {{-1, -1, -1, -1}, {{2, 32, 4, 5}, {1, 32, 1, 16}, {3, 32, 7, 2}}}, + {{-1, -1, -1, -1}, {{2, 32, 4, 1}, {1, 32, 1, 3}, {3, 32, 7, 11}}}, + {{-1, -1, -1, -1}, {{2, 32, 4, 10}, {1, 32, 1, 5}, {3, 32, 7, 1}}}, + }, + { + {{{1, 3}, {1, 32}, {1, 7}, {2, 16}}, {{2, 32, 4, 5}, {1, 32, 1, 16}, {3, 32, 7, 2}}}, + {{{1, 3}, {1, 32}, {1, 7}, {1, 11}}, {{2, 32, 4, 1}, {1, 32, 1, 3}, {3, 32, 7, 11}}}, + {{{1, 3}, {1, 32}, {1, 7}, {1, 10}}, {{2, 32, 4, 10}, {1, 32, 1, 5}, {3, 32, 7, 1}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_dynamic_axis_3, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(3), + ::testing::ValuesIn(inputShapes4D_axis3), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_4D_ref, planarChannels_4D)), + ConcatLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block8_static, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(2, 3, 4), + ::testing::Values(static_shapes_to_test_representation({{2, 16, 3, 5, 7}, {2, 16, 3, 5, 7}})), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_5D_ref, planarChannels_5D, blocked8_5D_ref)), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block16, ConcatLayerCPUTest, +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block16_static, ConcatLayerCPUTest, ::testing::Combine( ::testing::Values(2, 3, 4), - ::testing::Values(std::vector>{{2, 32, 3, 5, 7}, - {2, 32, 3, 5, 7}}), + ::testing::Values(static_shapes_to_test_representation({{2, 32, 3, 5, 7}, {2, 32, 3, 5, 7}})), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(blocked16_5D_ref)), ConcatLayerCPUTest::getTestCaseName); +const std::vector> inputShapes5D_Block_axis1 = { + { + {{-1, 32, -1, -1, -1}, {{2, 32, 5, 7, 6}, {1, 32, 10, 2, 8}, {3, 32, 1, 8, 10}}}, + {{-1, 16, -1, -1, -1}, {{2, 16, 5, 7, 6}, {1, 16, 10, 2, 8}, {3, 16, 1, 8, 10}}}, + {{-1, 64, -1, -1, -1}, {{2, 64, 5, 7, 6}, {1, 64, 10, 2, 8}, {3, 64, 1, 8, 10}}}, + }, + { + {{{1, 3}, 32, {1, 10}, {2, 8}, {6, 10}}, {{2, 32, 5, 7, 6}, {1, 32, 10, 2, 8}, {3, 32, 1, 8, 10}}}, + {{{1, 3}, 16, {1, 10}, {2, 8}, {6, 10}}, {{2, 16, 5, 7, 6}, {1, 16, 10, 2, 8}, {3, 16, 1, 8, 10}}}, + {{{1, 3}, 64, {1, 10}, {2, 8}, {6, 10}}, {{2, 64, 5, 7, 6}, {1, 64, 10, 2, 8}, {3, 64, 1, 8, 10}}}, + }, +}; -INSTANTIATE_TEST_SUITE_P(smoke_Concat_inPlace, ConcatLayerCPUTest, +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block_dynamic_axis_1, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(0, 1, 2), - ::testing::Values(std::vector>{{1, 1, 1, 10}, - {1, 1, 1, 10}}, - std::vector>{{1, 1, 5}, - {1, 1, 5}}), + ::testing::Values(1), + ::testing::ValuesIn(inputShapes5D_Block_axis1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"})), + ::testing::Values(blocked8_5D_ref, blocked16_5D_ref)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes5D_axis1 = { + { + {{-1, -1, -1, -1, -1}, {{2, 5, 5, 7, 6}, {1, 3, 10, 2, 8}, {3, 4, 1, 8, 10}}}, + {{-1, -1, -1, -1, -1}, {{2, 16, 5, 7, 6}, {1, 20, 10, 2, 8}, {3, 5, 1, 8, 10}, }}, + {{-1, -1, -1, -1, -1}, {{2, 1, 5, 7, 6}, {1, 17, 10, 2, 8}, {3, 5, 1, 8, 10}}}, + }, + { + {{{1, 3}, {3, 5}, {1, 10}, {2, 8}, {6, 10}}, {{2, 5, 5, 7, 6}, {1, 3, 10, 2, 8}, {3, 4, 1, 8, 10}}}, + {{{1, 3}, {5, 20}, {1, 10}, {2, 8}, {4, 10}}, {{2, 16, 5, 7, 6}, {1, 20, 10, 2, 8}, {3, 5, 1, 8, 10}, }}, + {{{1, 3}, {1, 17}, {1, 10}, {2, 8}, {6, 10}}, {{2, 1, 5, 7, 6}, {1, 17, 10, 2, 8}, {3, 5, 1, 8, 10}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_dynamic_axis_1, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(1), + ::testing::ValuesIn(inputShapes5D_axis1), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_5D_ref, planarChannels_5D)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes5D_Block_axis2 = { + { + {{-1, 16, -1, -1, -1}, {{2, 16, 5, 8, 7}, {1, 16, 16, 1, 2}, {3, 16, 2, 5, 8}, }}, + {{-1, 16, -1, -1, -1}, {{2, 16, 1, 8, 7}, {1, 16, 3, 1, 2}, {3, 16, 11, 5, 8}}}, + {{-1, 16, -1, -1, -1}, {{2, 16, 10, 8, 7}, {1, 16, 5, 1, 2}, {3, 16, 1, 5, 8}}}, + }, + { + {{{1, 3}, 16, {2, 16}, {1, 8}, {2, 8}}, {{2, 16, 5, 8, 7}, {1, 16, 16, 1, 2}, {3, 16, 2, 5, 8}, }}, + {{{1, 5}, 16, {1, 11}, {1, 8}, {1, 8}}, {{2, 16, 1, 8, 7}, {1, 16, 3, 1, 2}, {3, 16, 11, 5, 8}}}, + {{{1, 6}, 16, {1, 10}, {1, 8}, {2, 10}}, {{2, 16, 10, 8, 7}, {1, 16, 5, 1, 2}, {3, 16, 1, 5, 8}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block_dynamic_axis_2, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(2), + ::testing::ValuesIn(inputShapes5D_Block_axis2), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked8_5D_ref, blocked16_5D_ref)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes5D_axis2 = { + { + {{-1, -1, -1, -1, -1}, {{2, 4, 5, 8, 7}, {1, 20, 16, 1, 2}, {3, 8, 2, 5, 8}}}, + {{-1, -1, -1, -1, -1}, {{2, 4, 1, 8, 7}, {1, 20, 3, 1, 2}, {3, 8, 11, 5, 8}}}, + {{-1, -1, -1, -1, -1}, {{2, 4, 10, 8, 7}, {1, 20, 5, 1, 2}, {3, 8, 1, 5, 8}}}, + }, + { + {{{1, 3}, {4, 20}, {1, 16}, {1, 8}, {2, 8}}, {{2, 4, 5, 8, 7}, {1, 20, 16, 1, 2}, {3, 8, 2, 5, 8}}}, + {{{1, 3}, {4, 20}, {1, 11}, {1, 10}, {1, 15}}, {{2, 4, 1, 8, 7}, {1, 20, 3, 1, 2}, {3, 8, 11, 5, 8}}}, + {{{1, 3}, {1, 20}, {1, 15}, {1, 10}, {2, 8}}, {{2, 4, 10, 8, 7}, {1, 20, 5, 1, 2}, {3, 8, 1, 5, 8}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_dynamic_axis_2, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(2), + ::testing::ValuesIn(inputShapes5D_axis2), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_5D_ref, planarChannels_5D)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes5D_Block_axis3 = { + { + {{-1, 32, -1, -1, -1}, {{2, 32, 4, 5, 7}, {1, 32, 1, 16, 3}, {3, 32, 7, 2, 4}}}, + {{-1, 32, -1, -1, -1}, {{2, 32, 4, 1, 7}, {1, 32, 1, 3, 3}, {3, 32, 7, 11, 4}}}, + {{-1, 32, -1, -1, -1}, {{2, 32, 4, 10, 7}, {1, 32, 1, 5, 3}, {3, 32, 7, 1, 4}}}, + }, + { + {{{1, 3}, 32, {1, 7}, {2, 16}, {3, 7}}, {{2, 32, 4, 5, 7}, {1, 32, 1, 16, 3}, {3, 32, 7, 2, 4}, }}, + {{{1, 5}, 32, {1, 7}, {1, 11}, {3, 7}}, {{2, 32, 4, 1, 7}, {1, 32, 1, 3, 3}, {3, 32, 7, 11, 4}}}, + {{{1, 6}, 32, {1, 15}, {1, 10}, {1, 20}}, {{2, 32, 4, 10, 7}, {1, 32, 1, 5, 3}, {3, 32, 7, 1, 4}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block_dynamic_axis_3, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(3), + ::testing::ValuesIn(inputShapes5D_Block_axis3), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked8_5D_ref, blocked16_5D_ref)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes5D_axis3 = { + { + {{-1, -1, -1, -1, -1}, {{2, 32, 4, 5, 7}, {1, 11, 1, 16, 3}, {3, 7, 7, 2, 4}}}, + {{-1, -1, -1, -1, -1}, {{2, 32, 4, 1, 7}, {1, 11, 1, 3, 3}, {3, 7, 7, 11, 4}}}, + {{-1, -1, -1, -1, -1}, {{2, 32, 4, 10, 7}, {1, 11, 1, 5, 3}, {3, 7, 7, 1, 4}}}, + }, + { + {{{1, 7}, {7, 32}, {1, 7}, {1, 16}, {3, 14}}, {{2, 32, 4, 5, 7}, {1, 11, 1, 16, 3}, {3, 7, 7, 2, 4}, }}, + {{{1, 7}, {7, 32}, {1, 10}, {1, 11}, {3, 7}}, {{2, 32, 4, 1, 7}, {1, 11, 1, 3, 3}, {3, 7, 7, 11, 4}}}, + {{{1, 7}, {1, 32}, {1, 10}, {1, 10}, {1, 10}}, {{2, 32, 4, 10, 7}, {1, 11, 1, 5, 3}, {3, 7, 7, 1, 4}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_dynamic_axis_3, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(3), + ::testing::ValuesIn(inputShapes5D_axis3), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_5D_ref, planarChannels_5D)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes5D_Block_axis4 = { + { + {{-1, 32, -1, -1, -1}, {{2, 32, 4, 5, 5}, {1, 32, 1, 1, 16}, {3, 32, 7, 9, 2}, }}, + {{-1, 32, -1, -1, -1}, {{2, 32, 4, 5, 1}, {1, 32, 1, 1, 3}, {3, 32, 7, 9, 11}}}, + {{-1, 32, -1, -1, -1}, {{2, 32, 4, 5, 10}, {1, 32, 1, 1, 5}, {3, 32, 7, 9, 1}}}, + }, + { + {{{1, 15}, 32, {1, 10}, {1, 10}, {1, 16}}, {{2, 32, 4, 5, 5}, {1, 32, 1, 1, 16}, {3, 32, 7, 9, 2}, }}, + {{{1, 15}, 32, {1, 10}, {1, 10}, {1, 11}}, {{2, 32, 4, 5, 1}, {1, 32, 1, 1, 3}, {3, 32, 7, 9, 11}}}, + {{{1, 15}, 32, {1, 10}, {1, 10}, {1, 11}}, {{2, 32, 4, 5, 10}, {1, 32, 1, 1, 5}, {3, 32, 7, 9, 1}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block_dynamic_axis_4, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(4), + ::testing::ValuesIn(inputShapes5D_Block_axis4), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked8_5D_ref, blocked16_5D_ref)), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes5D_axis4 = { + { + {{-1, -1, -1, -1, -1}, {{2, 1, 4, 5, 5}, {1, 4, 1, 1, 16}, {3, 14, 7, 9, 2}}}, + {{-1, -1, -1, -1, -1}, {{2, 1, 4, 5, 1}, {1, 4, 1, 1, 3}, {3, 14, 7, 9, 11}}}, + {{-1, -1, -1, -1, -1}, {{2, 1, 4, 5, 10}, {1, 4, 1, 1, 5}, {3, 14, 7, 9, 1}}}, + }, + { + {{{1, 3}, {1, 14}, {1, 7}, {1, 10}, {2, 16}}, {{2, 1, 4, 5, 5}, {1, 4, 1, 1, 16}, {3, 14, 7, 9, 2}}}, + {{{1, 3}, {1, 14}, {1, 7}, {1, 9}, {1, 11}}, {{2, 1, 4, 5, 1}, {1, 4, 1, 1, 3}, {3, 14, 7, 9, 11}}}, + {{{1, 3}, {1, 14}, {1, 7}, {1, 9}, {1, 10}}, {{2, 1, 4, 5, 10}, {1, 4, 1, 1, 5}, {3, 14, 7, 9, 1}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_dynamic_axis_4, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(4), + ::testing::ValuesIn(inputShapes5D_axis4), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_5D_ref, planarChannels_5D)), ConcatLayerCPUTest::getTestCaseName); +const std::vector> inputShapes_byBatch = { + static_shapes_to_test_representation({{5, 2, 2, 2}, {2, 2, 2, 2}}), + static_shapes_to_test_representation({{1, 3, 5}, {3, 3, 5}}), + static_shapes_to_test_representation({{4, 3, 2}, {1, 3, 2}}), + // 5D + { + {{-1, -1, -1, -1, -1}, {{10, 32, 4, 5, 5}, {4, 7, 1, 1, 3}, {3, 20, 7, 9, 1}, }}, + {{-1, -1, -1, -1, -1}, {{5, 32, 4, 5, 5}, {7, 7, 1, 1, 3}, {3, 20, 7, 9, 1}}}, + {{-1, -1, -1, -1, -1}, {{1, 32, 4, 5, 5}, {1, 7, 1, 1, 3}, {6, 20, 7, 9, 1}}}, + }, + { + {{{3, 10}, {7, 32}, {1, 9}, {1, 10}, {1, 5}}, {{10, 32, 4, 5, 5}, {4, 7, 1, 1, 3}, {3, 20, 7, 9, 1}, }}, + {{{3, 7}, {7, 32}, {1, 7}, {1, 9}, {1, 5}}, {{5, 32, 4, 5, 5}, {7, 7, 1, 1, 3}, {3, 20, 7, 9, 1}}}, + {{{1, 6}, {7, 32}, {1, 7}, {1, 9}, {1, 5}}, {{1, 32, 4, 5, 5}, {1, 7, 1, 1, 3}, {6, 20, 7, 9, 1}}}, + }, + // 4D + { + {{-1, -1, -1, -1}, {{10, 32, 4, 5}, {4, 7, 1, 1}, {3, 20, 7, 9}, }}, + {{-1, -1, -1, -1}, {{5, 32, 4, 5}, {7, 7, 1, 1}, {3, 20, 7, 9}}}, + {{-1, -1, -1, -1}, {{1, 32, 4, 5}, {1, 7, 1, 1}, {6, 20, 7, 9}}}, + }, + { + {{{1, 10}, {1, 32}, {1, 7}, {1, 9}}, {{10, 32, 4, 5}, {4, 7, 1, 1}, {3, 20, 7, 9}, }}, + {{{3, 7}, {7, 32}, {1, 7}, {1, 9}}, {{5, 32, 4, 5}, {7, 7, 1, 1}, {3, 20, 7, 9}}}, + {{{1, 6}, {7, 32}, {1, 7}, {1, 9}}, {{1, 32, 4, 5}, {1, 7, 1, 1}, {6, 20, 7, 9}}}, + } +}; + INSTANTIATE_TEST_SUITE_P(smoke_Concat_byBatch, ConcatLayerCPUTest, ::testing::Combine( ::testing::Values(0), - ::testing::Values(std::vector>{{5, 2, 2, 2}, - {2, 2, 2, 2}}, - std::vector>{{1, 3, 5}, - {3, 3, 5}}, - std::vector>{{4, 3, 2}, - {1, 3, 2}}), + ::testing::ValuesIn(inputShapes_byBatch), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"})), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat_3D, ConcatLayerCPUTest, +const std::vector> inputShapes3D_axis1 = { + static_shapes_to_test_representation({{2, 4, 5}, {2, 4, 5}}), + { + {{-1, -1, -1}, {{2, 5, 12}, {1, 16, 1}, {5, 2, 6}, }}, + {{-1, -1, -1}, {{2, 1, 12}, {1, 3, 1}, {5, 11, 6}}}, + {{-1, -1, -1}, {{2, 10, 12}, {1, 5, 1}, {5, 1, 6}}}, + }, + { + {{{1, 5}, {2, 16}, {1, 12}}, {{2, 5, 12}, {1, 16, 1}, {5, 2, 6}, }}, + {{{1, 5}, {1, 11}, {1, 21}}, {{2, 1, 12}, {1, 3, 1}, {5, 11, 6}}}, + {{{1, 5}, {1, 10}, {1, 12}}, {{2, 10, 12}, {1, 5, 1}, {5, 1, 6}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat_3D_axis1, ConcatLayerCPUTest, ::testing::Combine( - ::testing::Values(1, 2), - ::testing::Values(std::vector>{{2, 4, 5}, - {2, 4, 5}}), + ::testing::Values(1), + ::testing::ValuesIn(inputShapes3D_axis1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(CPUSpecificParams{{}, {}, {}, "ref"})), ConcatLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Concat_2D, ConcatLayerCPUTest, +const std::vector> inputShapes3D_axis2 = { + static_shapes_to_test_representation({{2, 4, 5}, {2, 4, 5}}), + { + {{-1, -1, -1}, {{4, 4, 5}, {3, 2, 16}, {1, 1, 2}}}, + {{-1, -1, -1}, {{4, 4, 1}, {3, 2, 3}, {1, 1, 11}}}, + {{-1, -1, -1}, {{4, 4, 10}, {3, 2, 5}, {1, 1, 1}}}, + }, + { + {{{1, 4}, {1, 4}, {2, 16}}, {{4, 4, 5}, {3, 2, 16}, {1, 1, 2}, }}, + {{{1, 4}, {1, 4}, {1, 11}}, {{4, 4, 1}, {3, 2, 3}, {1, 1, 11}}}, + {{{1, 4}, {1, 4}, {1, 10}}, {{4, 4, 10}, {3, 2, 5}, {1, 1, 1}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat_3D_axis2, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(2), + ::testing::ValuesIn(inputShapes3D_axis2), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CPUSpecificParams{{}, {}, {}, "ref"})), + ConcatLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes2D_axis1 = { + static_shapes_to_test_representation({{3, 2}, {3, 10}}), + { + {{-1, -1}, {{19, 5}, {1, 16}, {8, 2}, }}, + {{-1, -1}, {{19, 1}, {1, 3}, {8, 11}}}, + {{-1, -1}, {{19, 10}, {1, 5}, {8, 1}}}, + }, + { + {{{1, 19}, {2, 16}}, {{19, 5}, {1, 16}, {8, 2}, }}, + {{{1, 19}, {1, 11}}, {{19, 1}, {1, 3}, {8, 11}}}, + {{{1, 19}, {1, 10}}, {{19, 10}, {1, 5}, {8, 1}}}, + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Concat_2D_axis1, ConcatLayerCPUTest, ::testing::Combine( ::testing::Values(1), - ::testing::Values(std::vector>{{3, 2}, - {3, 10}}), + ::testing::ValuesIn(inputShapes2D_axis1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(CPUSpecificParams{{}, {}, {}, "ref"})), ConcatLayerCPUTest::getTestCaseName); +const std::vector> inputShapes1D = { + static_shapes_to_test_representation({ov::Shape{5}, ov::Shape{5}}), + static_shapes_to_test_representation({ov::Shape{2}, ov::Shape{2}}), + static_shapes_to_test_representation({ov::Shape{1}, ov::Shape{1}}), + static_shapes_to_test_representation({ov::Shape{3}, ov::Shape{3}}), + { + {{-1}, {{19}, {8}, {5}}}, + {{-1}, {{19}, {8}, {5}}}, + {{-1}, {{19}, {8}, {5}}}, + }, + { + {{{1, 20}}, {{19}, {8}, {5}}}, + {{{1, 20}}, {{19}, {8}, {5}}}, + {{{1, 20}}, {{19}, {8}, {5}}}, + }, +}; + INSTANTIATE_TEST_SUITE_P(smoke_Concat_1D, ConcatLayerCPUTest, - ::testing::Combine( - ::testing::Values(0), - ::testing::Values(std::vector>{{5}, - {2}, - {1}, - {3}}), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"})), - ConcatLayerCPUTest::getTestCaseName); + ::testing::Combine( + ::testing::Values(0), + ::testing::ValuesIn(inputShapes1D), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"})), + ConcatLayerCPUTest::getTestCaseName); + +// ============================================== inPlace cases ============================================ +INSTANTIATE_TEST_SUITE_P(concat_Concat4D_CPU_Block8inPlace, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(0, 1), + ::testing::Values(static_shapes_to_test_representation({{1, 8, 3, 5}, {1, 8, 3, 5}})), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_4D, planarChannels_4D, blocked8_4D)), + ConcatLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_Block16inPlace, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(0, 1), + ::testing::Values(static_shapes_to_test_representation({{1, 32, 3, 5}, {1, 32, 3, 5}})), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked16_4D)), + ConcatLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(concat_Concat5D_CPU_Block8inPlace, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(0, 1), + ::testing::Values(static_shapes_to_test_representation({{1, 16, 3, 5, 7}, {1, 16, 3, 5, 7}})), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_5D, planarChannels_5D, blocked8_5D)), + ConcatLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Concat5D_CPU_Block16inPlace, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(0, 1), + ::testing::Values(static_shapes_to_test_representation({{1, 32, 3, 5, 7}, {1, 32, 3, 5, 7}})), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked16_5D)), + ConcatLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Concat_inPlace, ConcatLayerCPUTest, + ::testing::Combine( + ::testing::Values(0, 1, 2), + ::testing::ValuesIn(std::vector>{ + static_shapes_to_test_representation({{1, 1, 1, 10}, {1, 1, 1, 10}}), + static_shapes_to_test_representation({{1, 1, 5}, {1, 1, 5}})}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"})), + ConcatLayerCPUTest::getTestCaseName); } // namespace + } // namespace CPULayerTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/convolution_backprop_data.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/convolution_backprop_data.cpp index df0fdc1e2abb98..bf319b82ca5ecc 100755 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/convolution_backprop_data.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/convolution_backprop_data.cpp @@ -51,6 +51,7 @@ class DeconvolutionLayerCPUTest : public testing::WithParamInterface padBegin, padEnd, outPadding; size_t convOutChannels; std::tie(kernel, stride, padBegin, padEnd, dilation, convOutChannels, padType, outPadding) = convParams; @@ -102,7 +103,14 @@ TEST_P(DeconvolutionLayerCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() Run(); - CheckPluginRelatedResults(executableNetwork, "Deconvolution"); + CPUTestsBase::CheckPluginRelatedResults(executableNetwork, "Deconvolution"); + bool isSupportedParams = stride[stride.size() - 1] <= kernel[kernel.size() - 1]; + if (stride.size() > 1) + isSupportedParams &= stride[stride.size() - 2] <= kernel[kernel.size() - 2]; + if (stride.size() > 2) + isSupportedParams &= stride[stride.size() - 3] <= kernel[kernel.size() - 3]; + if (isSupportedParams) + CheckFusingResults(executableNetwork, "Deconvolution"); } namespace { diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/cum_sum.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/cum_sum.cpp new file mode 100644 index 00000000000000..90a1d12b5dfd3a --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/cum_sum.cpp @@ -0,0 +1,259 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "test_utils/cpu_test_utils.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using namespace CPUTestUtils; + +namespace CPULayerTestsDefinitions { + +using cumSumShape = std::pair, std::vector>>; +using cumSumParams = std::tuple< + ngraph::element::Type, // data precision + cumSumShape, // input shape + std::int64_t, // axis + bool, // exclusive + bool>; // reverse + +class CumSumLayerCPUTest : public testing::WithParamInterface, public ov::test::SubgraphBaseTest, public CPUTestsBase { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + ngraph::element::Type inputPrecision; + std::pair, std::vector>> shapes; + std::int64_t axis; + bool exclusive; + bool reverse; + std::tie(inputPrecision, shapes, axis, exclusive, reverse) = obj.param; + + std::ostringstream result; + result << inputPrecision << "_" << "IS=" << CommonTestUtils::partialShape2str(shapes.first) << "_" << "TS="; + for (const auto& shape : shapes.second) { + result << "("; + for (const auto& item : shape) { + result << CommonTestUtils::vec2str(item) << "_"; + } + result << ")_"; + } + + result << "Axis=" << axis << "_" << (exclusive ? "exclusive" : "") << "_" << (reverse ? "reverse" : ""); + return result.str(); + } + +protected: + void SetUp() override { + targetDevice = CommonTestUtils::DEVICE_CPU; + ngraph::element::Type inputPrecision; + std::pair, std::vector>> shapes; + std::int64_t axis; + bool exclusive; + bool reverse; + std::tie(inputPrecision, shapes, axis, exclusive, reverse) = this->GetParam(); + + for (size_t i = 0; i < shapes.second.size(); i++) { + targetStaticShapes.push_back(shapes.second[i]); + } + inputDynamicShapes = shapes.first; + + auto params = ngraph::builder::makeDynamicParams(inputPrecision, { inputDynamicShapes.front() }); + auto axisNode = ngraph::opset1::Constant::create(ngraph::element::i32, ngraph::Shape{}, std::vector{axis})->output(0); + auto cumSum = ngraph::builder::makeCumSum(params[0], axisNode, exclusive, reverse); + + function = std::make_shared(ngraph::NodeVector{ cumSum }, params, "CumSumLayerCPUTest"); + functionRefs = ngraph::clone_function(*function); + } +}; + +TEST_P(CumSumLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + run(); + // TODO: Should be uncommented after updating the CheckPluginRelatedResults() method + //CheckPluginRelatedResults(executableNetwork, "CumSum"); +} + +const ngraph::element::TypeVector inputPrecision = { + ngraph::element::i8, + ngraph::element::u8, + ngraph::element::i16, + ngraph::element::i32, + ngraph::element::f32 +}; + +const std::vector axes = { 0, 1, 2, 3, 4, 5, 6 }; +const std::vector negativeAxes = { -1, -2, -3, -4, -5, -6 }; + +const std::vector exclusive = { true, false }; +const std::vector reverse = { true, false }; + +const std::vector inShapes = { + { + // dynamic + { + {-1} + }, + // target + { + {{16}, {18}, {12}} + } + }, + { + // dynamic + { + {-1, -1} + }, + // target + { + {{9, 15}, {18, 12}, {12, 12}} + } + }, + { + // dynamic + { + {-1, -1, -1} + }, + // target + { + {{16, 10, 12}, {18, 12, 10}, {12, 18, 10}} + } + }, + { + // dynamic + { + {-1, -1, -1, -1} + }, + // target + { + {{18, 20, 14, 12}, {19, 20, 14, 12}, {20, 22, 23, 25}} + } + }, + { + // dynamic + { + {-1, -1, -1, -1, -1} + }, + // target + { + {{2, 4, 6, 2, 4}, {3, 5, 6, 3, 5}, {1, 4, 2, 6, 8}} + } + }, + { + // dynamic + { + {-1, -1, -1, -1, -1, -1} + }, + // target + { + {{2, 4, 6, 2, 4, 2}, {3, 5, 6, 3, 5, 3}, {1, 4, 2, 6, 8, 1}} + } + }, + { + // dynamic + { + {-1, -1, -1, -1, -1, -1, -1} + }, + // target + { + {{2, 4, 6, 2, 4, 2, 4}, {3, 5, 6, 3, 5, 3, 5}, {1, 4, 2, 6, 8, 1, 4}} + } + }, + { + // dynamic + { + {{2, 5}, {3, 7}, {4, 8}, {5, 7}, {2, 5}, {3, 7}, {1, 2}} + }, + // target + { + {{2, 4, 6, 5, 4, 3, 1}, {3, 5, 6, 6, 5, 3, 1}, {5, 7, 4, 6, 3, 7, 2}} + } + }, + { + // dynamic + { + {{2, 5}, -1, {4, 8}, -1, -1, {3, 7}, -1} + }, + // target + { + {{2, 4, 6, 5, 4, 3, 1}, {3, 5, 6, 6, 5, 3, 1}, {5, 7, 4, 6, 3, 7, 2}} + } + }, +}; + +const auto testCasesAxis_0 = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(inShapes), + ::testing::Values(axes[0]), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +const auto testCasesAxis_1 = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(std::vector(inShapes.begin() + 1, inShapes.end())), + ::testing::Values(axes[1]), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +const auto testCasesAxis_2 = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(std::vector(inShapes.begin() + 2, inShapes.end())), + ::testing::Values(axes[2]), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +const auto testCasesAxis_3 = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(std::vector(inShapes.begin() + 3, inShapes.end())), + ::testing::Values(axes[3]), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +const auto testCasesAxis_4 = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(std::vector(inShapes.begin() + 4, inShapes.end())), + ::testing::Values(axes[4]), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +const auto testCasesAxis_5 = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(std::vector(inShapes.begin() + 5, inShapes.end())), + ::testing::Values(axes[5]), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +const auto testCasesAxis_6 = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(std::vector(inShapes.begin() + 6, inShapes.end())), + ::testing::Values(axes[6]), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +const auto testCasesAxis_negative = ::testing::Combine( + ::testing::ValuesIn(inputPrecision), + ::testing::ValuesIn(std::vector(inShapes.begin() + 6, inShapes.end())), + ::testing::ValuesIn(negativeAxes), + ::testing::ValuesIn(exclusive), + ::testing::ValuesIn(reverse) +); + +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_axis_0, CumSumLayerCPUTest, testCasesAxis_0, CumSumLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_axis_1, CumSumLayerCPUTest, testCasesAxis_1, CumSumLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_axis_2, CumSumLayerCPUTest, testCasesAxis_2, CumSumLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_axis_3, CumSumLayerCPUTest, testCasesAxis_3, CumSumLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_axis_4, CumSumLayerCPUTest, testCasesAxis_4, CumSumLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_axis_5, CumSumLayerCPUTest, testCasesAxis_5, CumSumLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_axis_6, CumSumLayerCPUTest, testCasesAxis_6, CumSumLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefsNumpy_negative_axes, CumSumLayerCPUTest, testCasesAxis_negative, CumSumLayerCPUTest::getTestCaseName); + +} // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp index f4d6df8e3b740e..4462137911ba0c 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/depth_to_space.cpp @@ -2,56 +2,78 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include "shared_test_classes/single_layer/depth_to_space.hpp" #include "test_utils/cpu_test_utils.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" + using namespace InferenceEngine; using namespace CPUTestUtils; using namespace ngraph::opset3; +using namespace ov::test; namespace CPULayerTestsDefinitions { -typedef std::tuple< - LayerTestsDefinitions::depthToSpaceParamsTuple, +using DepthToSpaceLayerCPUTestParamSet = std::tuple< + InputShape, // Input shape + ElementType, // Input element type + DepthToSpace::DepthToSpaceMode, // Mode + std::size_t, // Block size CPUSpecificParams -> DepthToSpaceLayerCPUTestParamSet; +>; class DepthToSpaceLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { + virtual public ov::test::SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(testing::TestParamInfo obj) { - LayerTestsDefinitions::depthToSpaceParamsTuple basicParamsSet; + InputShape shapes; + ElementType inType; + DepthToSpace::DepthToSpaceMode mode; + std::size_t blockSize; CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = obj.param; - - std::ostringstream result; - result << LayerTestsDefinitions::DepthToSpaceLayerTest::getTestCaseName( - testing::TestParamInfo(basicParamsSet, 0)); - - result << CPUTestsBase::getTestCaseName(cpuParams); - - return result.str(); + std::tie(shapes, inType, mode, blockSize, cpuParams) = obj.param; + + std::ostringstream results; + results << "IS=" << CommonTestUtils::partialShape2str({shapes.first}) << "_"; + results << "TS="; + for (const auto& item : shapes.second) { + results << CommonTestUtils::vec2str(item) << "_"; + } + results << "Prc=" << inType << "_"; + switch (mode) { + case DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST: + results << "BLOCKS_FIRST_"; + break; + case DepthToSpace::DepthToSpaceMode::DEPTH_FIRST: + results << "DEPTH_FIRST_"; + break; + default: + throw std::runtime_error("Unsupported DepthToSpaceMode"); + } + results << "BS=" << blockSize << "_"; + results << CPUTestsBase::getTestCaseName(cpuParams); + + return results.str(); } protected: void SetUp() override { - LayerTestsDefinitions::depthToSpaceParamsTuple basicParamsSet; + InputShape shapes; + ElementType inType; + DepthToSpace::DepthToSpaceMode mode; + std::size_t blockSize; CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = this->GetParam(); + std::tie(shapes, inType, mode, blockSize, cpuParams) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - - std::vector inputShape; - DepthToSpace::DepthToSpaceMode mode; - std::size_t blockSize; - InferenceEngine::Precision netPrecision; - std::tie(inputShape, netPrecision, mode, blockSize, targetDevice) = basicParamsSet; - - inPrc = outPrc = netPrecision; - selectedType = getPrimitiveType() + "_" + inPrc.name(); - auto inPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(inPrc, {inputShape}); - auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); - auto d2s = ngraph::builder::makeDepthToSpace(paramOuts[0], mode, blockSize); + if (selectedType.empty()) { + selectedType = getPrimitiveType(); + } + selectedType = selectedType + "_" + InferenceEngine::details::convertPrecision(inType).name(); + targetDevice = CommonTestUtils::DEVICE_CPU; + init_input_shapes({shapes}); + + auto params = ngraph::builder::makeDynamicParams(inType, inputDynamicShapes); + auto d2s = ngraph::builder::makeDepthToSpace(params[0], mode, blockSize); d2s->get_rt_info() = getCPUInfo(); ngraph::ResultVector results{std::make_shared(d2s)}; function = std::make_shared(results, params, "DepthToSpaceCPU"); @@ -61,35 +83,51 @@ class DepthToSpaceLayerCPUTest : public testing::WithParamInterface CPUParams4D = { + cpuParams_nhwc, + cpuParams_nchw +}; -const auto cpuParams_nhwc_ref = CPUSpecificParams {{nhwc}, {nhwc}, {"ref_any"}, {"ref_any"}}; -const auto cpuParams_ndhwc_ref = CPUSpecificParams {{ndhwc}, {ndhwc}, {"ref_any"}, {"ref_any"}}; +const std::vector CPUParamsBlocked4D = { + cpuParams_nChw16c, + cpuParams_nChw8c, + cpuParams_nhwc +}; +const std::vector CPUParams5D = { + cpuParams_ndhwc, + cpuParams_ncdhw +}; -const std::vector inputPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::BF16, - InferenceEngine::Precision::I8 +const std::vector CPUParamsBlocked5D = { + cpuParams_nCdhw16c, + cpuParams_nCdhw8c, + cpuParams_ndhwc +}; + +const std::vector inputElementType = { + ElementType::f32, + ElementType::bf16, + ElementType::i8 }; const std::vector depthToSpaceModes = { @@ -97,99 +135,162 @@ const std::vector depthToSpaceModes = { DepthToSpace::DepthToSpaceMode::DEPTH_FIRST }; -const std::vector> inputShapesBS2_4D = { - {1, 64, 1, 1}, {1, 64, 1, 3}, {1, 128, 3, 3}, {2, 128, 1, 1}, {1, 192, 2, 2}, {2, 256, 2, 3}, {1, 512, 2, 1} +/* *========================* Static Shapes Tests *========================* */ + +namespace static_shapes { + +const std::vector inputShapesBS2_4D = { + {1, 64, 1, 1}, + {1, 64, 1, 3}, + {1, 128, 3, 3}, + {2, 128, 1, 1}, + {1, 192, 2, 2}, + {2, 256, 2, 3}, + {1, 512, 2, 1} }; -const std::vector> inputShapesBS3_4D = { - {1, 27, 1, 1}, {1, 27, 2, 3}, {1, 18, 2, 3}, {3, 18, 1, 1}, {2, 18, 3, 1} +const std::vector inputShapesBS3_4D = { + {1, 27, 1, 1}, + {1, 27, 2, 3}, + {1, 18, 2, 3}, + {3, 18, 1, 1}, + {2, 18, 3, 1} }; -const std::vector CPUParamsBS2_4D = { - cpuParams_nChw16c, - cpuParams_nChw8c_avx2, - cpuParams_nChw8c_sse42, - cpuParams_nhwc_avx2, - cpuParams_nhwc_sse42, - cpuParams_nhwc_ref, +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceBS2_4D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::ValuesIn(static_shapes_to_test_representation(inputShapesBS2_4D)), + testing::ValuesIn(inputElementType), + testing::ValuesIn(depthToSpaceModes), + testing::Values(1, 2), + testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBlocked4D))), + DepthToSpaceLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceStaticBS3_4D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::ValuesIn(static_shapes_to_test_representation(inputShapesBS3_4D)), + testing::ValuesIn(inputElementType), + testing::ValuesIn(depthToSpaceModes), + testing::Values(1, 3), + testing::ValuesIn(filterCPUInfoForDevice(CPUParams4D))), + DepthToSpaceLayerCPUTest::getTestCaseName); + +const std::vector inputShapesBS2_5D = { + {1, 128, 1, 1, 1}, + {1, 128, 2, 1, 2}, + {1, 256, 2, 1, 3}, + {2, 256, 3, 1, 1}, + {1, 384, 1, 2, 2}, + {2, 512, 1, 2, 1} }; -const auto depthToSpaceBS2_4DParams = testing::Combine( - testing::Combine( - testing::ValuesIn(inputShapesBS2_4D), - testing::ValuesIn(inputPrecisions), - testing::ValuesIn(depthToSpaceModes), - testing::Values(1, 2), - testing::Values(CommonTestUtils::DEVICE_CPU)), - testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBS2_4D)) -); - -INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceBS2_4D, DepthToSpaceLayerCPUTest, depthToSpaceBS2_4DParams, DepthToSpaceLayerCPUTest::getTestCaseName); - -const std::vector CPUParamsBS3_4D = { - cpuParams_nhwc_avx2, - cpuParams_nhwc_sse42, - cpuParams_nhwc_ref, +const std::vector inputShapesBS3_5D = { + {1, 54, 1, 1, 1}, + {1, 54, 2, 1, 2}, + {3, 54, 1, 1, 1}, + {2, 54, 3, 1, 2}, + {1, 54, 3, 2, 2} }; -const auto depthToSpaceBS3_4DParams = testing::Combine( - testing::Combine( - testing::ValuesIn(inputShapesBS3_4D), - testing::ValuesIn(inputPrecisions), - testing::ValuesIn(depthToSpaceModes), - testing::Values(1, 3), - testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBS3_4D)) -); +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceStaticBS2_5D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::ValuesIn(static_shapes_to_test_representation(inputShapesBS2_5D)), + testing::ValuesIn(inputElementType), + testing::ValuesIn(depthToSpaceModes), + testing::Values(1, 2), + testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBlocked5D))), + DepthToSpaceLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceBS3_4D, DepthToSpaceLayerCPUTest, depthToSpaceBS3_4DParams, DepthToSpaceLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceStaticBS3_5D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::ValuesIn(static_shapes_to_test_representation(inputShapesBS3_5D)), + testing::ValuesIn(inputElementType), + testing::ValuesIn(depthToSpaceModes), + testing::Values(1, 3), + testing::ValuesIn(filterCPUInfoForDevice(CPUParams5D))), + DepthToSpaceLayerCPUTest::getTestCaseName); -const std::vector> inputShapesBS2_5D = { - {1, 128, 1, 1, 1}, {1, 128, 2, 1, 2}, {1, 256, 2, 1, 3}, {2, 256, 3, 1, 1}, {1, 384, 1, 2, 2}, {2, 512, 1, 2, 1} -}; +} // namespace static_shapes +/* *========================* *==================* *========================* */ -const std::vector> inputShapesBS3_5D = { - {1, 54, 1, 1, 1}, {1, 54, 2, 1, 2}, {3, 54, 1, 1, 1}, {2, 54, 3, 1, 2}, {1, 54, 3, 2, 2} + +/* *========================* Dynamic Shapes Tests *========================* */ +namespace dynamic_shapes { + +const std::vector inputShapes4D = { + {{-1, -1, -1 , -1}, // dynamic + {{2, 36, 1, 1}, {1, 36, 3, 1}, {1, 72, 1, 4}}}, // target + + {{-1, 576, -1 , -1}, // dynamic + {{1, 576, 1, 1}, {1, 576, 2, 2}, {3, 576, 4, 1}}}, // target + + {{{1, 5}, {36, 72}, {1, 16}, {1, 16}}, // dynamic + {{3, 36, 4, 4}, {1, 36, 16, 12}, {3, 72, 8, 8}}}, // target }; -const std::vector CPUParamsBS2_5D = { - cpuParams_nCdhw16c, - cpuParams_nCdhw8c_avx2, - cpuParams_nCdhw8c_sse42, - cpuParams_ndhwc_avx2, - cpuParams_ndhwc_sse42, - cpuParams_ndhwc_ref, +const std::vector inputShapes5D = { + {{-1, -1, -1, -1, -1}, // dynamic + {{2, 216, 1, 1, 1}, {1, 216, 3, 1, 2}, {1, 432, 2, 3, 1}}}, // target + + {{{1, 3}, {216, 432}, {1, 4}, {1, 4}, {1, 4}}, // dynamic + {{3, 216, 2, 2, 2}, {1, 432, 1, 1, 1}}}, // target }; -const auto depthToSpaceBS2_5DParams = testing::Combine( - testing::Combine( - testing::ValuesIn(inputShapesBS2_5D), - testing::ValuesIn(inputPrecisions), - testing::ValuesIn(depthToSpaceModes), - testing::Values(1, 2), - testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBS2_5D)) -); - -INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceBS2_5D, DepthToSpaceLayerCPUTest, depthToSpaceBS2_5DParams, DepthToSpaceLayerCPUTest::getTestCaseName); - -const std::vector CPUParamsBS3_5D = { - cpuParams_ndhwc_avx2, - cpuParams_ndhwc_sse42, - cpuParams_ndhwc_ref, +const std::vector inputShapesBlocked5D = { + {{-1, 256, -1, -1, -1}, // dynamic + {{1, 256, 1, 1, 1}, {1, 256, 2, 1, 4}, {3, 256, 4, 1, 2}}}, // target + + {{{1, 3}, 256, {1, 3}, {1, 3}, {1, 3}}, // dynamic + {{1, 256, 1, 1, 1}, {1, 256, 2, 1, 3}, {3, 256, 3, 1, 2}}}, // target }; -const auto depthToSpaceBS3_5DParams = testing::Combine( - testing::Combine( - testing::ValuesIn(inputShapesBS3_5D), - testing::ValuesIn(inputPrecisions), - testing::ValuesIn(depthToSpaceModes), - testing::Values(1, 3), - testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBS3_5D)) -); - -INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceBS3_5D, DepthToSpaceLayerCPUTest, depthToSpaceBS3_5DParams, DepthToSpaceLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceDynamic4D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::ValuesIn(inputShapes4D), + testing::ValuesIn(inputElementType), + testing::ValuesIn(depthToSpaceModes), + testing::Values(1, 2, 3), + testing::ValuesIn(filterCPUInfoForDevice(CPUParams4D))), + DepthToSpaceLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceDynamicBlocksFirstBlocked4D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::Values(inputShapes4D[1]), + testing::ValuesIn(inputElementType), + testing::Values(DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST), + testing::Values(1, 2, 3), + testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBlocked4D))), + DepthToSpaceLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceDynamicDepthFirstBlocked4D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::Values(inputShapes4D[1]), + testing::ValuesIn(inputElementType), + testing::Values(DepthToSpace::DepthToSpaceMode::DEPTH_FIRST), + testing::Values(1, 2), + testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBlocked4D))), + DepthToSpaceLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceDynamic5D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::ValuesIn(inputShapes5D), + testing::ValuesIn(inputElementType), + testing::ValuesIn(depthToSpaceModes), + testing::Values(1, 2, 3), + testing::ValuesIn(filterCPUInfoForDevice(CPUParams5D))), + DepthToSpaceLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_CPUDepthToSpaceDynamicCPUSpecific5D, DepthToSpaceLayerCPUTest, + testing::Combine( + testing::ValuesIn(inputShapesBlocked5D), + testing::ValuesIn(inputElementType), + testing::ValuesIn(depthToSpaceModes), + testing::Values(1, 2), + testing::ValuesIn(filterCPUInfoForDevice(CPUParamsBlocked5D))), + DepthToSpaceLayerCPUTest::getTestCaseName); + +} // namespace dynamic_shapes +/* *========================* *==================* *========================* */ } // namespace } // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gather_nd.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gather_nd.cpp new file mode 100644 index 00000000000000..13876aeb174ee1 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/gather_nd.cpp @@ -0,0 +1,193 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" + +using namespace InferenceEngine; +using namespace ov; +using namespace test; + +namespace CPULayerTestsDefinitions { + +using GatherNDLayerCPUTestParamSet = std::tuple< + InputShape, // Input shapes + std::pair>, // Indexes shape and values + ElementType, // Input element type + ElementType, // Indices element type + int // Batch dims +>; + +class GatherNDLayerCPUTest : public testing::WithParamInterface, + virtual public SubgraphBaseTest { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + InputShape shapes; + std::pair> indexes; + ElementType dataElementType, idxElementType; + int batchDims; + std::tie(shapes, indexes, dataElementType, idxElementType, batchDims) = obj.param; + + std::ostringstream results; + results << "IS=" << CommonTestUtils::partialShape2str({shapes.first}) << "_"; + results << "TS="; + for (const auto& item : shapes.second) { + results << CommonTestUtils::vec2str(item) << "_"; + } + results << "IDXShape=" << CommonTestUtils::vec2str(indexes.first) << "_"; + results << "SRCPrc=" << dataElementType << "_"; + results << "IDXPrc=" << idxElementType << "_"; + results << "BD=" << batchDims << "_"; + + return results.str(); +} + +protected: + void SetUp() override { + InputShape shapes; + std::pair> indexes; + ElementType dataElementType, idxElementType; + int batchDims; + std::tie(shapes, indexes, dataElementType, idxElementType, batchDims) = this->GetParam(); + + targetDevice = CommonTestUtils::DEVICE_CPU; + init_input_shapes({shapes}); + + auto params = ngraph::builder::makeDynamicParams(dataElementType, inputDynamicShapes); + auto indexes_node = ngraph::opset3::Constant::create(idxElementType, indexes.first, indexes.second); + auto gather_nd = std::make_shared(params[0], indexes_node, batchDims); + ngraph::ResultVector results{std::make_shared(gather_nd)}; + function = std::make_shared(results, params, "gatherND"); + } +}; + +class GatherND8LayerCPUTest : public testing::WithParamInterface, + virtual public SubgraphBaseTest { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + return GatherNDLayerCPUTest::getTestCaseName(obj); + } + +protected: + void SetUp() override { + InputShape shapes; + std::pair> indexes; + ElementType dataElementType, idxElementType; + int batchDims; + std::tie(shapes, indexes, dataElementType, idxElementType, batchDims) = this->GetParam(); + + targetDevice = CommonTestUtils::DEVICE_CPU; + init_input_shapes({shapes}); + + auto params = ngraph::builder::makeDynamicParams(dataElementType, inputDynamicShapes); + auto indexes_node = ngraph::opset3::Constant::create(idxElementType, indexes.first, indexes.second); + auto gather_nd = std::make_shared(params[0], indexes_node, batchDims); + ngraph::ResultVector results{std::make_shared(gather_nd)}; + function = std::make_shared(results, params, "gatherND"); + } +}; + +TEST_P(GatherNDLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + run(); +} + +TEST_P(GatherND8LayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + run(); +} + +namespace { + +const std::vector inputPrecisions = { + ElementType::f32, + ElementType::bf16, + ElementType::i8 +}; + +const std::vector indexesPrecisions = { + ElementType::i32 +}; + +const std::vector inputShapesDynamicBD_0 = { + {{-1, -1, -1}, // dynamic + {{5, 10, 5}, {4, 12, 4}, {4, 12, 4}, {5, 5, 5}}}, // target + + {{-1, 5, -1, -1}, // dynamic + {{8, 5, 5, 5}, {5, 5, 8, 4}, {4, 5, 4, 5}}}, // target + + {{{4, 10}, {5, 10}, {5, 10}, {5, 10}, {5, 10}}, // dynamic + {{4, 5, 5, 5, 5}, {4, 5, 5, 8, 5}, {10, 8, 5, 5, 5}}}, // target +}; + +const std::vector>> indexesShapesBD_0 = { + std::pair>{{2, 2}, {3, 3, 2, 1}}, + std::pair>{{1, 2, 3}, {0, 1, 1, 1, 0, 2}}, + std::pair>{{2, 1, 1, 2}, {0, 2, 1, 1}}, +}; + +const auto subset_BD0 = ::testing::Combine( + ::testing::ValuesIn(inputShapesDynamicBD_0), + ::testing::ValuesIn(indexesShapesBD_0), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(indexesPrecisions), + ::testing::Values(0)); + +INSTANTIATE_TEST_SUITE_P(smoke_GatherND5DynamicBD_0, GatherNDLayerCPUTest, subset_BD0, GatherNDLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_GatherND8DynamicBD_0, GatherND8LayerCPUTest, subset_BD0, GatherNDLayerCPUTest::getTestCaseName); + +const std::vector inputShapesDynamicBD_1 = { + {{3, -1, -1}, // dynamic + {{3, 10, 5}, {3, 10, 5}, {3, 12, 8}, {3, 8, 8}}}, // target + + {{3, {5, 10}, {5, 10}, {5, 10}, {5, 10}}, // dynamic + {{3, 5, 5, 5, 5}, {3, 8, 10, 10, 10}, {3, 8, 6, 8, 7}}}, // target +}; + +const std::vector>> indexesShapesBD_1 = { + std::pair>{{3, 2}, {0, 1, 2, 1, 0, 0}}, + std::pair>{{3, 2, 2}, {0, 1, 1, 1, 0, 2, 0, 1, 1, 1, 0, 2}}, + std::pair>{{3, 1, 1, 2}, {0, 2, 1, 1, 0, 2}}, +}; + +const auto subset_BD1 = ::testing::Combine( + ::testing::ValuesIn(inputShapesDynamicBD_1), + ::testing::ValuesIn(indexesShapesBD_1), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(indexesPrecisions), + ::testing::Values(0)); + +INSTANTIATE_TEST_SUITE_P(smoke_GatherND5DynamicBD_1, GatherNDLayerCPUTest, subset_BD1, GatherNDLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_GatherND8DynamicBD_1, GatherND8LayerCPUTest, subset_BD1, GatherNDLayerCPUTest::getTestCaseName); + +const std::vector inputShapesDynamicBD_2 = { + {{2, 2, -1, -1, -1}, // dynamic + {{2, 2, 5, 6, 5}, {2, 2, 2, 3, 3}, {2, 2, 2, 3, 3}, {2, 2, 7, 2, 3}}}, // target + + {{2, 2, {5, 10}, {5, 10}, {5, 10}}, // dynamic + {{2, 2, 5, 5, 5}, {2, 2, 10, 10, 5}, {2, 2, 7, 8, 7}}}, // target +}; + +const std::vector>> indexesShapesBD_2 = { + std::pair>{{2, 2, 3}, {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}}, + std::pair>{{2, 2, 2, 3}, {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0}}, +}; + +const auto subset_BD2 = ::testing::Combine( + ::testing::ValuesIn(inputShapesDynamicBD_2), + ::testing::ValuesIn(indexesShapesBD_2), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(indexesPrecisions), + ::testing::Values(0)); + +INSTANTIATE_TEST_SUITE_P(smoke_GatherND5DynamicBD_2, GatherNDLayerCPUTest, subset_BD2, GatherNDLayerCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_GatherND8DynamicBD_2, GatherND8LayerCPUTest, subset_BD2, GatherNDLayerCPUTest::getTestCaseName); + + +} // namespace +} // namespace CPULayerTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/group_convolution_backprop_data.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/group_convolution_backprop_data.cpp index 1f50a43b80d178..0a18a2bc74abc2 100755 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/group_convolution_backprop_data.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/group_convolution_backprop_data.cpp @@ -49,6 +49,7 @@ class GroupDeconvolutionLayerCPUTest : public testing::WithParamInterface padBegin, padEnd, outputPadding; size_t convOutChannels, numGroups; std::tie(kernel, stride, padBegin, padEnd, dilation, convOutChannels, numGroups, padType, outputPadding) = groupConvParams; @@ -101,7 +102,14 @@ TEST_P(GroupDeconvolutionLayerCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() Run(); - CheckPluginRelatedResults(executableNetwork, "Deconvolution"); + CPUTestsBase::CheckPluginRelatedResults(executableNetwork, "Deconvolution"); + bool isSupportedParams = stride[stride.size() - 1] <= kernel[kernel.size() - 1]; + if (stride.size() > 1) + isSupportedParams &= stride[stride.size() - 2] <= kernel[kernel.size() - 2]; + if (stride.size() > 2) + isSupportedParams &= stride[stride.size() - 3] <= kernel[kernel.size() - 3]; + if (isSupportedParams) + CheckFusingResults(executableNetwork, "Deconvolution"); } namespace { diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/log_softmax.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/log_softmax.cpp new file mode 100644 index 00000000000000..b3248d5aa2b299 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/log_softmax.cpp @@ -0,0 +1,127 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "test_utils/cpu_test_utils.hpp" +#include "ngraph_functions/builders.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using namespace CPUTestUtils; +using namespace ov::test; + +namespace CPULayerTestsDefinitions { + +using logSoftmaxLayerTestParams = std::tuple< + std::vector, // inputShape + Precision, // netPrecision + int64_t>; // axis + +class LogSoftmaxLayerCPUTest + : public testing::WithParamInterface, + public SubgraphBaseTest, + public CPUTestsBase { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + std::vector inputShapes; + Precision netPrecision; + int64_t axis; + std::tie(inputShapes, netPrecision, axis) = obj.param; + + std::ostringstream result; + if (inputShapes.front().first.size() != 0) { + result << "IS=("; + for (const auto &shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result.seekp(-1, result.cur); + result << ")_"; + } + result << "TS="; + for (const auto &shape : inputShapes) { + for (const auto &item : shape.second) { + result << CommonTestUtils::vec2str(item) << "_"; + } + } + result << "netPRC=" << netPrecision.name(); + result << "Axis=" << axis; + return result.str(); + } + +protected: + void SetUp() override { + targetDevice = CommonTestUtils::DEVICE_CPU; + + std::vector inputShapes; + Precision netPrecision; + int64_t axis; + std::tie(inputShapes, netPrecision, axis) = this->GetParam(); + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + inType = outType = ngPrc; + + selectedType = std::string("unknown_") + netPrecision.name(); + init_input_shapes(inputShapes); + + const auto params = ngraph::builder::makeDynamicParams(ngPrc, {inputDynamicShapes.front()}); + const auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); + const auto logSoftmax = std::make_shared(paramOuts[0], axis); + const ngraph::ResultVector results{std::make_shared(logSoftmax)}; + function = std::make_shared(results, params, "logSoftmax"); + } +}; + +TEST_P(LogSoftmaxLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + run(); + // TODO: Should be uncommented after updating the CheckPluginRelatedResults() method + // CheckPluginRelatedResults(executableNetwork, "logSoftmax"); +} + +namespace { +const std::vector netPrecisions = { + Precision::FP32 +}; + +const std::vector> inputShapes2D = { + { + {{{-1, -1}, {{1, 100}, {100, 1}, {10, 10}}}}, + {{{-1, {1}}, {{1, 1}, {100, 1}, {10, 1}}}} + } +}; + +const std::vector axis2D = { + -2, -1, 0, 1 +}; + +const auto params2D = testing::Combine( + testing::ValuesIn(inputShapes2D), + testing::ValuesIn(netPrecisions), + testing::ValuesIn(axis2D)); + +INSTANTIATE_TEST_SUITE_P(smoke_LogSoftmax2D_dynamic, LogSoftmaxLayerCPUTest, params2D, + LogSoftmaxLayerCPUTest::getTestCaseName); + +const std::vector> inputShapes4D = { + { + {{{-1, -1, -1, -1}, {{1, 100, 1, 1}, {1, 3, 4, 3}, {2, 3, 4, 5}}}}, + {{{{1, 2}, -1, {1, 5}, -1}, {{1, 100, 1, 1}, {1, 3, 5, 3}, {2, 3, 4, 5}}}} + } +}; + +const std::vector axis4D = { + -4, -3, -2, -1, 0, 1, 2, 3 +}; + +const auto params4D = testing::Combine( + testing::ValuesIn(inputShapes4D), + testing::ValuesIn(netPrecisions), + testing::ValuesIn(axis4D)); + +INSTANTIATE_TEST_SUITE_P(smoke_LogSoftmax4D_dynamic, LogSoftmaxLayerCPUTest, params4D, + LogSoftmaxLayerCPUTest::getTestCaseName); + +} // namespace +} // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/mat_mul.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/mat_mul.cpp index 8b87079f3b2479..0eccdbdce1cc31 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/mat_mul.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/mat_mul.cpp @@ -188,6 +188,8 @@ const std::vector IS3D = { {{{7, 32, 120}, true}, {{120, 50}, false}}, {{{7, 32, 120}, false}, {{120, 50}, true}}, {{{7, 32, 120}, true}, {{120, 50}, true}}, + + {{{1, 429}, false}, {{1, 429, 1}, true}}, }; std::vector fusingParamsSet3D { diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/non_max_suppression.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/non_max_suppression.cpp new file mode 100644 index 00000000000000..aad65a57160496 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/non_max_suppression.cpp @@ -0,0 +1,446 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" +#include "functional_test_utils/ov_tensor_utils.hpp" +#include "test_utils/cpu_test_utils.hpp" + +using namespace ov::test; +using namespace ngraph; +using namespace CPUTestUtils; + +namespace CPULayerTestsDefinitions { + +enum { + BATCHES, + BOXES, + CLASSES +}; + +using TargetShapeParams = std::tuple; // Number of classes + +using InputShapeParams = std::tuple, // bounds for input dynamic shape + std::vector>; // target input dimensions + +using InputPrecisions = std::tuple; // iou_threshold, score_threshold, soft_nms_sigma precisions + +using ThresholdValues = std::tuple; // Soft NMS sigma + +using NmsParams = std::tuple; // Device name + +class NmsLayerCPUTest : public testing::WithParamInterface, virtual public SubgraphBaseTest, public CPUTestsBase { +public: + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + InputShapeParams inShapeParams; + InputPrecisions inPrecisions; + int32_t maxOutBoxesPerClass; + ngraph::helpers::InputLayerType maxOutBoxesType; + ThresholdValues thrValues; + float iouThr, scoreThr, softNmsSigma; + op::v5::NonMaxSuppression::BoxEncodingType boxEncoding; + bool sortResDescend; + element::Type outType; + std::string targetDevice; + std::tie(inShapeParams, inPrecisions, maxOutBoxesPerClass, thrValues, maxOutBoxesType, boxEncoding, sortResDescend, outType, targetDevice) = obj.param; + + std::tie(iouThr, scoreThr, softNmsSigma) = thrValues; + + ElementType paramsPrec, maxBoxPrec, thrPrec; + std::tie(paramsPrec, maxBoxPrec, thrPrec) = inPrecisions; + + std::vector bounds; + std::vector targetShapes; + std::tie(bounds, targetShapes) = inShapeParams; + + std::ostringstream result; + if (!bounds.empty()) { + IE_ASSERT(bounds.size() == 3); + result << "BatchesBounds=" << bounds[BATCHES] << "_BoxesBounds=" << bounds[BOXES] << "_ClassesBounds=" << bounds[CLASSES] << "_"; + } + for (const auto &ts : targetShapes) { + size_t numBatches, numBoxes, numClasses; + std::tie(numBatches, numBoxes, numClasses) = ts; + result << "(nB=" << numBatches << "_nBox=" << numBoxes << "_nC=" << numClasses << ")_"; + } + result << "paramsPrec=" << paramsPrec << "_maxBoxPrec=" << maxBoxPrec << "_thrPrec=" << thrPrec << "_"; + result << "maxOutBoxesPerClass=" << maxOutBoxesPerClass << "_"; + result << "iouThr=" << iouThr << "_scoreThr=" << scoreThr << "_softNmsSigma=" << softNmsSigma << "_"; + result << "maxOutBoxesType=" << maxOutBoxesType << "_"; + result << "boxEncoding=" << boxEncoding << "_sortResDescend=" << sortResDescend << "_outType=" << outType << "_"; + result << "TargetDevice=" << targetDevice; + return result.str(); + } + + void generate_inputs(const std::vector& targetInputStaticShapes) override { + inputs.clear(); + const auto& funcInputs = function->inputs(); + for (int i = 0; i < funcInputs.size(); ++i) { + const auto& funcInput = funcInputs[i]; + ov::runtime::Tensor tensor; + + if (i == 1) { + tensor = ov::runtime::Tensor(funcInput.get_element_type(), targetInputStaticShapes[i]); + + const size_t range = 1; + const size_t startFrom = 0; + const size_t k = 1000; + const int seed = 1; + std::default_random_engine random(seed); + std::uniform_int_distribution distribution(k * startFrom, k * (startFrom + range)); + + auto *dataPtr = tensor.data(); + for (size_t i = 0; i < tensor.get_size(); i++) { + auto value = static_cast(distribution(random)); + dataPtr[i] = value / static_cast(k); + } + } else if (i == 2) { + tensor = ov::runtime::Tensor(funcInput.get_element_type(), targetInputStaticShapes[i], &maxOutBoxesPerClass); + } else { + tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(), targetInputStaticShapes[i]); + } + + inputs.insert({funcInput.get_node_shared_ptr(), tensor}); + } + } + void compare(const std::vector &expected, const std::vector &actual) override { + CompareBBoxes(expected, actual); + inferRequestNum++; + } + +protected: + void SetUp() override { + InputShapeParams inShapeParams; + InputPrecisions inPrecisions; + ThresholdValues thrValues; + ngraph::helpers::InputLayerType maxOutBoxesType; + float iouThr, scoreThr, softNmsSigma; + op::v5::NonMaxSuppression::BoxEncodingType boxEncoding; + bool sortResDescend; + element::Type outType; + std::tie(inShapeParams, inPrecisions, maxOutBoxesPerClass, thrValues, maxOutBoxesType, boxEncoding, sortResDescend, outType, + targetDevice) = this->GetParam(); + + element::Type paramsPrec, maxBoxPrec, thrPrec; + std::tie(paramsPrec, maxBoxPrec, thrPrec) = inPrecisions; + + std::tie(iouThr, scoreThr, softNmsSigma) = thrValues; + + std::vector bounds; + std::tie(bounds, targetInDims) = inShapeParams; + + if (!bounds.empty()) { + inputDynamicShapes = std::vector{{bounds[BATCHES], bounds[BOXES], 4}, {bounds[BATCHES], bounds[CLASSES], bounds[BOXES]}}; + } else { + size_t batches, boxes, classes; + std::tie(batches, boxes, classes) = targetInDims.front(); + ov::Dimension numBatches(batches), numBoxes(boxes), numClasses(classes); + inputDynamicShapes = std::vector{{numBatches, numBoxes, 4}, {numBatches, numClasses, numBoxes}}; + } + + for (const auto &ts : targetInDims) { + size_t numBatches, numBoxes, numClasses; + std::tie(numBatches, numBoxes, numClasses) = ts; + targetStaticShapes.push_back(std::vector{{numBatches, numBoxes, 4}, {numBatches, numClasses, numBoxes}}); + if (maxOutBoxesType == ngraph::helpers::InputLayerType::PARAMETER) { + targetStaticShapes.back().push_back(ngraph::Shape{1}); + } + } + + std::shared_ptr maxOutBoxesPerClassNode; + auto params = ngraph::builder::makeDynamicParams(paramsPrec, inputDynamicShapes); + params[0]->set_friendly_name("param_1"); + params[1]->set_friendly_name("param_2"); + + if (maxOutBoxesType == ngraph::helpers::InputLayerType::PARAMETER) { + inputDynamicShapes.push_back(ngraph::PartialShape{1}); + params.push_back(std::make_shared(element::Type_t::i32, inputDynamicShapes.back())); + params[1]->set_friendly_name("param_3"); + maxOutBoxesPerClassNode = params.back(); + } else { + maxOutBoxesPerClassNode = builder::makeConstant(maxBoxPrec, ngraph::Shape{}, std::vector{maxOutBoxesPerClass}); + } + + auto iouThrNode = builder::makeConstant(thrPrec, ngraph::Shape{}, std::vector{iouThr})->output(0); + auto scoreThrNode = builder::makeConstant(thrPrec, ngraph::Shape{}, std::vector{scoreThr})->output(0); + auto softNmsSigmaNode = builder::makeConstant(thrPrec, ngraph::Shape{}, std::vector{softNmsSigma})->output(0); + auto nms = std::make_shared(params[0], params[1], maxOutBoxesPerClassNode, iouThrNode, scoreThrNode, + softNmsSigmaNode, boxEncoding, sortResDescend, outType); + + function = makeNgraphFunction(paramsPrec, params, nms, "NMS"); + } + +private: + typedef struct Rect { + int32_t x1; + int32_t y1; + int32_t x2; + int32_t y2; + } Rect; + + class Box { + public: + Box() = default; + + Box(int32_t batchId, int32_t classId, int32_t boxId, Rect rect, float score) { + this->batchId = batchId; + this->classId = classId; + this->boxId = boxId; + this->rect = rect; + this->score = score; + } + + int32_t batchId; + int32_t classId; + int32_t boxId; + Rect rect; + float score; + }; + + /* + * 1: selected_indices - tensor of type T_IND and shape [number of selected boxes, 3] containing information about selected boxes as triplets + * [batch_index, class_index, box_index]. + * 2: selected_scores - tensor of type T_THRESHOLDS and shape [number of selected boxes, 3] containing information about scores for each selected box as triplets + * [batch_index, class_index, box_score]. + * 3: valid_outputs - 1D tensor with 1 element of type T_IND representing the total number of selected boxes. + */ + void CompareBBoxes(const std::vector &expectedOutputs, const std::vector &actualOutputs) { + size_t numBatches, numBoxes, numClasses; + std::tie(numBatches, numBoxes, numClasses) = targetInDims[inferRequestNum]; + + auto iouFunc = [](const Box& boxI, const Box& boxJ) { + const Rect& rectI = boxI.rect; + const Rect& rectJ = boxJ.rect; + + float areaI = (rectI.y2 - rectI.y1) * (rectI.x2 - rectI.x1); + float areaJ = (rectJ.y2 - rectJ.y1) * (rectJ.x2 - rectJ.x1); + + if (areaI <= 0.0f || areaJ <= 0.0f) { + return 0.0f; + } + + float intersection_ymin = std::max(rectI.y1, rectJ.y1); + float intersection_xmin = std::max(rectI.x1, rectJ.x1); + float intersection_ymax = std::min(rectI.y2, rectJ.y2); + float intersection_xmax = std::min(rectI.x2, rectJ.x2); + + float intersection_area = + std::max(intersection_ymax - intersection_ymin, 0.0f) * + std::max(intersection_xmax - intersection_xmin, 0.0f); + + return intersection_area / (areaI + areaJ - intersection_area); + }; + + // Get input bboxes' coords + std::vector> coordList(numBatches, std::vector(numBoxes)); + { + std::pair, ov::runtime::Tensor> bboxes = *inputs.begin(); + for (const auto &input : inputs) { + if (input.first->get_name() < bboxes.first->get_name()) { + bboxes = input; + } + } + + const auto buffer = bboxes.second.data(); + for (size_t i = 0; i < numBatches; ++i) { + for (size_t j = 0; j < numBoxes; ++j) { + const int32_t y1 = static_cast(buffer[(i*numBoxes+j)*4+0]); + const int32_t x1 = static_cast(buffer[(i*numBoxes+j)*4+1]); + const int32_t y2 = static_cast(buffer[(i*numBoxes+j)*4+2]); + const int32_t x2 = static_cast(buffer[(i*numBoxes+j)*4+3]); + + coordList[i][j] = { std::min(y1, y2), + std::min(x1, x2), + std::max(y1, y2), + std::max(x1, x2) }; + } + } + } + + auto compareBox = [](const Box& boxA, const Box& boxB) { + return (boxA.batchId < boxB.batchId) || + (boxA.batchId == boxB.batchId && boxA.classId < boxB.classId) || + (boxA.batchId == boxB.batchId && boxA.classId == boxB.classId && boxA.boxId < boxB.boxId); + }; + + // Get expected bboxes' index/score + std::vector expectedList; + { + const auto indeces_iter = expectedOutputs.begin(); + const auto scores_iter = expectedOutputs.begin() + 1; + size_t selected_indices_size = indeces_iter->get_size(); + size_t selected_scores_size = scores_iter->get_size(); + ASSERT_TRUE(selected_indices_size == selected_scores_size); + + expectedList.resize(selected_indices_size); + + if (indeces_iter->get_element_type() == ov::element::i32) { + auto selected_indices_data = indeces_iter->data(); + + for (size_t i = 0; i < selected_indices_size; i += 3) { + expectedList[i/3].batchId = selected_indices_data[i+0]; + expectedList[i/3].classId = selected_indices_data[i+1]; + expectedList[i/3].boxId = selected_indices_data[i+2]; + expectedList[i/3].rect = coordList[expectedList[i/3].batchId][expectedList[i/3].boxId]; + } + } else { + auto selected_indices_data = indeces_iter->data(); + + for (size_t i = 0; i < selected_indices_size; i += 3) { + expectedList[i/3].batchId = static_cast(selected_indices_data[i+0]); + expectedList[i/3].classId = static_cast(selected_indices_data[i+1]); + expectedList[i/3].boxId = static_cast(selected_indices_data[i+2]); + expectedList[i/3].rect = coordList[expectedList[i/3].batchId][expectedList[i/3].boxId]; + } + } + + if (scores_iter->get_element_type() == ov::element::f32) { + auto selected_scores_data = scores_iter->data(); + for (size_t i = 0; i < selected_scores_size; i += 3) { + expectedList[i/3].score = selected_scores_data[i+2]; + } + } else { + auto selected_scores_data = scores_iter->data(); + for (size_t i = 0; i < selected_scores_size; i += 3) { + expectedList[i/3].score = static_cast(selected_scores_data[i+2]); + } + } + + std::sort(expectedList.begin(), expectedList.end(), compareBox); + } + + // Get actual bboxes' index/score + std::vector actualList; + { + const auto indeces_iter = actualOutputs.begin(); + const auto scores_iter = actualOutputs.begin() + 1; + size_t selected_indices_size = indeces_iter->get_size(); + const auto selected_indices_data = indeces_iter->data(); + + const auto selected_scores_data = scores_iter->data(); + + for (size_t i = 0; i < selected_indices_size; i += 3) { + const int32_t batchId = selected_indices_data[i+0]; + const int32_t classId = selected_indices_data[i+1]; + const int32_t boxId = selected_indices_data[i+2]; + const float score = selected_scores_data[i+2]; + if (batchId == -1 || classId == -1 || boxId == -1) + break; + + actualList.emplace_back(batchId, classId, boxId, coordList[batchId][boxId], score); + } + std::sort(actualList.begin(), actualList.end(), compareBox); + } + + std::vector intersectionList; + std::vector differenceList; + { + std::list tempExpectedList(expectedList.size()), tempActualList(actualList.size()); + std::copy(expectedList.begin(), expectedList.end(), tempExpectedList.begin()); + std::copy(actualList.begin(), actualList.end(), tempActualList.begin()); + auto sameBox = [](const Box& boxA, const Box& boxB) { + return (boxA.batchId == boxB.batchId) && (boxA.classId == boxB.classId) && (boxA.boxId == boxB.boxId); + }; + + for (auto itA = tempActualList.begin(); itA != tempActualList.end(); ++itA) { + bool found = false; + for (auto itB = tempExpectedList.begin(); itB != tempExpectedList.end(); ++itB) { + if (sameBox(*itA, *itB)) { + intersectionList.emplace_back(*itB); + tempExpectedList.erase(itB); + found = true; + break; + } + } + + if (!found) { + differenceList.emplace_back(*itA); + } + } + differenceList.insert(differenceList.end(), tempExpectedList.begin(), tempExpectedList.end()); + + for (auto& item : differenceList) { + if ((item.rect.x1 == item.rect.x2) || (item.rect.y1 == item.rect.y2)) + continue; + + float maxIou = 0.f; + for (auto& refItem : intersectionList) { + maxIou = std::max(maxIou, iouFunc(item, refItem)); + + if (maxIou > 0.3f) break; + } + + ASSERT_TRUE(maxIou > 0.3f) << "MaxIOU: " << maxIou + << ", expectedList.size(): " << expectedList.size() << ", actualList.size(): " << actualList.size() + << ", intersectionList.size(): " << intersectionList.size() << ", diffList.size(): " << differenceList.size() + << ", batchId: " << item.batchId << ", classId: " << item.classId << ", boxId: " << item.boxId + << ", score: " << item.score << ", coord: " << item.rect.x1 << ", " << item.rect.y1 << ", " << item.rect.x2 << ", " << item.rect.y2; + } + } + } + std::vector targetInDims; + size_t inferRequestNum = 0; + int32_t maxOutBoxesPerClass; +}; + +TEST_P(NmsLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + run(); + // CheckPluginRelatedResults(executableNetwork, "NonMaxSuppression"); +}; + +const std::vector inShapeParams = { + InputShapeParams{std::vector{-1, -1, -1}, std::vector{TargetShapeParams{2, 50, 50}, + TargetShapeParams{3, 100, 5}, + TargetShapeParams{1, 10, 50}}}, + InputShapeParams{std::vector{{1, 5}, {1, 100}, {10, 75}}, std::vector{TargetShapeParams{4, 15, 10}, + TargetShapeParams{5, 5, 12}, + TargetShapeParams{1, 35, 15}}} +}; + +const std::vector maxOutBoxPerClass = {5, 20}; +const std::vector threshold = {0.3f, 0.7f}; +const std::vector sigmaThreshold = {0.0f, 0.5f}; +const std::vector encodType = {op::v5::NonMaxSuppression::BoxEncodingType::CENTER, + op::v5::NonMaxSuppression::BoxEncodingType::CORNER}; +const std::vector sortResDesc = {true, false}; +const std::vector outType = {element::i32, element::i64}; +const std::vector maxBoxInputTypes = {ngraph::helpers::InputLayerType::PARAMETER, ngraph::helpers::InputLayerType::CONSTANT}; + +const auto nmsParams = ::testing::Combine(::testing::ValuesIn(inShapeParams), + ::testing::Combine(::testing::Values(ElementType::f32), + ::testing::Values(ElementType::i32), + ::testing::Values(ElementType::f32)), + ::testing::ValuesIn(maxOutBoxPerClass), + ::testing::Combine(::testing::ValuesIn(threshold), + ::testing::ValuesIn(threshold), + ::testing::ValuesIn(sigmaThreshold)), + ::testing::ValuesIn(maxBoxInputTypes), + ::testing::ValuesIn(encodType), + ::testing::ValuesIn(sortResDesc), + ::testing::ValuesIn(outType), + ::testing::Values(CommonTestUtils::DEVICE_CPU) +); + +INSTANTIATE_TEST_SUITE_P(smoke_NmsLayerCPUTest, NmsLayerCPUTest, nmsParams, NmsLayerCPUTest::getTestCaseName); + +} // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pad.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pad.cpp index d0838784ad18f9..9ce20e53bc3c1e 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pad.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pad.cpp @@ -4,57 +4,75 @@ #include #include "test_utils/cpu_test_utils.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov; +using namespace test; namespace CPULayerTestsDefinitions { -typedef std::tuple< - LayerTestsDefinitions::padLayerTestParamsSet, +using PadLayerCPUTestParamSet = std::tuple< + InputShape, // Input shape + ElementType, // Input element type + std::vector, // padsBegin + std::vector, // padsEnd + float, // argPadValue + ngraph::helpers::PadMode, // padMode CPUSpecificParams -> padLayerCPUTestParamsSet; +>; -class PadLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { +class PadLayerCPUTest : public testing::WithParamInterface, + virtual public SubgraphBaseTest, public CPUTestsBase { public: - static std::string getTestCaseName(testing::TestParamInfo obj) { - LayerTestsDefinitions::padLayerTestParamsSet basicParamsSet; + static std::string getTestCaseName(testing::TestParamInfo obj) { + InputShape shapes; + ElementType elementType; + std::vector padsBegin, padsEnd; + ngraph::helpers::PadMode padMode; + float argPadValue; CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = obj.param; - - std::ostringstream result; - result << LayerTestsDefinitions::PadLayerTest::getTestCaseName(testing::TestParamInfo( - basicParamsSet, 0)); - - result << CPUTestsBase::getTestCaseName(cpuParams); - - return result.str(); + std::tie(shapes, elementType, padsBegin, padsEnd, argPadValue, padMode, cpuParams) = obj.param; + + std::ostringstream results; + results << "IS=" << CommonTestUtils::partialShape2str({shapes.first}) << "_"; + results << "TS="; + for (const auto& item : shapes.second) { + results << CommonTestUtils::vec2str(item) << "_"; + } + results << "Prc=" << elementType << "_"; + results << "padsBegin=" << CommonTestUtils::vec2str(padsBegin) << "_"; + results << "padsEnd=" << CommonTestUtils::vec2str(padsEnd) << "_"; + if (padMode == ngraph::helpers::PadMode::CONSTANT) { + results << "Value=" << argPadValue << "_"; + } + results << "PadMode=" << padMode << "_"; + results << CPUTestsBase::getTestCaseName(cpuParams); + + return results.str(); } protected: void SetUp() override { - LayerTestsDefinitions::padLayerTestParamsSet basicParamsSet; + InputShape shapes; + ElementType elementType; + std::vector padsBegin, padsEnd; + ngraph::helpers::PadMode padMode; + float argPadValue; CPUSpecificParams cpuParams; - std::tie(basicParamsSet, cpuParams) = this->GetParam(); + std::tie(shapes, elementType, padsBegin, padsEnd, argPadValue, padMode, cpuParams) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - - InferenceEngine::SizeVector inputShape; - std::vector padsBegin, padsEnd; - float argPadValue; - ngraph::helpers::PadMode padMode; - InferenceEngine::Precision netPrecision; - std::tie(padsBegin, padsEnd, argPadValue, padMode, netPrecision, inPrc, outPrc, inLayout, inputShape, targetDevice) = - basicParamsSet; - - inPrc = outPrc = netPrecision; - selectedType = std::string("ref_") + netPrecision.name(); - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); - auto paramOuts = ngraph::helpers::convert2OutputVector( - ngraph::helpers::castOps2Nodes(params)); - auto pad = ngraph::builder::makePad(paramOuts[0], padsBegin, padsEnd, argPadValue, padMode); + if (selectedType.empty()) { + selectedType = getPrimitiveType(); + } + selectedType = selectedType + "_" + InferenceEngine::details::convertPrecision(inType).name(); + targetDevice = CommonTestUtils::DEVICE_CPU; + init_input_shapes({shapes}); + + auto params = ngraph::builder::makeDynamicParams(elementType, inputDynamicShapes); + auto pad = ngraph::builder::makePad(params[0], padsBegin, padsEnd, argPadValue, padMode); pad->get_rt_info() = getCPUInfo(); ngraph::ResultVector results{std::make_shared(pad)}; function = std::make_shared(results, params, "pad"); @@ -64,8 +82,10 @@ class PadLayerCPUTest : public testing::WithParamInterface inputPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::BF16, - InferenceEngine::Precision::I8 +const std::vector inputPrecisions = { + ElementType::f32, + ElementType::bf16, + ElementType::i8 }; const std::vector argPadValue = {0.f, 1.f, 2.5f, -1.f}; @@ -95,6 +117,8 @@ const std::vector padMode = { ngraph::helpers::PadMode::SYMMETRIC }; +/* *======================* Static Shapes Tests 4D *======================* */ + const std::vector> padsBegin4DConstBlocked = {{0, 0, 0, 0}, {0, 0, 1, 3}, {2, 16, 1, 0}, {0, 0, 2, 0}}; const std::vector> padsEnd4DConstBlocked = {{0, 0, 0, 0}, {0, 0, 2, 1}, {2, 0, 0, 1}, {1, 32, 2, 0}}; @@ -109,95 +133,142 @@ const std::vector CPUParams4DBlocked = { cpuParams_nChw8c, }; -const auto pad4DConstParamsBlocked = testing::Combine( - testing::ValuesIn(padsBegin4DConstBlocked), - testing::ValuesIn(padsEnd4DConstBlocked), - testing::ValuesIn(argPadValue), - testing::Values(ngraph::helpers::PadMode::CONSTANT), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 5, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) -); - INSTANTIATE_TEST_SUITE_P( smoke_CPUPad4DConstBlocked, PadLayerCPUTest, ::testing::Combine( - pad4DConstParamsBlocked, + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 5, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4DConstBlocked), + ::testing::ValuesIn(padsEnd4DConstBlocked), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), ::testing::ValuesIn(CPUParams4DBlocked)), PadLayerCPUTest::getTestCaseName ); +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPad4DConst, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 5, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4D), + ::testing::ValuesIn(padsEnd4D), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), + ::testing::Values(cpuParams_nhwc)), + PadLayerCPUTest::getTestCaseName +); -const auto pad4DConstParams = testing::Combine( - testing::ValuesIn(padsBegin4D), - testing::ValuesIn(padsEnd4D), - testing::ValuesIn(argPadValue), - testing::Values(ngraph::helpers::PadMode::CONSTANT), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 5, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPad4DBlocked, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 10, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4DBlocked), + ::testing::ValuesIn(padsEnd4DBlocked), + ::testing::Values(0), + ::testing::ValuesIn(padMode), + ::testing::ValuesIn(CPUParams4DBlocked)), + PadLayerCPUTest::getTestCaseName ); INSTANTIATE_TEST_SUITE_P( - smoke_CPUPad4DConst, + smoke_CPUPad4D, PadLayerCPUTest, ::testing::Combine( - pad4DConstParams, + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 10, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4DBlocked), + ::testing::ValuesIn(padsEnd4DBlocked), + ::testing::Values(0), + ::testing::ValuesIn(padMode), ::testing::Values(cpuParams_nhwc)), PadLayerCPUTest::getTestCaseName ); -const auto pad4DParamsBlocked = testing::Combine( - testing::ValuesIn(padsBegin4DBlocked), - testing::ValuesIn(padsEnd4DBlocked), - testing::Values(0), - testing::ValuesIn(padMode), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 10, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) +/* *======================* *=====================* *======================* */ + +/* *======================* Dynamic Shapes Tests 4D *======================* */ + +const std::vector inputShapesDynamic4D = { + {{-1, -1, -1, -1}, // dynamic + {{5, 36, 5, 5}, {3, 16, 10, 5}, {3, 24, 10, 10}}}, // target + + {{-1, 32, -1, -1}, // dynamic + {{5, 32, 5, 5}, {5, 32, 5, 8}, {3, 32, 8, 8}}}, // target + + {{{1, 5}, {16, 32}, {1, 16}, {1, 16}}, // dynamic + {{3, 16, 5, 5}, {5, 24, 5, 8}, {3, 32, 8, 8}}}, // target +}; + +const std::vector CPUParams4DDynamic = { + cpuParams_nhwc, + cpuParams_nchw +}; + +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPadDynamic4DConst, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapesDynamic4D), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4D), + ::testing::ValuesIn(padsEnd4D), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), + ::testing::ValuesIn(CPUParams4DDynamic)), + PadLayerCPUTest::getTestCaseName ); INSTANTIATE_TEST_SUITE_P( - smoke_CPUPad4DBlocked, + smoke_CPUPadDynamic4DConstBlocked, PadLayerCPUTest, ::testing::Combine( - pad4DParamsBlocked, + ::testing::Values(inputShapesDynamic4D[1]), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4DConstBlocked), + ::testing::ValuesIn(padsEnd4DConstBlocked), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), ::testing::ValuesIn(CPUParams4DBlocked)), PadLayerCPUTest::getTestCaseName ); -const auto pad4DParams = testing::Combine( - testing::ValuesIn(padsBegin4D), - testing::ValuesIn(padsEnd4D), - testing::Values(0), - testing::ValuesIn(padMode), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 10, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPadDynamic4D, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapesDynamic4D), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4D), + ::testing::ValuesIn(padsEnd4D), + ::testing::Values(0), + ::testing::ValuesIn(padMode), + ::testing::ValuesIn(CPUParams4DDynamic)), + PadLayerCPUTest::getTestCaseName ); INSTANTIATE_TEST_SUITE_P( - smoke_CPUPad4D, + smoke_CPUPadDynamic4DBlocked, PadLayerCPUTest, ::testing::Combine( - pad4DParams, - ::testing::Values(cpuParams_nhwc)), + ::testing::Values(inputShapesDynamic4D[1]), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin4DBlocked), + ::testing::ValuesIn(padsEnd4DBlocked), + ::testing::Values(0), + ::testing::ValuesIn(padMode), + ::testing::ValuesIn(CPUParams4DBlocked)), PadLayerCPUTest::getTestCaseName ); +/* *======================* *=====================* *======================* */ + +/* *======================* Static Shapes Tests 5D *======================* */ + const std::vector> padsBegin5DConstBlocked = {{0, 0, 0, 0, 0}, {0, 0, 1, 1, 0}, {2, 32, 1, 1, 0}, {0, 0, 1, 3, 1}, {0, 0, 0, 1, 0}}; const std::vector> padsEnd5DConstBlocked = {{0, 0, 0, 0, 0}, {1, 16, 1, 1, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 1, 1}, {0, 0, 1, 0, 1}}; @@ -212,94 +283,139 @@ const std::vector CPUParams5DBlocked = { cpuParams_nCdhw8c, }; -const auto pad5DConstParamsBlocked = testing::Combine( - testing::ValuesIn(padsBegin5DConstBlocked), - testing::ValuesIn(padsEnd5DConstBlocked), - testing::ValuesIn(argPadValue), - testing::Values(ngraph::helpers::PadMode::CONSTANT), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 5, 5, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) -); - INSTANTIATE_TEST_SUITE_P( smoke_CPUPad5DConstBlocked, PadLayerCPUTest, ::testing::Combine( - pad5DConstParamsBlocked, + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 5, 5, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5DConstBlocked), + ::testing::ValuesIn(padsEnd5DConstBlocked), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), ::testing::ValuesIn(CPUParams5DBlocked)), PadLayerCPUTest::getTestCaseName ); -const auto pad5DConstParams = testing::Combine( - testing::ValuesIn(padsBegin5D), - testing::ValuesIn(padsEnd5D), - testing::ValuesIn(argPadValue), - testing::Values(ngraph::helpers::PadMode::CONSTANT), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 10, 5, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPad5DConst, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 5, 5, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5D), + ::testing::ValuesIn(padsEnd5D), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), + ::testing::Values(cpuParams_ndhwc)), + PadLayerCPUTest::getTestCaseName ); INSTANTIATE_TEST_SUITE_P( - smoke_CPUPad5DConst, + smoke_CPUPad5DBlocked, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 5, 5, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5DBlocked), + ::testing::ValuesIn(padsEnd5DBlocked), + ::testing::Values(0), + ::testing::ValuesIn(padMode), + ::testing::ValuesIn(CPUParams5DBlocked)), + PadLayerCPUTest::getTestCaseName +); + +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPad5D, PadLayerCPUTest, ::testing::Combine( - pad5DConstParams, + ::testing::ValuesIn(static_shapes_to_test_representation({{3, 16, 5, 5, 5}})), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5D), + ::testing::ValuesIn(padsEnd5D), + ::testing::Values(0), + ::testing::ValuesIn(padMode), ::testing::Values(cpuParams_ndhwc)), PadLayerCPUTest::getTestCaseName ); -const auto pad5DParamsBlocked = testing::Combine( - testing::ValuesIn(padsBegin5DBlocked), - testing::ValuesIn(padsEnd5DBlocked), - testing::Values(0), - testing::ValuesIn(padMode), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 5, 5, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) +/* *======================* *=====================* *======================* */ + +/* *======================* Dynamic Shapes Tests 5D *======================* */ + +const std::vector inputShapesDynamic5D = { + {{-1, -1, -1, -1, -1}, // dynamic + {{5, 36, 5, 5, 5}, {3, 16, 8, 5, 7}, {3, 24, 10, 10, 10}}}, // target + + {{-1, 32, -1, -1, -1}, // dynamic + {{5, 32, 5, 5, 5}, {3, 32, 8, 5, 7}, {3, 32, 10, 10, 10}}}, // target + + {{{1, 5}, {16, 32}, {1, 16}, {1, 16}, {1, 16}}, // dynamic + {{3, 16, 5, 5, 5}, {3, 24, 8, 5, 7}, {4, 32, 10, 10, 10}}}, // target +}; + +const std::vector CPUParams5DDynamic = { + cpuParams_ndhwc, + cpuParams_ncdhw +}; + +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPadDynamic5DConst, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapesDynamic5D), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5D), + ::testing::ValuesIn(padsEnd5D), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), + ::testing::ValuesIn(CPUParams5DDynamic)), + PadLayerCPUTest::getTestCaseName ); INSTANTIATE_TEST_SUITE_P( - smoke_CPUPad5DBlocked, + smoke_CPUPadDynamic5DConstBlocked, PadLayerCPUTest, ::testing::Combine( - pad5DParamsBlocked, + ::testing::Values(inputShapesDynamic5D[1]), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5DConstBlocked), + ::testing::ValuesIn(padsEnd5DConstBlocked), + ::testing::ValuesIn(argPadValue), + ::testing::Values(ngraph::helpers::PadMode::CONSTANT), ::testing::ValuesIn(CPUParams5DBlocked)), PadLayerCPUTest::getTestCaseName ); -const auto pad5DParams = testing::Combine( - testing::ValuesIn(padsBegin5D), - testing::ValuesIn(padsEnd5D), - testing::Values(0), - testing::ValuesIn(padMode), - testing::ValuesIn(inputPrecisions), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Precision::UNSPECIFIED), - testing::Values(InferenceEngine::Layout::ANY), - testing::Values(std::vector{3, 16, 5, 5, 5}), - testing::Values(CommonTestUtils::DEVICE_CPU) +INSTANTIATE_TEST_SUITE_P( + smoke_CPUPadDynamic5D, + PadLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapesDynamic5D), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5D), + ::testing::ValuesIn(padsEnd5D), + ::testing::Values(0), + ::testing::ValuesIn(padMode), + ::testing::ValuesIn(CPUParams5DDynamic)), + PadLayerCPUTest::getTestCaseName ); INSTANTIATE_TEST_SUITE_P( - smoke_CPUPad5D, + smoke_CPUPadDynamic5DBlocked, PadLayerCPUTest, ::testing::Combine( - pad5DParams, - ::testing::Values(cpuParams_ndhwc)), + ::testing::Values(inputShapesDynamic5D[1]), + ::testing::ValuesIn(inputPrecisions), + ::testing::ValuesIn(padsBegin5DBlocked), + ::testing::ValuesIn(padsEnd5DBlocked), + ::testing::Values(0), + ::testing::ValuesIn(padMode), + ::testing::ValuesIn(CPUParams5DBlocked)), PadLayerCPUTest::getTestCaseName ); +/* *======================* *=====================* *======================* */ } // namespace } // namespace CPULayerTestsDefinitions 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 index 70e732fdb3b2d5..564ecef0348322 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pooling.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/pooling.cpp @@ -4,53 +4,93 @@ #include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" -#include "shared_test_classes/single_layer/pooling.hpp" #include "test_utils/fusing_test_utils.hpp" +#include "shared_test_classes/single_layer/pooling.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" -using namespace InferenceEngine; +using namespace ov::test; using namespace CPUTestUtils; -using namespace LayerTestsDefinitions; namespace CPULayerTestsDefinitions { -typedef std::tuple< - poolLayerTestParamsSet, - CPUSpecificParams, - fusingSpecificParams -> poolLayerCpuTestParamsSet; + +using poolLayerCpuTestParamsSet = std::tuple; class PoolingLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CpuTestWithFusing { + virtual public SubgraphBaseTest, public CpuTestWithFusing { public: static std::string getTestCaseName(const testing::TestParamInfo& obj) { - poolLayerTestParamsSet basicParamsSet; + LayerTestsDefinitions::poolSpecificParams basicParamsSet; + InputShape inputShapes; + ElementType inPrc; + bool isInt8; CPUSpecificParams cpuParams; fusingSpecificParams fusingParams; - std::tie(basicParamsSet, cpuParams, fusingParams) = obj.param; - - std::ostringstream result; - result << PoolingLayerTest::getTestCaseName(testing::TestParamInfo( - basicParamsSet, 0)); - result << CPUTestsBase::getTestCaseName(cpuParams); - result << CpuTestWithFusing::getTestCaseName(fusingParams); + std::tie(basicParamsSet, inputShapes, inPrc, isInt8, cpuParams, fusingParams) = obj.param; - return result.str(); + 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) = basicParamsSet; + + std::ostringstream results; + results << "IS=("; + results << CommonTestUtils::partialShape2str({inputShapes.first}) << ")_"; + results << "TS="; + for (const auto& shape : inputShapes.second) { + results << CommonTestUtils::vec2str(shape) << "_"; + } + results << "Prc=" << inPrc << "_"; + switch (poolType) { + case ngraph::helpers::PoolingTypes::MAX: + results << "MaxPool_"; + break; + case ngraph::helpers::PoolingTypes::AVG: + results << "AvgPool_"; + results << "ExcludePad=" << excludePad << "_"; + break; + } + results << "K" << CommonTestUtils::vec2str(kernel) << "_"; + results << "S" << CommonTestUtils::vec2str(stride) << "_"; + results << "PB" << CommonTestUtils::vec2str(padBegin) << "_"; + results << "PE" << CommonTestUtils::vec2str(padEnd) << "_"; + results << "Rounding=" << roundingType << "_"; + results << "AutoPad=" << padType << "_"; + results << "INT8=" << isInt8 << "_"; + + results << CPUTestsBase::getTestCaseName(cpuParams); + results << CpuTestWithFusing::getTestCaseName(fusingParams); + return results.str(); + + return results.str(); } protected: void SetUp() override { - poolLayerTestParamsSet basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; + + LayerTestsDefinitions::poolSpecificParams basicParamsSet; + InputShape inputShapes; + ElementType inPrc; + bool isInt8; CPUSpecificParams cpuParams; fusingSpecificParams fusingParams; - std::tie(basicParamsSet, cpuParams, fusingParams) = this->GetParam(); - - poolSpecificParams poolParams; - std::vector inputShape; - InferenceEngine::Precision netPrecision; - std::tie(poolParams, netPrecision, inPrc, outPrc, inLayout, outLayout, inputShape, targetDevice) = basicParamsSet; + std::tie(basicParamsSet, inputShapes, inPrc, isInt8, cpuParams, fusingParams) = this->GetParam(); - if (outPrc == Precision::UNSPECIFIED) { - outPrc = inPrc; - } + 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) = basicParamsSet; std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; std::tie(postOpMgrPtr, fusedOps) = fusingParams; @@ -58,23 +98,19 @@ class PoolingLayerCPUTest : public testing::WithParamInterface 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 params = ngraph::builder::makeDynamicParams(inPrc, inputDynamicShapes); - 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 poolInput = params[0]; + if (isInt8) { + ov::Shape newShape(poolInput->get_output_partial_shape(0).size(), 1); + poolInput = ngraph::builder::makeFakeQuantize(poolInput, inPrc, 256, newShape); + } - std::shared_ptr pooling = ngraph::builder::makePooling(paramOuts[0], + std::shared_ptr pooling = ngraph::builder::makePooling(poolInput, stride, padBegin, padEnd, @@ -84,180 +120,206 @@ class PoolingLayerCPUTest : public testing::WithParamInterface vecCpuConfigs = {ref, sse42, avx, avx512}; -const std::vector inpOutPrecision = {Precision::FP32, Precision::BF16}; - -const std::vector> inputShapes4D = { - std::vector{3, 4, 64, 64}, - std::vector{2, 8, 8, 12}, - std::vector{1, 16, 16, 12}, - std::vector{1, 21, 8, 4}, - std::vector{1, 32, 8, 8}, +const std::vector inpOutPrecision = {ElementType::f32/*, ElementType::bf16*/}; + +const std::vector inputShapes4D = { + { {}, {{3, 4, 64, 64}} }, + { {}, {{2, 8, 8, 12}} }, + { {}, {{1, 16, 16, 12}} }, + { {}, {{1, 21, 8, 4}} }, + { {}, {{1, 32, 8, 8}} }, + { + // dynamic + {-1, -1, -1, -1}, + // target + { + {1, 32, 8, 8}, + {1, 21, 8, 4}, + {2, 8, 8, 12} + } + }, + { + // dynamic + {{1, 5}, {4, 32}, {1, 64}, {1, 64}}, + // target + { + {3, 4, 64, 64}, + {1, 16, 16, 12}, + {1, 32, 8, 8} + } + } }; -const std::vector> inputShapes5D = { - std::vector{1, 4, 16, 16, 16}, - std::vector{2, 8, 8, 8, 8}, - std::vector{2, 16, 12, 16, 20}, - std::vector{1, 19, 16, 20, 8}, - std::vector{1, 32, 16, 8, 12}, +const std::vector inputShapes5D = { + { {}, {{1, 4, 16, 16, 16}} }, + { {}, {{2, 8, 8, 8, 8}} }, + { {}, {{2, 16, 12, 16, 20}} }, + { {}, {{1, 19, 16, 20, 8}} }, + { {}, {{1, 32, 16, 8, 12}} }, + { + // dynamic + {-1, -1, -1, -1, -1}, + // target + { + {2, 8, 8, 8, 8}, + {1, 19, 16, 20, 8}, + {1, 4, 16, 16, 16} + } + }, + { + // dynamic + {{1, 5}, {4, 32}, {1, 64}, {1, 64}, {1, 25}}, + // target + { + {1, 4, 16, 16, 16}, + {1, 32, 16, 8, 12}, + {3, 16, 4, 8, 3} + } + } }; -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}, +const std::vector paramsMax4D = { + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2}, {2, 2}, {0, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, false }, + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2}, {2, 2}, {0, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false }, + LayerTestsDefinitions::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}, + LayerTestsDefinitions::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}, +const std::vector paramsAvg4D = { + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, true }, + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, true }, + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, false }, + LayerTestsDefinitions::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}, + LayerTestsDefinitions::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}, + LayerTestsDefinitions::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}, +const std::vector paramsAvg4D_RefOnly = { + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {2, 2}, {2, 2}, ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false }, }; INSTANTIATE_TEST_SUITE_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::ValuesIn(inputShapes4D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), - ::testing::Values(emptyFusingSpec)), + ::testing::ValuesIn(paramsMax4D), + ::testing::ValuesIn(inputShapes4D), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(false), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), + ::testing::Values(emptyFusingSpec)), PoolingLayerCPUTest::getTestCaseName); INSTANTIATE_TEST_SUITE_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::ValuesIn(inputShapes4D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), - ::testing::Values(emptyFusingSpec)), + ::testing::ValuesIn(paramsAvg4D), + ::testing::ValuesIn(inputShapes4D), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(false), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), + ::testing::Values(emptyFusingSpec)), PoolingLayerCPUTest::getTestCaseName); INSTANTIATE_TEST_SUITE_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::ValuesIn(inputShapes4D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(ref), - ::testing::Values(emptyFusingSpec)), + ::testing::ValuesIn(paramsAvg4D_RefOnly), + ::testing::ValuesIn(inputShapes4D), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(false), + ::testing::Values(ref), + ::testing::Values(emptyFusingSpec)), 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}, +const std::vector paramsMax5D = { + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, false }, + LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0}, + ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false }, + LayerTestsDefinitions::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}, + LayerTestsDefinitions::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}, +const std::vector paramsAvg5D = { + LayerTestsDefinitions::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_LOWER, true }, + LayerTestsDefinitions::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, true }, + LayerTestsDefinitions::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_LOWER, false }, + LayerTestsDefinitions::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}, + LayerTestsDefinitions::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}, + LayerTestsDefinitions::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}, + LayerTestsDefinitions::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}, +const std::vector paramsAvg5D_RefOnly = { + LayerTestsDefinitions::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_SUITE_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::ValuesIn(inputShapes5D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), - ::testing::Values(emptyFusingSpec)), - PoolingLayerCPUTest::getTestCaseName); + ::testing::Combine( + ::testing::ValuesIn(paramsMax5D), + ::testing::ValuesIn(inputShapes5D), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(false), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), + ::testing::Values(emptyFusingSpec)), + PoolingLayerCPUTest::getTestCaseName); INSTANTIATE_TEST_SUITE_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::ValuesIn(inputShapes5D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), - ::testing::Values(emptyFusingSpec)), - PoolingLayerCPUTest::getTestCaseName); + ::testing::Combine( + ::testing::ValuesIn(paramsAvg5D), + ::testing::ValuesIn(inputShapes5D), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(false), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)), + ::testing::Values(emptyFusingSpec)), + PoolingLayerCPUTest::getTestCaseName); INSTANTIATE_TEST_SUITE_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::ValuesIn(inputShapes5D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(ref), - ::testing::Values(emptyFusingSpec)), - PoolingLayerCPUTest::getTestCaseName); + ::testing::Combine( + ::testing::ValuesIn(paramsAvg5D_RefOnly), + ::testing::ValuesIn(inputShapes5D), + ::testing::ValuesIn(inpOutPrecision), + ::testing::Values(false), + ::testing::Values(ref), + ::testing::Values(emptyFusingSpec)), + PoolingLayerCPUTest::getTestCaseName); /* === Fusing === */ @@ -279,35 +341,82 @@ std::vector fusingParamsSet { fusingFakeQuantizePerChannel, }; +const std::vector inputShapes4D_int8 = { + { {}, {{3, 4, 64, 64}} }, + { {}, {{2, 8, 8, 12}} }, + { {}, {{1, 16, 16, 12}} }, + { {}, {{1, 21, 8, 4}} }, + { {}, {{1, 32, 8, 8}} }, + { + // dynamic + {-1, 32, -1, -1}, + // target + { + {1, 32, 8, 8}, + {1, 32, 8, 4}, + {2, 32, 8, 12} + } + }, + { + // dynamic + {{1, 5}, 16, {1, 64}, {1, 64}}, + // target + { + {3, 16, 32, 32}, + {1, 16, 16, 12}, + {1, 16, 8, 8} + } + } +}; + INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_4D_I8, PoolingLayerCPUTest, - ::testing::Combine( - ::testing::Combine( - ::testing::ValuesIn(paramsAvg4D), - ::testing::Values(Precision::FP32), - ::testing::Values(Precision::I8), - ::testing::Values(Precision::FP32), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::ValuesIn(inputShapes4D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_4D)), - ::testing::ValuesIn(fusingParamsSet)), - PoolingLayerCPUTest::getTestCaseName); + ::testing::Combine( + ::testing::ValuesIn(paramsAvg4D), + ::testing::ValuesIn(inputShapes4D_int8), + ::testing::Values(ElementType::f32), + ::testing::Values(true), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_4D)), + ::testing::ValuesIn(fusingParamsSet)), + PoolingLayerCPUTest::getTestCaseName); + +const std::vector inputShapes5D_int8 = { + { {}, {{1, 4, 16, 16, 16}} }, + { {}, {{2, 8, 8, 8, 8}} }, + { {}, {{2, 16, 12, 16, 20}} }, + { {}, {{1, 19, 16, 20, 8}} }, + { {}, {{1, 32, 16, 8, 12}} }, + { + // dynamic + {-1, 32, -1, -1, -1}, + // target + { + {2, 32, 8, 8, 8}, + {1, 32, 16, 20, 8}, + {1, 32, 16, 16, 16} + } + }, + { + // dynamic + {{1, 5}, 16, {1, 64}, {1, 64}, {1, 25}}, + // target + { + {1, 16, 16, 16, 16}, + {1, 16, 16, 8, 12}, + {2, 16, 8, 8, 8} + } + } +}; INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_5D_I8, PoolingLayerCPUTest, - ::testing::Combine( - ::testing::Combine( - ::testing::ValuesIn(paramsAvg5D), - ::testing::Values(Precision::FP32), - ::testing::Values(Precision::I8), - ::testing::Values(Precision::FP32), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::Values(InferenceEngine::Layout::ANY), - ::testing::ValuesIn(inputShapes5D), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_5D)), - ::testing::ValuesIn(fusingParamsSet)), - PoolingLayerCPUTest::getTestCaseName); + ::testing::Combine( + ::testing::ValuesIn(paramsAvg5D), + ::testing::ValuesIn(inputShapes5D_int8), + ::testing::Values(ElementType::f32), + ::testing::Values(true), + ::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_5D)), + ::testing::ValuesIn(fusingParamsSet)), + PoolingLayerCPUTest::getTestCaseName); } // namespace -} // namespace CPULayerTestsDefinitions \ No newline at end of file + +} // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/proposal.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/proposal.cpp new file mode 100644 index 00000000000000..85099c1cdfede0 --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/proposal.cpp @@ -0,0 +1,341 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include "test_utils/cpu_test_utils.hpp" +#include "ngraph_functions/builders.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using namespace CPUTestUtils; +using namespace ov::test; + +namespace CPULayerTestsDefinitions { + +namespace proposalTypes { + + typedef size_t base_size_type; + typedef float box_coordinate_scale_type; + typedef float box_size_scale_type; + typedef bool clip_after_nms_type; + typedef bool clip_before_nms_type; + typedef size_t feat_stride_type; + typedef std::string framework_type; + typedef size_t min_size_type; + typedef float nms_thresh_type; + typedef bool normalize_type; + typedef size_t post_nms_topn_type; + typedef size_t pre_nms_topn_type; + typedef std::vector ratio_type; + typedef std::vector scale_type; + +}; // namespace proposalTypes + +using namespace proposalTypes; + +using proposalSpecificParams = std::tuple< + base_size_type, + box_coordinate_scale_type, + box_size_scale_type, + clip_after_nms_type, + clip_before_nms_type, + feat_stride_type, + framework_type, + min_size_type, + nms_thresh_type, + normalize_type, + post_nms_topn_type, + pre_nms_topn_type, + ratio_type, + scale_type>; + +using proposalLayerTestCPUParams = std::tuple< + std::vector, // Input shapes + proposalSpecificParams, // Node attributes + Precision>; // Network precision + +class ProposalLayerCPUTest : public testing::WithParamInterface, + public SubgraphBaseTest, public CPUTestsBase { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + std::vector inputShapes; + proposalSpecificParams proposalParams; + Precision netPrecision; + std::tie(inputShapes, proposalParams, netPrecision) = obj.param; + + base_size_type base_size; + box_coordinate_scale_type box_coordinate_scale; + box_size_scale_type box_size_scale; + clip_after_nms_type clip_after_nms; + clip_before_nms_type clip_before_nms; + feat_stride_type feat_stride; + framework_type framework; + min_size_type min_size; + nms_thresh_type nms_thresh; + normalize_type normalize; + post_nms_topn_type post_nms_topn; + pre_nms_topn_type pre_nms_topn; + ratio_type ratio; + scale_type scale; + std::tie(base_size, box_coordinate_scale, box_size_scale, + clip_after_nms, clip_before_nms, feat_stride, + framework, min_size, nms_thresh, normalize, + post_nms_topn, pre_nms_topn, ratio, scale) = proposalParams; + + std::ostringstream result; + if (inputShapes.front().first.size() != 0) { + result << "IS=("; + for (const auto &shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result.seekp(-1, result.cur); + result << ")_"; + } + result << "TS="; + for (const auto& shape : inputShapes) { + for (const auto& item : shape.second) { + result << CommonTestUtils::vec2str(item) << "_"; + } + } + result << "base_size=" << base_size << "_"; + result << "framework=" << framework << "_"; + result << "ratio=" << CommonTestUtils::vec2str(ratio) << "_"; + result << "scale=" << CommonTestUtils::vec2str(scale) << "_"; + result << "netPRC=" << netPrecision.name(); + return result.str(); + } + +protected: + void SetUp() override { + targetDevice = CommonTestUtils::DEVICE_CPU; + + std::vector inputShapes; + proposalSpecificParams proposalParams; + Precision netPrecision; + std::tie(inputShapes, proposalParams, netPrecision) = this->GetParam(); + + base_size_type base_size; + box_coordinate_scale_type box_coordinate_scale; + box_size_scale_type box_size_scale; + clip_after_nms_type clip_after_nms; + clip_before_nms_type clip_before_nms; + feat_stride_type feat_stride; + framework_type framework; + min_size_type min_size; + nms_thresh_type nms_thresh; + normalize_type normalize; + post_nms_topn_type post_nms_topn; + pre_nms_topn_type pre_nms_topn; + ratio_type ratio; + scale_type scale; + std::tie(base_size, box_coordinate_scale, box_size_scale, + clip_after_nms, clip_before_nms, feat_stride, + framework, min_size, nms_thresh, normalize, + post_nms_topn, pre_nms_topn, ratio, scale) = proposalParams; + + init_input_shapes(inputShapes); + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto params = ngraph::builder::makeDynamicParams(ngPrc, {inputDynamicShapes[0], inputDynamicShapes[1], inputDynamicShapes[2]}); + auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); + + ngraph::op::ProposalAttrs attrs; + attrs.base_size = base_size; + attrs.pre_nms_topn = pre_nms_topn; + attrs.post_nms_topn = post_nms_topn; + attrs.nms_thresh = nms_thresh; + attrs.feat_stride = feat_stride; + attrs.min_size = min_size; + attrs.ratio = ratio; + attrs.scale = scale; + attrs.clip_before_nms = clip_before_nms; + attrs.clip_after_nms = clip_after_nms; + attrs.normalize = normalize; + attrs.box_size_scale = box_size_scale; + attrs.box_coordinate_scale = box_coordinate_scale; + attrs.framework = framework; + attrs.infer_probs = true; + + auto proposal = std::make_shared(paramOuts[0], paramOuts[1], paramOuts[2], attrs); + + ngraph::ResultVector results{ + std::make_shared(proposal->output(0)), + std::make_shared(proposal->output(1)) + }; + + function = std::make_shared(results, params, "Proposal"); + } + void generate_inputs(const std::vector& targetInputStaticShapes) override { + inputs.clear(); + const auto& funcInputs = function->inputs(); + for (int i = 0; i < funcInputs.size(); ++i) { + const auto& funcInput = funcInputs[i]; + ov::runtime::Tensor tensor; + + if (i == 2) { + tensor = ov::runtime::Tensor(funcInput.get_element_type(), targetInputStaticShapes[i]); + + auto *dataPtr = tensor.data(); + dataPtr[0] = dataPtr[1] = 225.0f; + dataPtr[2] = 1.0f; + if (tensor.get_size() == 4) dataPtr[3] = 1.0f; + } else { + tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(), targetInputStaticShapes[i], 10, 0, 1000); + } + inputs.insert({funcInput.get_node_shared_ptr(), tensor}); + } + } +}; + +TEST_P(ProposalLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + run(); + // TODO: Should be uncommented after updating the CheckPluginRelatedResults() method + // CheckPluginRelatedResults(executableNetwork, "Proposal"); +} + +namespace { + +const std::vector netPrecision = { + Precision::FP32 +}; + +std::vector> staticInputShapesCase1 = { + {{2, 30, 18, 22}, {2, 60, 18, 22}, {3}}, + {{1, 30, 18, 22}, {1, 60, 18, 22}, {3}}, + {{1, 30, 50, 80}, {1, 60, 50, 80}, {4}} +}; + +std::vector> dynamicInputShapesCase1 = { + { + { + {{-1, 30, -1, -1}, {{2, 30, 75, 75}, {1, 30, 50, 80}, {3, 30, 80, 80}}}, + {{-1, 60, -1, -1}, {{2, 60, 75, 75}, {1, 60, 50, 80}, {3, 60, 80, 80}}}, + {{{3, 4}}, {{3}, {4}, {3}}} + } + }, + { + { + {{-1, 30, {20, 40}, {10, 50}}, {{1, 30, 20, 10}, {1, 30, 20, 30}, {1, 30, 40, 35}}}, + {{-1, 60, {20, 40}, {10, 50}}, {{1, 60, 20, 10}, {1, 60, 20, 30}, {1, 60, 40, 35}}}, + {{3}, {{3}, {3}, {3}}} + } + } +}; + +const std::vector base_size_1 = {16}; +const std::vector box_coordinate_scale_1 = {1}; +const std::vector box_size_scale_1 = {1}; +const std::vector clip_after_nms_1 = {false}; +const std::vector clip_before_nms_1 = {true}; +const std::vector feat_stride_1 = {16}; +const std::vector framework_1 = {""}; +const std::vector min_size_1 = {12}; +const std::vector nms_thresh_1 = {0.699999988079071}; +const std::vector normalize_1 = {true}; +const std::vector post_nms_topn_1 = {300}; +const std::vector pre_nms_topn_1 = {6000}; +const std::vector ratio_1 = {{0.5, 1.0, 2.0}}; +const std::vector scale_1 = {{2.0, 4.0, 8.0, 16.0, 32.0}}; + +const auto proposalParamsCase1 = ::testing::Combine( + ::testing::ValuesIn(base_size_1), + ::testing::ValuesIn(box_coordinate_scale_1), + ::testing::ValuesIn(box_size_scale_1), + ::testing::ValuesIn(clip_after_nms_1), + ::testing::ValuesIn(clip_before_nms_1), + ::testing::ValuesIn(feat_stride_1), + ::testing::ValuesIn(framework_1), + ::testing::ValuesIn(min_size_1), + ::testing::ValuesIn(nms_thresh_1), + ::testing::ValuesIn(normalize_1), + ::testing::ValuesIn(post_nms_topn_1), + ::testing::ValuesIn(pre_nms_topn_1), + ::testing::ValuesIn(ratio_1), + ::testing::ValuesIn(scale_1) +); + +INSTANTIATE_TEST_SUITE_P(smoke_Proposal_Static_Test_Case1, ProposalLayerCPUTest, + ::testing::Combine(::testing::ValuesIn(static_shapes_to_test_representation(staticInputShapesCase1)), + proposalParamsCase1, + ::testing::ValuesIn(netPrecision)), + ProposalLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Proposal_Dynamic_Test_Case1, ProposalLayerCPUTest, + ::testing::Combine(::testing::ValuesIn(dynamicInputShapesCase1), + proposalParamsCase1, + ::testing::ValuesIn(netPrecision)), + ProposalLayerCPUTest::getTestCaseName); + + +std::vector> staticInputShapesCase2 = { + {{1, 24, 24, 30}, {1, 48, 24, 30}, {3}}, + {{1, 24, 38, 38}, {1, 48, 38, 38}, {4}} +}; + +std::vector> dynamicInputShapesCase2 = { + { + { + {{1, 24, -1, -1}, {{1, 24, 38, 38}, {1, 24, 20, 12}, {1, 24, 15, 15}}}, + {{1, 48, -1, -1}, {{1, 48, 38, 38}, {1, 48, 20, 12}, {1, 48, 15, 15}}}, + {{{3, 4}}, {{4}, {3}, {4}}} + } + }, + { + { + {{1, 24, {11, 38}, {11, 38}}, {{1, 24, 19, 11}, {1, 24, 15, 30}, {1, 24, 18, 17}}}, + {{1, 48, {11, 38}, {11, 38}}, {{1, 48, 19, 11}, {1, 48, 15, 30}, {1, 48, 18, 17}}}, + {{4}, {{4}, {4}, {4}}} + } + } +}; + +const std::vector base_size_2 = {256}; +const std::vector box_coordinate_scale_2 = {10}; +const std::vector box_size_scale_2 = {5}; +const std::vector clip_after_nms_2 = {false}; +const std::vector clip_before_nms_2 = {true}; +const std::vector feat_stride_2 = {16}; +const std::vector framework_2 = {"tensorflow"}; +const std::vector min_size_2 = {1}; +const std::vector nms_thresh_2 = {0.699999988079071}; +const std::vector normalize_2 = {true}; +const std::vector post_nms_topn_2 = {100}; +const std::vector pre_nms_topn_2 = {2147483647}; +const std::vector ratio_2 = {{0.5, 1.0, 2.0}}; +const std::vector scale_2 = {{0.25, 0.5, 1.0, 2.0}}; + +const auto proposalParamsCase2 = ::testing::Combine( + ::testing::ValuesIn(base_size_2), + ::testing::ValuesIn(box_coordinate_scale_2), + ::testing::ValuesIn(box_size_scale_2), + ::testing::ValuesIn(clip_after_nms_2), + ::testing::ValuesIn(clip_before_nms_2), + ::testing::ValuesIn(feat_stride_2), + ::testing::ValuesIn(framework_2), + ::testing::ValuesIn(min_size_2), + ::testing::ValuesIn(nms_thresh_2), + ::testing::ValuesIn(normalize_2), + ::testing::ValuesIn(post_nms_topn_2), + ::testing::ValuesIn(pre_nms_topn_2), + ::testing::ValuesIn(ratio_2), + ::testing::ValuesIn(scale_2) +); + +INSTANTIATE_TEST_SUITE_P(smoke_Proposal_Static_Test_Case2, ProposalLayerCPUTest, + ::testing::Combine(::testing::ValuesIn(static_shapes_to_test_representation(staticInputShapesCase2)), + proposalParamsCase2, + ::testing::ValuesIn(netPrecision)), + ProposalLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Proposal_Dynamic_Test_Case2, ProposalLayerCPUTest, + ::testing::Combine(::testing::ValuesIn(dynamicInputShapesCase2), + proposalParamsCase2, + ::testing::ValuesIn(netPrecision)), + ProposalLayerCPUTest::getTestCaseName); + +} // namespace +} // namespace CPULayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/split.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/split.cpp index 14b83c08ae07a6..68b18870b340bc 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/split.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/split.cpp @@ -2,56 +2,63 @@ // SPDX-License-Identifier: Apache-2.0 // +#include "shared_test_classes/base/ov_subgraph.hpp" #include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" -using namespace InferenceEngine; +using namespace ov::test; using namespace CPUTestUtils; namespace CPULayerTestsDefinitions { typedef std::tuple< - size_t, // Num splits - int64_t, // Axis - InferenceEngine::Precision, // Net precision - std::vector, // Input shapes - std::vector, // Used outputs indices - std::string, // Target device name + size_t, // Num splits + int64_t, // Axis + ElementType, // Net precision + InputShape, // Input shapes + std::vector, // Used outputs indices CPUSpecificParams > splitCPUTestParams; class SplitLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { + virtual public SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(testing::TestParamInfo obj) { size_t numSplits; int64_t axis; - InferenceEngine::Precision netPrecision; - InferenceEngine::SizeVector inputShape, outIndices; - std::string targetDevice; + ElementType netPrecision; + InputShape inputShapes; + InferenceEngine::SizeVector outIndices; CPUSpecificParams cpuParams; - std::tie(numSplits, axis, netPrecision, inputShape, outIndices, targetDevice, cpuParams) = obj.param; + std::tie(numSplits, axis, netPrecision, inputShapes, outIndices, cpuParams) = obj.param; std::ostringstream result; - result << "IS=" << CommonTestUtils::vec2str(inputShape) << "_"; + result << "IS="; + result << CommonTestUtils::partialShape2str({inputShapes.first}) << "_"; + result << "TS="; + for (const auto& shape : inputShapes.second) { + result << CommonTestUtils::vec2str(shape) << "_"; + } result << "numSplits=" << numSplits << "_"; result << "axis=" << axis << "_"; if (!outIndices.empty()) { result << "outIndices" << CommonTestUtils::vec2str(outIndices) << "_"; } - result << "netPRC=" << netPrecision.name() << "_"; - result << "trgDev=" << targetDevice; + result << "netPRC=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); return result.str(); } + protected: void SetUp() override { + targetDevice = CommonTestUtils::DEVICE_CPU; + size_t axis, numSplits; - std::vector inputShape, outIndices; - InferenceEngine::Precision netPrecision; + ElementType netPrecision; + InputShape inputShapes; + InferenceEngine::SizeVector outIndices; CPUSpecificParams cpuParams; - std::tie(numSplits, axis, netPrecision, inputShape, outIndices, targetDevice, cpuParams) = this->GetParam(); - inPrc = outPrc = netPrecision; + std::tie(numSplits, axis, netPrecision, inputShapes, outIndices, cpuParams) = this->GetParam(); if (outIndices.empty()) { for (int i = 0; i < numSplits; ++i) { outIndices.push_back(i); @@ -59,14 +66,15 @@ class SplitLayerCPUTest : public testing::WithParamInterface } std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - selectedType += std::string("_") + inPrc.name(); + selectedType += std::string("_") + InferenceEngine::details::convertPrecision(netPrecision).name(); + + init_input_shapes({inputShapes}); - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); auto paramOuts = ngraph::helpers::convert2OutputVector( ngraph::helpers::castOps2Nodes(params)); auto split = std::dynamic_pointer_cast(ngraph::builder::makeSplit(paramOuts[0], - ngPrc, numSplits, axis)); + netPrecision, numSplits, axis)); ngraph::ResultVector results; for (int i = 0; i < outIndices.size(); i++) { @@ -85,8 +93,8 @@ class SplitLayerCPUTest : public testing::WithParamInterface TEST_P(SplitLayerCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); - CheckPluginRelatedResults(executableNetwork, "Split"); + run(); +// CheckPluginRelatedResults(executableNetwork, "Split"); } namespace { @@ -115,70 +123,150 @@ const auto blocked16_4D_ref = CPUSpecificParams{{nChw16c}, {nChw16c}, {}, "ref"} const auto blocked16_5D_ref = CPUSpecificParams{{nCdhw16c}, {nCdhw16c}, {}, "ref"}; // List of precisions natively supported by mkldnn. -const std::vector netPrecisions = { - Precision::I8, - Precision::I32, - Precision::FP32, - Precision::BF16 +const std::vector netPrecisions = { + ElementType::i8, + ElementType::i32, + ElementType::f32, + ElementType::bf16 }; const std::vector> outIndices3 = {{0, 1, 2}, {0, 1, 1, 0, 2}, {0, 0, 0, 2}}; const std::vector> outIndices4 = {{0, 1, 2, 3}, {0, 1, 1, 0, 2, 3}, {0, 0, 0, 2, 3}}; +const std::vector inputShapes4D_Nspc2NcspSpecial = { + { {}, {{3, 8, 11, 9}} }, + { + // dynamic + {-1, -1, -1, -1}, + // target + { + {1, 4, 5, 7}, + {3, 8, 5, 9}, + {5, 16, 1, 8} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 25}, {2, 10}}, + // target + { + {2, 8, 5, 7}, + {1, 4, 10, 2}, + {3, 16, 5, 9} + } + }, +}; INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Nspc2NcspSpecial, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(4), ::testing::Values(1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({3, 28, 24, 9})), + ::testing::ValuesIn(inputShapes4D_Nspc2NcspSpecial), ::testing::ValuesIn(outIndices4), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(perChannelsToPlanar_4D)), SplitLayerCPUTest::getTestCaseName); +const std::vector inputShapes5D_Nspc2NcspSpecial = { + { {}, {{3, 9, 5, 9, 11}} }, + { + // dynamic + {-1, -1, -1, -1, -1}, + // target + { + {1, 12, 5, 7, 5}, + {3, 6, 8, 9, 1}, + {5, 9, 1, 8, 2} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 25}, {2, 10}, {1, 64}}, + // target + { + {2, 6, 5, 7, 7}, + {1, 3, 10, 2, 11}, + {3, 9, 4, 9, 8} + } + }, +}; + INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Nspc2NcspSpecial, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(3), ::testing::Values(1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({3, 21, 24, 9, 15})), + ::testing::ValuesIn(inputShapes5D_Nspc2NcspSpecial), ::testing::ValuesIn(outIndices3), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(perChannelsToPlanar_5D)), SplitLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block8inPlace, SplitLayerCPUTest, - ::testing::Combine( - ::testing::Values(3), - ::testing::Values(0, 1), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({3, 24, 24, 9})), - ::testing::ValuesIn(outIndices3), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_4D, planar_4D_ref, perChannels_4D, blocked8_4D)), - SplitLayerCPUTest::getTestCaseName); +const std::vector inputShapes4D_planar = { + { {}, {{3, 24, 24, 9}} }, + { + // dynamic + {-1, -1, -1, -1}, + // target + { + {1, 15, 12, 9}, + {3, 1, 9, 12}, + {5, 5, 6, 6} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 48}, {2, 48}}, + // target + { + {2, 5, 6, 9}, + {1, 7, 12, 6}, + {3, 11, 9, 3} + } + }, +}; -INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block8, SplitLayerCPUTest, +INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_planar, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(3), ::testing::Values(2, 3), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({3, 24, 24, 9})), + ::testing::ValuesIn(inputShapes4D_planar), ::testing::ValuesIn(outIndices3), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_4D, planar_4D_ref, perChannels_4D, blocked8_4D_ref)), + ::testing::Values(planar_4D, planar_4D_ref, perChannels_4D)), SplitLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block16inPlace, SplitLayerCPUTest, +const std::vector inputShapes4D_block = { + { {}, {{3, 16, 12, 12}} }, + { + // dynamic + {-1, 16, -1, -1}, + // target + { + {1, 16, 12, 12}, + {3, 16, 12, 12}, + {5, 16, 12, 12} + } + }, + { + // dynamic + {{1, 5}, 16, {1, 48}, {2, 24}}, + // target + { + {2, 16, 12, 12}, + {1, 16, 12, 12}, + {3, 16, 12, 12} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block8, SplitLayerCPUTest, ::testing::Combine( - ::testing::Values(4), - ::testing::Values(0, 1), + ::testing::Values(3), + ::testing::Values(2, 3), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({4, 64, 32, 12})), + ::testing::ValuesIn(inputShapes4D_block), ::testing::ValuesIn(outIndices3), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(blocked16_4D)), + ::testing::Values(blocked8_4D_ref)), SplitLayerCPUTest::getTestCaseName); INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block16, SplitLayerCPUTest, @@ -186,43 +274,77 @@ INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block16, SplitLayerCPUTest, ::testing::Values(4), ::testing::Values(2, 3), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({4, 64, 32, 12})), + ::testing::ValuesIn(inputShapes4D_block), ::testing::ValuesIn(outIndices4), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(blocked16_4D_ref)), SplitLayerCPUTest::getTestCaseName); -INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Block8inPlace, SplitLayerCPUTest, +const std::vector inputShapes5D_planar = { + { {}, {{3, 5, 3, 6, 12}} }, + { + // dynamic + {-1, -1, -1, -1, -1}, + // target + { + {1, 15, 12, 3, 9}, + {3, 1, 6, 12, 3}, + {5, 5, 6, 6, 6} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 48}, {2, 48}, {1, 40}}, + // target + { + {2, 5, 12, 3, 6}, + {1, 7, 12, 6, 9}, + {3, 11, 9, 3, 30} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_planar, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(3), - ::testing::Values(0, 1), + ::testing::Values(2, 3, 4), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({3, 24, 24, 9, 15})), + ::testing::ValuesIn(inputShapes5D_planar), ::testing::ValuesIn(outIndices3), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_5D, planar_5D_ref, perChannels_5D, blocked8_5D)), + ::testing::Values(planar_5D, planar_5D_ref, perChannels_5D)), SplitLayerCPUTest::getTestCaseName); +const std::vector inputShapes5D_block = { + { {}, {{3, 16, 24, 12, 36}} }, + { + // dynamic + {-1, 16, -1, -1, -1}, + // target + { + {1, 16, 12, 24, 24}, + {3, 16, 12, 12, 12}, + {5, 16, 12, 12, 24} + } + }, + { + // dynamic + {{1, 5}, 16, {1, 48}, {2, 24}, {3, 64}}, + // target + { + {2, 16, 12, 12, 24}, + {1, 16, 12, 12, 24}, + {3, 16, 12, 12, 12} + } + }, +}; + INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Block8, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(3), ::testing::Values(2, 3, 4), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({3, 24, 24, 9, 15})), + ::testing::ValuesIn(inputShapes5D_block), ::testing::ValuesIn(outIndices3), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(planar_5D, planar_5D_ref, perChannels_5D, blocked8_5D_ref)), - SplitLayerCPUTest::getTestCaseName); - -INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Block16inPlace, SplitLayerCPUTest, - ::testing::Combine( - ::testing::Values(4), - ::testing::Values(0, 1), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({4, 64, 32, 12, 20})), - ::testing::ValuesIn(outIndices4), - ::testing::Values(CommonTestUtils::DEVICE_CPU), - ::testing::Values(blocked16_5D)), + ::testing::Values(blocked8_5D_ref)), SplitLayerCPUTest::getTestCaseName); INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Block16, SplitLayerCPUTest, @@ -230,43 +352,154 @@ INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Block16, SplitLayerCPUTest, ::testing::Values(4), ::testing::Values(2, 3, 4), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({4, 64, 32, 12, 20})), + ::testing::ValuesIn(inputShapes5D_block), ::testing::ValuesIn(outIndices4), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(blocked16_5D_ref)), SplitLayerCPUTest::getTestCaseName); +const std::vector inputShapes3D = { + { {}, {{14, 28, 21}} }, + { + // dynamic + {-1, -1, -1}, + // target + { + {7, 21, 14}, + {21, 7, 14}, + {21, 14, 7}, + } + }, + { + // dynamic + {{1, 60}, {1, 50}, {1, 48}}, + // target + { + {14, 21, 7}, + {21, 7, 14}, + {7, 14, 21}, + } + }, +}; + INSTANTIATE_TEST_SUITE_P(smoke_Split3D, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(7), ::testing::Values(0, 1, 2), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({14, 42, 21})), + ::testing::ValuesIn(inputShapes3D), ::testing::Values(std::vector({})), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"}, CPUSpecificParams{{}, {}, {"ref"}, "ref"})), SplitLayerCPUTest::getTestCaseName); +const std::vector inputShapes2D = { + { {}, {{6, 12}} }, + { + // dynamic + {-1, -1}, + // target + { + {2, 8}, + {10, 4}, + {2, 6}, + } + }, + { + // dynamic + {{1, 60}, {1, 50}}, + // target + { + {2, 4}, + {4, 4}, + {6, 12}, + } + }, +}; + INSTANTIATE_TEST_SUITE_P(smoke_Split2D, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(2), ::testing::Values(0, 1), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({6, 12})), + ::testing::ValuesIn(inputShapes2D), ::testing::Values(std::vector({})), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"}, CPUSpecificParams{{}, {}, {"ref"}, "ref"})), SplitLayerCPUTest::getTestCaseName); +const std::vector inputShapes1D = { + { {}, {{10}} }, + { + // dynamic + {-1}, + // target + { + {5}, + {15}, + {10}, + } + }, + { + // dynamic + {{1, 60}}, + // target + { + {15}, + {5}, + {10}, + } + }, +}; + INSTANTIATE_TEST_SUITE_P(smoke_Split1D, SplitLayerCPUTest, ::testing::Combine( ::testing::Values(5), ::testing::Values(0), ::testing::ValuesIn(netPrecisions), - ::testing::Values(std::vector({10})), + ::testing::ValuesIn(inputShapes1D), ::testing::Values(std::vector({})), - ::testing::Values(CommonTestUtils::DEVICE_CPU), ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"}, CPUSpecificParams{{}, {}, {"ref"}, "ref"})), SplitLayerCPUTest::getTestCaseName); + +// ============================================== inPlace cases ============================================ +INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block8inPlace, SplitLayerCPUTest, + ::testing::Combine( + ::testing::Values(3), + ::testing::Values(0, 1), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InputShape{ {}, {{3, 24, 24, 9}} }), + ::testing::ValuesIn(outIndices3), + ::testing::Values(planar_4D, planar_4D_ref, perChannels_4D, blocked8_4D)), + SplitLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Split4D_CPU_Block16inPlace, SplitLayerCPUTest, + ::testing::Combine( + ::testing::Values(4), + ::testing::Values(0, 1), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InputShape{ {}, {{4, 64, 32, 12}} }), + ::testing::ValuesIn(outIndices3), + ::testing::Values(blocked16_4D)), + SplitLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Block8inPlace, SplitLayerCPUTest, + ::testing::Combine( + ::testing::Values(3), + ::testing::Values(0, 1), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InputShape{ {}, {{3, 24, 24, 9, 15}} }), + ::testing::ValuesIn(outIndices3), + ::testing::Values(planar_5D, planar_5D_ref, perChannels_5D, blocked8_5D)), + SplitLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Split5D_CPU_Block16inPlace, SplitLayerCPUTest, + ::testing::Combine( + ::testing::Values(4), + ::testing::Values(0, 1), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(InputShape{ {}, {{4, 64, 32, 12, 20}} }), + ::testing::ValuesIn(outIndices4), + ::testing::Values(blocked16_5D)), + SplitLayerCPUTest::getTestCaseName); + } // namespace + } // namespace CPULayerTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/variadic_split.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/variadic_split.cpp new file mode 100644 index 00000000000000..d7395f315977ad --- /dev/null +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/variadic_split.cpp @@ -0,0 +1,434 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" +#include "test_utils/cpu_test_utils.hpp" + +using namespace ov::test; +using namespace CPUTestUtils; + +namespace CPULayerTestsDefinitions { + +typedef std::tuple< + InputShape, + int64_t, // Axis + std::vector, // Split lengths + ElementType, // Net precision + CPUSpecificParams +> varSplitCPUTestParams; + +class VariadicSplitLayerCPUTest : public testing::WithParamInterface, + virtual public SubgraphBaseTest, public CPUTestsBase { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + InputShape shapes; + int64_t axis; + std::vector splitLenght; + ElementType netPrecision; + CPUSpecificParams cpuParams; + std::tie(shapes, axis, splitLenght, netPrecision, cpuParams) = obj.param; + + std::ostringstream result; + result << "IS="; + result << CommonTestUtils::partialShape2str({shapes.first}) << "_"; + result << "TS="; + for (const auto& shape : shapes.second) { + result << CommonTestUtils::vec2str(shape) << "_"; + } + result << "axis=" << axis << "_"; + result << "splitLenght=" << CommonTestUtils::vec2str(splitLenght) << "_"; + result << "netPRC=" << netPrecision << "_"; + result << CPUTestsBase::getTestCaseName(cpuParams); + return result.str(); + } + +protected: + void SetUp() override { + targetDevice = CommonTestUtils::DEVICE_CPU; + + InputShape inputShapes; + int64_t axis; + std::vector splitLenght; + ElementType netPrecision; + CPUSpecificParams cpuParams; + std::tie(inputShapes, axis, splitLenght, netPrecision, cpuParams) = this->GetParam(); + + std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; + selectedType += std::string("_") + InferenceEngine::details::convertPrecision(netPrecision).name(); + + init_input_shapes({inputShapes}); + + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + auto paramOuts = ngraph::helpers::convert2OutputVector( + ngraph::helpers::castOps2Nodes(params)); + + auto splitAxisOp = std::make_shared(ngraph::element::i64, ngraph::Shape{}, std::vector{axis}); + auto splitLengthsOp = std::make_shared(ngraph::element::i32, ngraph::Shape{splitLenght.size()}, splitLenght); + auto varSplit = std::make_shared(paramOuts[0], splitAxisOp, splitLengthsOp); + + varSplit->get_rt_info() = getCPUInfo(); + + function = std::make_shared(varSplit, params, "VariadicSplitCPU"); + } +}; + +TEST_P(VariadicSplitLayerCPUTest, CompareWithRefs) { + SKIP_IF_CURRENT_TEST_IS_DISABLED() + + run(); +// CheckPluginRelatedResults(executableNetwork, "Split"); +} + +namespace { +const auto planar_4D_ref = CPUSpecificParams{{nchw}, {nchw}, {"ref"}, "ref"}; +const auto planar_5D_ref = CPUSpecificParams{{ncdhw}, {ncdhw}, {"ref"}, "ref"}; + +const auto planar_4D = CPUSpecificParams{{nchw}, {nchw}, {}, "unknown"}; +const auto planar_5D = CPUSpecificParams{{ncdhw}, {ncdhw}, {}, "unknown"}; + +const auto perChannels_4D = CPUSpecificParams{{nhwc}, {nhwc}, {}, "ref"}; +const auto perChannels_5D = CPUSpecificParams{{ndhwc}, {ndhwc}, {}, "ref"}; + +const auto perChannelsToPlanar_4D = CPUSpecificParams{{nhwc}, {nchw}, {}, "ref"}; +const auto perChannelsToPlanar_5D = CPUSpecificParams{{ndhwc}, {ncdhw}, {}, "ref"}; + +const auto blocked8_4D = CPUSpecificParams{{nChw8c}, {nChw8c}, {}, "unknown"}; +const auto blocked8_5D = CPUSpecificParams{{nCdhw8c}, {nCdhw8c}, {}, "unknown"}; + +const auto blocked8_4D_ref = CPUSpecificParams{{nChw8c}, {nChw8c}, {}, "ref"}; +const auto blocked8_5D_ref = CPUSpecificParams{{nCdhw8c}, {nCdhw8c}, {}, "ref"}; + +const auto blocked16_4D = CPUSpecificParams{{nChw16c}, {nChw16c}, {}, "unknown"}; +const auto blocked16_5D = CPUSpecificParams{{nCdhw16c}, {nCdhw16c}, {}, "unknown"}; + +const auto blocked16_4D_ref = CPUSpecificParams{{nChw16c}, {nChw16c}, {}, "ref"}; +const auto blocked16_5D_ref = CPUSpecificParams{{nCdhw16c}, {nCdhw16c}, {}, "ref"}; + +// List of precisions natively supported by mkldnn. +const std::vector netPrecisions = { + ElementType::i8, + ElementType::i32, + ElementType::f32, + ElementType::bf16 +}; + +const std::vector inputShapes4D_Nspc2NcspSpecial = { + { {}, {{3, 5, 24, 9}} }, + { + // dynamic + {-1, -1, -1, -1}, + // target + { + {1, 8, 5, 7}, + {3, 9, 7, 9}, + {5, 6, 1, 8} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 25}, {2, 10}}, + // target + { + {2, 7, 5, 7}, + {1, 10, 10, 2}, + {3, 5, 6, 9} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit4D_CPU_Nspc2NcspSpecial, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes4D_Nspc2NcspSpecial), + ::testing::Values(1), + ::testing::Values(std::vector{1, 2, -1, 1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(perChannelsToPlanar_4D)), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes5D_Nspc2NcspSpecial = { + { {}, {{3, 4, 7, 9, 3}} }, + { + // dynamic + {-1, -1, -1, -1, -1}, + // target + { + {1, 6, 5, 7, 5}, + {3, 8, 6, 9, 1}, + {5, 9, 1, 8, 2} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 25}, {2, 10}, {1, 64}}, + // target + { + {2, 5, 5, 7, 7}, + {1, 4, 10, 2, 11}, + {3, 7, 5, 9, 8} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit5D_CPU_Nspc2NcspSpecial, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes5D_Nspc2NcspSpecial), + ::testing::Values(1), + ::testing::Values(std::vector{2, 1, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(perChannelsToPlanar_5D)), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes4D_planar = { + { {}, {{3, 6, 5, 6}} }, + { + // dynamic + {-1, -1, -1, -1}, + // target + { + {1, 9, 8, 7}, + {3, 8, 6, 5}, + {5, 3, 7, 6} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 48}, {2, 48}}, + // target + { + {2, 9, 5, 6}, + {1, 6, 9, 8}, + {3, 1, 6, 7} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit4D_CPU_planar, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes4D_planar), + ::testing::Values(2, 3), + ::testing::Values(std::vector{1, 3, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_4D, planar_4D_ref, perChannels_4D)), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes4D_block = { + { {}, {{3, 16, 6, 7}} }, + { + // dynamic + {-1, 16, -1, -1}, + // target + { + {1, 16, 8, 7}, + {3, 16, 7, 8}, + {5, 16, 9, 8} + } + }, + { + // dynamic + {{1, 5}, 16, {1, 48}, {2, 24}}, + // target + { + {2, 16, 12, 6}, + {1, 16, 6, 9}, + {3, 16, 7, 6} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit4D_CPU_Block8, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes4D_block), + ::testing::Values(2, 3), + ::testing::Values(std::vector{2, 2, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked8_4D_ref)), + VariadicSplitLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit4D_CPU_Block16, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes4D_block), + ::testing::Values(2, 3), + ::testing::Values(std::vector{2, 2, -1, 1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked16_4D_ref)), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes5D_planar = { + { {}, {{3, 24, 4, 5, 6}} }, + { + // dynamic + {-1, -1, -1, -1, -1}, + // target + { + {1, 2, 4, 6, 5}, + {3, 1, 6, 4, 5}, + {5, 6, 5, 7, 4} + } + }, + { + // dynamic + {{1, 5}, {1, 64}, {1, 48}, {2, 48}, {2, 40}}, + // target + { + {2, 5, 4, 5, 6}, + {1, 7, 5, 4, 7}, + {3, 3, 5, 6, 4} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit5D_CPU_planar, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes5D_planar), + ::testing::Values(2, 3, 4), + ::testing::Values(std::vector{2, 1, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(planar_5D, planar_5D_ref, perChannels_5D)), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes5D_block = { + { {}, {{3, 16, 8, 5, 6}} }, + { + // dynamic + {-1, 16, -1, -1, -1}, + // target + { + {1, 16, 5, 6, 7}, + {3, 16, 24, 5, 8}, + {5, 16, 6, 7, 5} + } + }, + { + // dynamic + {{1, 5}, 16, {1, 48}, {2, 24}, {2, 64}}, + // target + { + {2, 16, 7, 6, 5}, + {1, 16, 6, 5, 7}, + {3, 16, 5, 7, 6} + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit5D_CPU_Block8, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes5D_block), + ::testing::Values(2, 3, 4), + ::testing::Values(std::vector{1, 2, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked8_5D_ref)), + VariadicSplitLayerCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit5D_CPU_Block16, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes5D_block), + ::testing::Values(2, 3, 4), + ::testing::Values(std::vector{2, 1, -1, 1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(blocked16_5D_ref)), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes3D = { + { {}, {{14, 7, 21}} }, + { + // dynamic + {-1, -1, -1}, + // target + { + {7, 21, 14}, + {21, 7, 14}, + {21, 14, 7}, + } + }, + { + // dynamic + {{1, 60}, {1, 50}, {1, 48}}, + // target + { + {14, 21, 7}, + {21, 7, 14}, + {7, 14, 21}, + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit3D, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes3D), + ::testing::Values(0, 1, 2), + ::testing::Values(std::vector{2, 4, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"}, CPUSpecificParams{{}, {}, {"ref"}, "ref"})), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes2D = { + { {}, {{6, 12}} }, + { + // dynamic + {-1, -1}, + // target + { + {3, 8}, + {10, 4}, + {3, 6}, + } + }, + { + // dynamic + {{1, 60}, {1, 50}}, + // target + { + {3, 4}, + {4, 4}, + {6, 12}, + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit2D, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes2D), + ::testing::Values(0, 1), + ::testing::Values(std::vector{2, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"}, CPUSpecificParams{{}, {}, {"ref"}, "ref"})), + VariadicSplitLayerCPUTest::getTestCaseName); + +const std::vector inputShapes1D = { + { {}, {{10}} }, + { + // dynamic + {-1}, + // target + { + {5}, + {15}, + {10}, + } + }, + { + // dynamic + {{1, 60}}, + // target + { + {15}, + {5}, + {10}, + } + }, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_VariadicSplit1D, VariadicSplitLayerCPUTest, + ::testing::Combine( + ::testing::ValuesIn(inputShapes1D), + ::testing::Values(0), + ::testing::Values(std::vector{2, 1, 1, -1}), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CPUSpecificParams{{}, {}, {}, "unknown"}, CPUSpecificParams{{}, {}, {"ref"}, "ref"})), + VariadicSplitLayerCPUTest::getTestCaseName); + +} // namespace + +} // namespace CPULayerTestsDefinitions \ No newline at end of file diff --git a/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/align_mamtul_input_ranks.cpp b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/align_matmul_input_ranks.cpp similarity index 100% rename from inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/align_mamtul_input_ranks.cpp rename to inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/align_matmul_input_ranks.cpp diff --git a/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp index ca99be789a9006..4704becf624649 100644 --- a/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp +++ b/inference-engine/tests/functional/plugin/cpu/subgraph_tests/src/concat_const_inplace.cpp @@ -13,43 +13,74 @@ using namespace InferenceEngine; namespace SubgraphTestsDefinitions { // Subgraph: /* - * Parameter Constant + * Parameter Constant[FP32/BF16] * \ / * \ / - * Transpose - * Constant / - * \ / + * Transpose[FP32/BF16] + * Constant[FP32] / + * \ X No Reorder * \ / - * Concat (inPlace) + * Concat (inPlace)[FP32/BF16] * | + * Convolution [FP32/BF16] * | - * Result + * Result[FP32/BF16] */ -class ConcatConstantInPlaceTest : virtual public LayerTestsUtils::LayerTestsCommon { +class ConcatConstantInPlaceTest : public testing::WithParamInterface, virtual public LayerTestsUtils::LayerTestsCommon { public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + std::ostringstream result; + result << "ConcatConstantInPlaceTest" << obj.param.name(); + return result.str(); + } + void SetUp() override { targetDevice = CommonTestUtils::DEVICE_CPU; - inPrc = outPrc = Precision::FP32; - const std::vector inputShape = {1, 384, 196}; - auto inputParams = ngraph::builder::makeParams(ngraph::element::f32, {inputShape, inputShape}); + if (Precision::BF16 == (inPrc = outPrc = this->GetParam())) + configuration.insert({ PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES }); + else + configuration.insert({ PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO }); + + const std::vector inputShape = {1, 3, 3, 11}; + auto inputParams = ngraph::builder::makeParams(ngraph::element::f32, {inputShape}); - auto transposeOrder = ngraph::opset8::Constant::create(ngraph::element::i32, {3}, {0, 2, 1}); + auto transposeOrder = ngraph::opset8::Constant::create(ngraph::element::i32, {4}, {0, 3, 2, 1}); auto transpose = std::make_shared(inputParams[0], transposeOrder); - auto concatConstantInput = ngraph::opset8::Constant::create(ngraph::element::f32, {1, 1, 384}, {10.0f}); + auto concatConstantInput = ngraph::opset8::Constant::create(ngraph::element::f32, {1, 1, 3, 3}, {10.0f}); auto concat = ngraph::builder::makeConcat({concatConstantInput, transpose}, 1); - ngraph::ResultVector results{std::make_shared(concat)}; + // convolution + std::vector weightValuesFP32(12); + ngraph::Shape convFilterShape = { 1, 12, 1, 1 }; +// weightValuesFP32.resize(12); + FuncTestUtils::fillInputsBySinValues(weightValuesFP32.data(), weightValuesFP32.size()); + auto weightsNode = std::make_shared(ngraph::element::f32, convFilterShape, weightValuesFP32); + std::shared_ptr conv = std::make_shared( + concat, weightsNode, ngraph::Strides({ 1, 1 }), ngraph::CoordinateDiff({ 0, 0 }), + ngraph::CoordinateDiff({ 0, 0 }), ngraph::Strides({ 1, 1 }), ngraph::op::PadType::EXPLICIT); + conv->set_friendly_name("CONV"); + + ngraph::ResultVector results{std::make_shared(conv)}; function = std::make_shared(results, inputParams, "ConcatConstantInPlace"); } }; namespace { - TEST_F(ConcatConstantInPlaceTest, smoke_ConcatConstantInPlaceTest_CPU) { + TEST_P(ConcatConstantInPlaceTest, smoke_ConcatConstantInPlaceTest_CPU) { SKIP_IF_CURRENT_TEST_IS_DISABLED() Run(); + if (this->GetParam() == Precision::BF16) + CheckNodeOfTypeCount(executableNetwork, "Reorder", 4); + else + CheckNodeOfTypeCount(executableNetwork, "Reorder", 3); } + +INSTANTIATE_TEST_SUITE_P(smoke_ConcatConstantInPlaceTest_CPU, ConcatConstantInPlaceTest, + testing::Values(Precision::FP32, Precision::BF16), + ConcatConstantInPlaceTest::getTestCaseName); + } // namespace -} // namespace SubgraphTestsDefinitions \ No newline at end of file +} // namespace SubgraphTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp b/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp index d55f2a988593b2..7d1dc60109ae2c 100644 --- a/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp +++ b/inference-engine/tests/functional/plugin/cpu/test_utils/fusing_test_utils.hpp @@ -219,18 +219,18 @@ const auto fusingScaleShift = fusingSpecificParams{ std::make_shared(std::vector{ {[](std::shared_ptr inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){ auto localPrc = inpNode->get_element_type(); - ngraph::Shape newShape(inpNode->get_shape().size(), 1); + ngraph::Shape newShape(inpNode->get_output_partial_shape(0).size(), 1); return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape); }, "FakeQuantize(PerTensor)"}}), {"FakeQuantize"} }; const auto fusingFakeQuantizePerChannel = fusingSpecificParams{std::make_shared(std::vector{ {[](std::shared_ptr inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){ auto localPrc = inpNode->get_element_type(); - auto shape = inpNode->get_shape(); + auto shape = inpNode->get_output_partial_shape(0); if (shape.size() == 1) IE_THROW() << "If shape.size() == 1 then Granularity can be PerTensor only"; ngraph::Shape newShape(shape.size(), 1); - newShape[1] = shape[1]; + newShape[1] = shape[1].get_length(); return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape); }, "FakeQuantize(PerChannel)"}}), {"FakeQuantize"}}; diff --git a/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp b/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp index f0deafaf07140d..91d28dc577a947 100644 --- a/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp +++ b/inference-engine/tests/functional/plugin/gna/Import_export_tests/import_export_memory_layer.cpp @@ -65,16 +65,14 @@ class ImportMemoryTest : public testing::WithParamInterfaceImportNetwork(inputStream, targetDevice, configuration); std::vector queryToState; - IE_SUPPRESS_DEPRECATED_START - for (const auto &query_state : executableNetwork.QueryState()) { + InferenceEngine::InferRequest importInfer = importedNetwork.CreateInferRequest(); + for (const auto &query_state : importInfer.QueryState()) { queryToState.push_back(query_state.GetName()); } - for (const auto &next_memory : importedNetwork.QueryState()) { + for (const auto &next_memory : importInfer.QueryState()) { ASSERT_TRUE(std::find(queryToState.begin(), queryToState.end(), next_memory.GetName()) != queryToState.end()) << "State " << next_memory.GetName() << " expected to be in memory states but it is not!"; } - IE_SUPPRESS_DEPRECATED_END - InferenceEngine::InferRequest importInfer = importedNetwork.CreateInferRequest(); importInfer.Infer(); } diff --git a/inference-engine/tests/functional/plugin/gna/scale_factors_tests/eltwise_act_fq.cpp b/inference-engine/tests/functional/plugin/gna/scale_factors_tests/eltwise_act_fq.cpp index b9d54f1308b818..a8d49970d8dd71 100644 --- a/inference-engine/tests/functional/plugin/gna/scale_factors_tests/eltwise_act_fq.cpp +++ b/inference-engine/tests/functional/plugin/gna/scale_factors_tests/eltwise_act_fq.cpp @@ -85,6 +85,8 @@ class EltwiseActFqTest : public testing::WithParamInterface, if (act == ngraph::helpers::ActivationTypes::Log) { // clamp not positive values inputDataMin = 1.0e-3; + // get error threshold value from PWL error + threshold = std::stof(configuration["GNA_PWL_MAX_ERROR_PERCENT"]); } auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); @@ -136,6 +138,7 @@ const std::vector netPrecisions = { const std::vector> configs = { { {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, + {"GNA_PWL_MAX_ERROR_PERCENT", "0.025"} } }; diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/activation.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/activation.cpp index 71c0cfc3d70766..584f31ed76913d 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/activation.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/activation.cpp @@ -6,6 +6,66 @@ #include "single_layer_tests/activation.hpp" #include "common_test_utils/test_constants.hpp" +namespace LayerTestsDefinitions { + +class ActivationLayerGNATest : public ActivationLayerTest { +protected: + void SetUp() override { + ActivationLayerTest::SetUp(); + // TODO: remove after integer inference output support + auto ngPrc = function->get_parameters()[0]->get_element_type().get_type_name(); + if (ngPrc == "u8" || ngPrc == "i16") { + threshold = 1.0; + } + } + + InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override { + bool inPrcSigned = function->get_parameters()[0]->get_element_type().is_signed(); + int32_t data_start_from = -10; + uint32_t data_range = 20; + int32_t resolution = 32768; + switch (activationType) { + case ngraph::helpers::ActivationTypes::Log: { + data_start_from = 1; + data_range = 20; + resolution = 32768; + break; + } + case ngraph::helpers::ActivationTypes::Sign: { + data_start_from = -10; + data_range = 20; + resolution = 3072; + break; + } + case ngraph::helpers::ActivationTypes::Exp: { + const double max_result_on_GNA = 15.9; + const double exp_inverse = std::round(std::log(max_result_on_GNA)); + if (inPrcSigned) { + data_range = exp_inverse * 2.0; + data_start_from = -exp_inverse; + } else { + data_range = exp_inverse; + data_start_from = 0; + } + break; + } + } + if (!inPrcSigned) { + data_range = 15; + data_start_from = 0; + } + + return FuncTestUtils::createAndFillBlob(info.getTensorDesc(), data_range, + data_start_from, resolution); + } +}; + +TEST_P(ActivationLayerGNATest, CompareWithRefs) { + Run(); +} + +} // namespace LayerTestsDefinitions + using namespace LayerTestsDefinitions; using namespace ngraph::helpers; namespace { @@ -16,13 +76,12 @@ const std::vector inputPrecisions = { InferenceEngine::Precision::U8 }; + const std::vector netPrecisions = { - // TODO: Issue:27391 - // InferenceEngine::Precision::FP32, - // TODO: Issue:28036 - // InferenceEngine::Precision::FP16, + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16, InferenceEngine::Precision::I16, - InferenceEngine::Precision::U8 + InferenceEngine::Precision::U8, }; const std::map>> activationTypes = { @@ -62,6 +121,6 @@ const auto basicCases = ::testing::Combine( ); -INSTANTIATE_TEST_SUITE_P(smoke_Activation_Basic, ActivationLayerTest, basicCases, ActivationLayerTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_Activation_Basic, ActivationLayerGNATest, basicCases, ActivationLayerTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/eltwise.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/eltwise.cpp index e065d8597f664c..50153264efbbe5 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/eltwise.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/single_layer_tests/eltwise.cpp @@ -41,10 +41,17 @@ std::vector eltwiseOpTypes = { ngraph::helpers::EltwiseTypes::ADD }; -std::map additional_config = { - {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, - {"GNA_SCALE_FACTOR_0", "1638.4"}, - {"GNA_SCALE_FACTOR_1", "1638.4"} +std::vector> additional_config = { + { + {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, + {"GNA_SCALE_FACTOR_0", "1638.4"}, + {"GNA_SCALE_FACTOR_1", "1638.4"} + }, + { + {"GNA_DEVICE_MODE", "GNA_SW_FP32"}, + {"GNA_SCALE_FACTOR_0", "1638.4"}, + {"GNA_SCALE_FACTOR_1", "1638.4"} + } }; const auto multiply_params = ::testing::Combine( @@ -56,7 +63,7 @@ const auto multiply_params = ::testing::Combine( ::testing::Values(ov::element::undefined), ::testing::Values(ov::element::undefined), ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::Values(additional_config)); + ::testing::ValuesIn(additional_config)); INSTANTIATE_TEST_SUITE_P(smoke_CompareWithRefs, EltwiseLayerTest, multiply_params, EltwiseLayerTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp index c727248cbbd176..082303bddc16a0 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/skip_tests_config.cpp @@ -17,10 +17,7 @@ std::vector disabledTestPatterns() { // TODO: FIX BUG 59041 ".*Behavior.*CallbackThrowException.*", // TODO: FIX BUG 32210 - R"(.*ActivationLayerTest.CompareWithRefs/(Sigmoid|Tanh|Exp|Log).*)", R"(.*ActivationFQSubgraph.*activation=(Exp|Log).*)", - // TODO: Issue 68586 - R"(.*EltwiseActFqTest.*act=Log.*)", // TODO: Issue 32542 R"(.*(EltwiseLayerTest).*eltwiseOpType=(Sum|Sub).*opType=SCALAR.*)", R"(.*(EltwiseLayerTest).*eltwiseOpType=Prod.*secondaryInputType=PARAMETER.*opType=SCALAR.*)", @@ -76,5 +73,8 @@ std::vector disabledTestPatterns() { // TODO: Issue: CVS-69639 R"(.*EltwiseLayerTest.*OpType=Prod.*)", R"(.*EltwiseLayerTest.*OpType=Sum.*PARAMETER.*VECTOR.*)", + // TODO: Issue:27391 + // TODO: Issue:28036 + R"(.*ActivationLayerGNATest.*(Log|Exp).*netPRC=(FP16|FP32).*)", }; } diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/concat_quantization_during_memory_requantization.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/concat_quantization_during_memory_requantization.cpp index 0357c545f57872..5e5618e498a8a6 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/concat_quantization_during_memory_requantization.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/concat_quantization_during_memory_requantization.cpp @@ -15,8 +15,10 @@ namespace { InferenceEngine::Precision::FP32 }; - std::map config = { - {"GNA_COMPACT_MODE", "NO"} + std::vector> additionalConfig = { + { {"GNA_COMPACT_MODE", "NO"} }, + { {"GNA_COMPACT_MODE", "NO"}, + {"GNA_DEVICE_MODE", "GNA_SW_FP32"}} }; std::vector inputSizes = { @@ -37,6 +39,6 @@ namespace { ::testing::Values(CommonTestUtils::DEVICE_GNA), ::testing::ValuesIn(inputSizes), ::testing::ValuesIn(hiddenSizes), - ::testing::Values(config)), + ::testing::ValuesIn(additionalConfig)), ConcatQuantDuringMemoryRequantTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/first_connect_input_concat.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/first_connect_input_concat.cpp index e62bdd99cfcb72..1d9f23edfb4d51 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/first_connect_input_concat.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/first_connect_input_concat.cpp @@ -22,9 +22,15 @@ const std::vector netPrecisions = { InferenceEngine::Precision::FP16, }; -std::map additional_config = { - {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, - {"GNA_COMPACT_MODE", "NO"}, +std::vector> additional_config = { + { + {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, + {"GNA_COMPACT_MODE", "NO"} + }, + { + {"GNA_DEVICE_MODE", "GNA_SW_FP32"}, + {"GNA_COMPACT_MODE", "NO"} + } }; INSTANTIATE_TEST_SUITE_P(smoke_concat_first_input, ConcatFirstInputTest, @@ -32,7 +38,7 @@ INSTANTIATE_TEST_SUITE_P(smoke_concat_first_input, ConcatFirstInputTest, ::testing::ValuesIn(inShapes), ::testing::ValuesIn(netPrecisions), ::testing::Values(CommonTestUtils::DEVICE_GNA), - ::testing::Values(additional_config)), + ::testing::ValuesIn(additional_config)), ConcatFirstInputTest::getTestCaseName); } //namespace diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/multiple_concat.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/multiple_concat.cpp index 2cd3e96ee992e3..52b85236db3222 100644 --- a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/multiple_concat.cpp +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/multiple_concat.cpp @@ -27,10 +27,17 @@ std::vector constant_sizes_unaligned = { 99 }; -std::map additional_config = { - {"GNA_COMPACT_MODE", "NO"}, - {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, - {"GNA_SCALE_FACTOR_0", "3276.8"}, +std::vector> additional_config = { + { + {"GNA_COMPACT_MODE", "NO"}, + {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, + {"GNA_SCALE_FACTOR_0", "3276.8"} + }, + { + {"GNA_COMPACT_MODE", "NO"}, + {"GNA_DEVICE_MODE", "GNA_SW_FP32"}, + {"GNA_SCALE_FACTOR_0", "3276.8"} + }, }; } // namespace @@ -40,7 +47,7 @@ INSTANTIATE_TEST_SUITE_P(I_aligned_C_aligned, MultipleConcatTest, ::testing::Values(InferenceEngine::Precision::FP32), ::testing::ValuesIn(input_sizes_aligned), ::testing::ValuesIn(constant_sizes_aligned), - ::testing::Values(additional_config)), + ::testing::ValuesIn(additional_config)), MultipleConcatTest::getTestCaseName); INSTANTIATE_TEST_SUITE_P(I_aligned_C_unaligned, MultipleConcatTest, @@ -49,7 +56,7 @@ INSTANTIATE_TEST_SUITE_P(I_aligned_C_unaligned, MultipleConcatTest, ::testing::Values(InferenceEngine::Precision::FP32), ::testing::ValuesIn(input_sizes_aligned), ::testing::ValuesIn(constant_sizes_unaligned), - ::testing::Values(additional_config)), + ::testing::ValuesIn(additional_config)), MultipleConcatTest::getTestCaseName); INSTANTIATE_TEST_SUITE_P(I_unaligned_C_aligned, MultipleConcatTest, @@ -58,7 +65,7 @@ INSTANTIATE_TEST_SUITE_P(I_unaligned_C_aligned, MultipleConcatTest, ::testing::Values(InferenceEngine::Precision::FP32), ::testing::ValuesIn(input_sizes_unaligned), ::testing::ValuesIn(constant_sizes_aligned), - ::testing::Values(additional_config)), + ::testing::ValuesIn(additional_config)), MultipleConcatTest::getTestCaseName); INSTANTIATE_TEST_SUITE_P(I_unaligned_C_unaligned, MultipleConcatTest, @@ -67,6 +74,6 @@ INSTANTIATE_TEST_SUITE_P(I_unaligned_C_unaligned, MultipleConcatTest, ::testing::Values(InferenceEngine::Precision::FP32), ::testing::ValuesIn(input_sizes_unaligned), ::testing::ValuesIn(constant_sizes_unaligned), - ::testing::Values(additional_config)), + ::testing::ValuesIn(additional_config)), MultipleConcatTest::getTestCaseName); } // namespace SubgraphTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/gpu/concurrency/gpu_concurrency_tests.cpp b/inference-engine/tests/functional/plugin/gpu/concurrency/gpu_concurrency_tests.cpp new file mode 100644 index 00000000000000..52296a3f42f1d6 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/concurrency/gpu_concurrency_tests.cpp @@ -0,0 +1,110 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include + +#include "openvino/runtime/core.hpp" + +#include +#include +#include +#include "ngraph_functions/subgraph_builders.hpp" +#include "functional_test_utils/blob_utils.hpp" +#include "openvino/core/preprocess/pre_post_process.hpp" +#include "transformations/utils/utils.hpp" + +using namespace ::testing; + +using ConcurrencyTestParams = std::tuple; // number of requests + +class OVConcurrencyTest : public CommonTestUtils::TestsCommon, + public testing::WithParamInterface { + void SetUp() override { + std::tie(num_streams, num_requests) = this->GetParam(); + fn_ptrs = {ngraph::builder::subgraph::makeSplitMultiConvConcat(), + ngraph::builder::subgraph::makeMultiSingleConv()}; + }; +public: + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + size_t streams, requests; + std::tie(streams, requests) = obj.param; + return "_num_streams_" + std::to_string(streams) + "_num_req_" + + std::to_string(requests); + } + +protected: + size_t num_streams; + size_t num_requests; + std::vector> fn_ptrs; +}; + +TEST_P(OVConcurrencyTest, canInferTwoExecNets) { + auto ie = ov::runtime::Core(); + + ov::ResultVector outputs; + std::vector irs; + std::vector> ref; + std::vector outElementsCount; + + for (size_t i = 0; i < fn_ptrs.size(); ++i) { + auto fn = fn_ptrs[i]; + + auto exec_net = ie.compile_model(fn_ptrs[i], CommonTestUtils::DEVICE_GPU, + {{ov::ie::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, std::to_string(num_streams)}}); + + auto input = fn_ptrs[i]->get_parameters().at(0); + auto output = fn_ptrs[i]->get_results().at(0); + + for (int j = 0; j < num_streams * num_requests; j++) { + outputs.push_back(output); + + auto inf_req = exec_net.create_infer_request(); + irs.push_back(inf_req); + + auto tensor = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); + inf_req.set_tensor(input, tensor); + + outElementsCount.push_back(ov::shape_size(fn_ptrs[i]->get_output_shape(0))); + const auto in_tensor = inf_req.get_tensor(input); + const auto tensorSize = in_tensor.get_byte_size(); + const auto inBlobBuf = static_cast(in_tensor.data()); + std::vector inData(inBlobBuf, inBlobBuf + tensorSize); + auto reOutData = ngraph::helpers::interpreterFunction(fn_ptrs[i], {inData}).front().second; + ref.push_back(reOutData); + } + } + + const int niter = 10; + for (int i = 0; i < niter; i++) { + for (auto ir : irs) { + ir.start_async(); + } + + for (auto ir : irs) { + ir.wait(); + } + } + + auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); + for (size_t i = 0; i < irs.size(); ++i) { + const auto &refBuffer = ref[i].data(); + ASSERT_EQ(outElementsCount[i], irs[i].get_tensor(outputs[i]).get_size()); + FuncTestUtils::compareRawBuffers(irs[i].get_tensor(outputs[i]).data(), + reinterpret_cast(refBuffer), outElementsCount[i], + outElementsCount[i], + thr); + } +} + +const std::vector num_streams{ 1, 2 }; +const std::vector num_requests{ 1, 4 }; + +INSTANTIATE_TEST_SUITE_P(smoke_RemoteTensor, OVConcurrencyTest, + ::testing::Combine(::testing::ValuesIn(num_streams), + ::testing::ValuesIn(num_requests)), + OVConcurrencyTest::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/gpu/remote_blob_tests/cldnn_remote_tensor_tests.cpp b/inference-engine/tests/functional/plugin/gpu/remote_blob_tests/cldnn_remote_tensor_tests.cpp deleted file mode 100644 index 21bf8d8988cf43..00000000000000 --- a/inference-engine/tests/functional/plugin/gpu/remote_blob_tests/cldnn_remote_tensor_tests.cpp +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include - -#include "openvino/runtime/gpu/ocl.hpp" -#include "openvino/runtime/core.hpp" - -#include -#include -#include -#include -#include "ngraph_functions/subgraph_builders.hpp" -#include "functional_test_utils/blob_utils.hpp" -#include "openvino/core/preprocess/pre_post_process.hpp" -#include "transformations/utils/utils.hpp" - -using namespace ::testing; - -class OVRemoteTensor_Test : public CommonTestUtils::TestsCommon { -protected: - std::shared_ptr fn_ptr; - - void SetUp() override { - fn_ptr = ngraph::builder::subgraph::makeSplitMultiConvConcat(); - } -}; - -TEST_F(OVRemoteTensor_Test, DISABLED_smoke_canInputUserTensor) { -#if defined(ANDROID) - GTEST_SKIP(); -#endif - auto ie = ov::runtime::Core(); - - using namespace ov::preprocess; - auto function = PrePostProcessor() - .input(InputInfo() - .tensor(InputTensorInfo().set_element_type(ov::element::i8)) - .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) - .build(fn_ptr); - - auto exec_net = ie.compile_model(function, CommonTestUtils::DEVICE_GPU); - - // regular inference - auto inf_req_regular = exec_net.create_infer_request(); - auto input = function->get_parameters().at(0); - auto output = function->get_results().at(0); - auto fakeImageData = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); - - inf_req_regular.set_tensor(input->get_friendly_name(), fakeImageData); - - inf_req_regular.infer(); - auto output_tensor_regular = inf_req_regular.get_tensor(ngraph::op::util::create_ie_output_name(output->input_value(0))); - - // inference using remote tensor - auto inf_req_shared = exec_net.create_infer_request(); - auto cldnn_context = exec_net.get_context().as(); - cl_context ctx = cldnn_context; - auto ocl_instance = std::make_shared(ctx); - cl_int err; - - auto imSize = ov::shape_size(input->get_shape()); - - cl::Buffer shared_buffer(ocl_instance->_context, CL_MEM_READ_WRITE, imSize, NULL, &err); - { - void* buffer = fakeImageData.data(); - ocl_instance->_queue.enqueueWriteBuffer(shared_buffer, true, 0, imSize, buffer); - } - - auto cldnn_tensor = cldnn_context.create_tensor(input->get_element_type(), input->get_shape(), shared_buffer); - inf_req_shared.set_tensor(input->get_friendly_name(), cldnn_tensor); - - inf_req_shared.infer(); - auto output_tensor_shared = inf_req_shared.get_tensor(ngraph::op::util::create_ie_output_name(output->input_value(0))); - - // compare results - { - ASSERT_EQ(output->get_element_type(), ov::element::f32); - ASSERT_EQ(output_tensor_regular.get_size(), output_tensor_shared.get_size()); - auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); - ASSERT_NO_THROW(output_tensor_regular.data()); - ASSERT_NO_THROW(output_tensor_shared.data()); - FuncTestUtils::compare_tensor(output_tensor_regular, output_tensor_shared, thr); - } -} - -TEST_F(OVRemoteTensor_Test, DISABLED_smoke_canInferOnUserContext) { - auto ie = ov::runtime::Core(); - - using namespace ov::preprocess; - auto function = PrePostProcessor() - .input(InputInfo() - .tensor(InputTensorInfo().set_element_type(ov::element::i8)) - .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) - .build(fn_ptr); - - auto exec_net_regular = ie.compile_model(function, CommonTestUtils::DEVICE_GPU); - auto input = function->get_parameters().at(0); - auto output = function->get_results().at(0); - - // regular inference - auto inf_req_regular = exec_net_regular.create_infer_request(); - auto fakeImageData = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); - inf_req_regular.set_tensor(input->get_friendly_name(), fakeImageData); - - inf_req_regular.infer(); - auto output_tensor_regular = inf_req_regular.get_tensor(ngraph::op::util::create_ie_output_name(output->input_value(0))); - - // inference using remote tensor - auto ocl_instance = std::make_shared(); - - auto remote_context = ov::runtime::gpu::ClContext(ie, ocl_instance->_context.get()); - auto exec_net_shared = ie.compile_model(function, remote_context); - auto inf_req_shared = exec_net_shared.create_infer_request(); - inf_req_shared.set_tensor(input->get_friendly_name(), fakeImageData); - - inf_req_shared.infer(); - auto output_tensor_shared = inf_req_shared.get_tensor(ngraph::op::util::create_ie_output_name(output->input_value(0))); - - // compare results - { - ASSERT_EQ(output->get_element_type(), ov::element::f32); - ASSERT_EQ(output_tensor_regular.get_size(), output_tensor_shared.get_size()); - auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); - ASSERT_NO_THROW(output_tensor_regular.data()); - ASSERT_NO_THROW(output_tensor_shared.data()); - FuncTestUtils::compare_tensor(output_tensor_regular, output_tensor_shared, thr); - } -} - -class OVRemoteTensorBatched_Test : public CommonTestUtils::TestsCommon, public testing::WithParamInterface { - void SetUp() override { - num_batch = this->GetParam(); - }; -public: - static std::string getTestCaseName(const testing::TestParamInfo &obj) { - return "num_batch_" + std::to_string(obj.param); - } - -protected: - size_t num_batch; - std::vector> fn_ptrs; -}; - -TEST_P(OVRemoteTensorBatched_Test, DISABLED_canInputNV12) { -#if defined(ANDROID) - GTEST_SKIP(); -#endif - const int height = 16; - const int width = 16; - - // ------------------------------------------------------ - // Prepare input data - std::vector fake_image_data_y; - std::vector fake_image_data_uv; - - for (int i = 0; i < num_batch; i++) { - fake_image_data_y.push_back(FuncTestUtils::create_and_fill_tensor(ov::element::u8, {1, 1, height, width}, 50, 0, 1, i)); - fake_image_data_uv.push_back(FuncTestUtils::create_and_fill_tensor(ov::element::u8, {1, 2, height / 2, width / 2}, 256, 0, 1, i)); - } - - auto ie = ov::runtime::Core(); - - // ------------------------------------------------------ - // inference using remote tensor with batch - auto fn_ptr_remote = ngraph::builder::subgraph::makeConvPoolRelu({num_batch, 3, height, width}); - - // TODO: Add preprocessing! - // CNNNetwork net_remote(fn_ptr_remote); - // net_remote.getInputsInfo().begin()->second->setLayout(Layout::NCHW); - // net_remote.getInputsInfo().begin()->second->setPrecision(Precision::U8); - // net_remote.getInputsInfo().begin()->second->getPreProcess().setColorFormat(ColorFormat::NV12); - - /* XXX: is it correct to set KEY_CLDNN_NV12_TWO_INPUTS in case of remote tensor? */ - auto exec_net_b = ie.compile_model(fn_ptr_remote, CommonTestUtils::DEVICE_GPU, - { { ov::ie::GPUConfigParams::KEY_GPU_NV12_TWO_INPUTS, ov::ie::PluginConfigParams::YES} }); - auto inf_req_remote = exec_net_b.create_infer_request(); - auto cldnn_context = exec_net_b.get_context().as(); - cl_context ctx = cldnn_context.get(); - auto ocl_instance = std::make_shared(ctx); - cl_int err; - - std::vector nv12_image_plane_y, nv12_image_plane_uv; - std::vector img_y, img_uv; - std::vector> tensor_remote; - - for (int i = 0; i < num_batch; i++) { - cl_image_format image_format; - cl_image_desc image_desc = { 0 }; - image_format.image_channel_order = CL_R; - image_format.image_channel_data_type = CL_UNORM_INT8; - image_desc.image_type = CL_MEM_OBJECT_IMAGE2D; - image_desc.image_width = width; - image_desc.image_height = height; - - nv12_image_plane_y.push_back(clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, NULL, &err)); - ASSERT_EQ(err, 0); - - image_format.image_channel_order = CL_RG; - image_desc.image_width = width / 2; - image_desc.image_height = height / 2; - - nv12_image_plane_uv.push_back(clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, NULL, &err)); - ASSERT_EQ(err, 0); - - size_t origin[3] = { 0, 0, 0 }; - size_t y_region[3] = { (size_t)width, (size_t)height, 1 }; - size_t uv_region[3] = { (size_t)width / 2, (size_t)height / 2, 1 }; - - err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_y[i], - true, origin, y_region, 0, 0, fake_image_data_y[i].data(), 0, NULL, NULL); - ASSERT_EQ(err, 0); - - err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_uv[i], - true, origin, uv_region, 0, 0, fake_image_data_uv[i].data(), 0, NULL, NULL); - ASSERT_EQ(err, 0); - - img_y.push_back(cl::Image2D(nv12_image_plane_y[i])); - img_uv.push_back(cl::Image2D(nv12_image_plane_uv[i])); - - tensor_remote.push_back(cldnn_context.create_tensor_nv12(img_y[i], img_uv[i])); - } - - if (num_batch == 1) { - inf_req_remote.set_tensor(fn_ptr_remote->get_parameters().front()->get_friendly_name() + "/y", tensor_remote[0].first); - inf_req_remote.set_tensor(fn_ptr_remote->get_parameters().front()->get_friendly_name() + "/uv", tensor_remote[0].second); - } else { - GTEST_SKIP() << "Not implemented test"; - } - - inf_req_remote.infer(); - - auto outputTensor_shared = inf_req_remote.get_tensor( - ngraph::op::util::create_ie_output_name(fn_ptr_remote->get_results().front()->input_value(0))); - - // ------------------------------------------------------ - // Setup to inference using local tensor with batch=1 - auto fn_ptr_local = ngraph::builder::subgraph::makeConvPoolRelu({1, 3, height, width}); - - // net_local.getInputsInfo().begin()->second->setLayout(Layout::NCHW); - // net_local.getInputsInfo().begin()->second->setPrecision(Precision::U8); - // net_local.getInputsInfo().begin()->second->getPreProcess().setColorFormat(ColorFormat::NV12); - - auto exec_net_b1 = ie.compile_model(fn_ptr_local, CommonTestUtils::DEVICE_GPU); - - auto inf_req_local = exec_net_b1.create_infer_request(); - - // Run regular input for each image and compare against batched tensor - for (int i = 0; i < num_batch; i++) { - auto y_tensor = ov::runtime::Tensor{ov::element::u8, {1, 1, height, width}}; - auto uv_tensor = ov::runtime::Tensor{ov::element::u8, {1, 2, height / 2, width / 2}}; - inf_req_local.set_tensor(fn_ptr_local->get_parameters().front()->get_friendly_name() + "/y", y_tensor); - inf_req_local.set_tensor(fn_ptr_local->get_parameters().front()->get_friendly_name() + "/uv", uv_tensor); - inf_req_local.infer(); - auto output_tensor_local = inf_req_local.get_tensor( - ngraph::op::util::create_ie_output_name(fn_ptr_local->get_results().front()->input_value(0))); - - // This network generates [1, size] tensor whether batch=1 or 2. So need to split - auto split_shared_tensor = ov::runtime::Tensor{output_tensor_local.get_element_type(), - output_tensor_local.get_shape(), - outputTensor_shared.data() + output_tensor_local.get_size() * i}; - ASSERT_EQ(output_tensor_local.get_size(), split_shared_tensor.get_size()); - float thr = 0.1; - - FuncTestUtils::compare_tensor(output_tensor_local, split_shared_tensor, thr, "", false); - } -} - -const std::vector num_batches{1, 2, 4}; - -INSTANTIATE_TEST_SUITE_P(smoke_RemoteTensor, OVRemoteTensorBatched_Test, ::testing::ValuesIn(num_batches), OVRemoteTensorBatched_Test::getTestCaseName); - -using TwoNetsParams = std::tuple; // number of requests - -class OVRemoteTensorTwoNets_Test : public CommonTestUtils::TestsCommon, - public testing::WithParamInterface { - void SetUp() override { - std::tie(num_streams, num_requests) = this->GetParam(); - fn_ptrs = {ngraph::builder::subgraph::makeSplitMultiConvConcat(), - ngraph::builder::subgraph::makeMultiSingleConv()}; - }; -public: - static std::string getTestCaseName(const testing::TestParamInfo& obj) { - size_t streams, requests; - std::tie(streams, requests) = obj.param; - return "_num_streams_" + std::to_string(streams) + "_num_req_" + - std::to_string(requests); - } - -protected: - size_t num_streams; - size_t num_requests; - std::vector> fn_ptrs; -}; - -TEST_P(OVRemoteTensorTwoNets_Test, DISABLED_canInferTwoExecNets) { - auto ie = ov::runtime::Core(); - - std::vector outputs; - std::vector irs; - std::vector> ref; - std::vector outElementsCount; - - for (size_t i = 0; i < fn_ptrs.size(); ++i) { - auto fn = fn_ptrs[i]; - - auto exec_net = ie.compile_model(fn_ptrs[i], CommonTestUtils::DEVICE_GPU, - {{ov::ie::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, std::to_string(num_streams)}}); - - auto input = fn_ptrs[i]->get_parameters().at(0); - auto output = fn_ptrs[i]->get_results().at(0); - - for (int j = 0; j < num_streams * num_requests; j++) { - outputs.push_back(ngraph::op::util::create_ie_output_name(output->input_value(0))); - - auto inf_req = exec_net.create_infer_request(); - irs.push_back(inf_req); - - auto tensor = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); - inf_req.set_tensor(input->get_friendly_name(), tensor); - - outElementsCount.push_back( - std::accumulate(begin(fn_ptrs[i]->get_output_shape(0)), end(fn_ptrs[i]->get_output_shape(0)), 1, - std::multiplies())); - const auto in_tensor = inf_req.get_tensor(input->get_friendly_name()); - const auto tensorSize = in_tensor.get_byte_size(); - const auto inBlobBuf = static_cast(in_tensor.data()); - std::vector inData(inBlobBuf, inBlobBuf + tensorSize); - auto reOutData = ngraph::helpers::interpreterFunction(fn_ptrs[i], {inData}).front().second; - ref.push_back(reOutData); - } - } - - const int niter = 10; - for (int i = 0; i < niter; i++) { - for (auto ir : irs) { - ir.start_async(); - } - - for (auto ir : irs) { - ir.wait(); - } - } - - auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); - for (size_t i = 0; i < irs.size(); ++i) { - const auto &refBuffer = ref[i].data(); - ASSERT_EQ(outElementsCount[i], irs[i].get_tensor(outputs[i]).get_size()); - FuncTestUtils::compareRawBuffers(irs[i].get_tensor(outputs[i]).data(), - reinterpret_cast(refBuffer), outElementsCount[i], - outElementsCount[i], - thr); - } -} - -const std::vector num_streams{ 1, 2 }; -const std::vector num_requests{ 1, 4 }; - -INSTANTIATE_TEST_SUITE_P(smoke_RemoteTensor, OVRemoteTensorTwoNets_Test, - ::testing::Combine(::testing::ValuesIn(num_streams), - ::testing::ValuesIn(num_requests)), - OVRemoteTensorTwoNets_Test::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/gpu/remote_blob_tests/gpu_remote_tensor_tests.cpp b/inference-engine/tests/functional/plugin/gpu/remote_blob_tests/gpu_remote_tensor_tests.cpp new file mode 100644 index 00000000000000..b593c29183dac8 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/remote_blob_tests/gpu_remote_tensor_tests.cpp @@ -0,0 +1,479 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include + +#include "openvino/runtime/gpu/ocl/ocl.hpp" +#include "openvino/runtime/core.hpp" + +#include +#include +#include +#include +#include "ngraph_functions/subgraph_builders.hpp" +#include "functional_test_utils/blob_utils.hpp" +#include "openvino/core/preprocess/pre_post_process.hpp" +#include "transformations/utils/utils.hpp" + +using namespace ::testing; + +class OVRemoteTensor_Test : public CommonTestUtils::TestsCommon { +protected: + std::shared_ptr fn_ptr; + + void SetUp() override { + fn_ptr = ngraph::builder::subgraph::makeSplitMultiConvConcat(); + } +}; + +TEST_F(OVRemoteTensor_Test, smoke_canInputUserTensor) { +#if defined(ANDROID) + GTEST_SKIP(); +#endif + auto ie = ov::runtime::Core(); + + using namespace ov::preprocess; + auto function = PrePostProcessor(fn_ptr) + .input(InputInfo() + .tensor(InputTensorInfo().set_element_type(ov::element::i8)) + .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) + .build(); + + auto exec_net = ie.compile_model(function, CommonTestUtils::DEVICE_GPU); + + // regular inference + auto inf_req_regular = exec_net.create_infer_request(); + auto input = function->get_parameters().at(0); + auto output = function->get_results().at(0); + auto fakeImageData = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); + + inf_req_regular.set_tensor(input, fakeImageData); + + inf_req_regular.infer(); + auto output_tensor_regular = inf_req_regular.get_tensor(output); + + // inference using remote tensor + auto inf_req_shared = exec_net.create_infer_request(); + auto cldnn_context = exec_net.get_context().as(); + cl_context ctx = cldnn_context; + auto ocl_instance = std::make_shared(ctx); + cl_int err; + + auto imSize = ov::shape_size(input->get_shape()); + + cl::Buffer shared_buffer(ocl_instance->_context, CL_MEM_READ_WRITE, imSize, NULL, &err); + { + void* buffer = fakeImageData.data(); + ocl_instance->_queue.enqueueWriteBuffer(shared_buffer, true, 0, imSize, buffer); + } + + auto cldnn_tensor = cldnn_context.create_tensor(input->get_element_type(), input->get_shape(), shared_buffer); + inf_req_shared.set_tensor(input, cldnn_tensor); + + inf_req_shared.infer(); + auto output_tensor_shared = inf_req_shared.get_tensor(output); + + // compare results + { + ASSERT_EQ(output->get_element_type(), ov::element::f32); + ASSERT_EQ(output_tensor_regular.get_size(), output_tensor_shared.get_size()); + auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); + ASSERT_NO_THROW(output_tensor_regular.data()); + ASSERT_NO_THROW(output_tensor_shared.data()); + FuncTestUtils::compare_tensor(output_tensor_regular, output_tensor_shared, thr); + } +} + +TEST_F(OVRemoteTensor_Test, smoke_canInferOnUserContext) { + auto ie = ov::runtime::Core(); + + using namespace ov::preprocess; + auto function = PrePostProcessor(fn_ptr) + .input(InputInfo() + .tensor(InputTensorInfo().set_element_type(ov::element::i8)) + .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) + .build(); + + auto exec_net_regular = ie.compile_model(function, CommonTestUtils::DEVICE_GPU); + auto input = function->get_parameters().at(0); + auto output = function->get_results().at(0); + + // regular inference + auto inf_req_regular = exec_net_regular.create_infer_request(); + auto fakeImageData = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); + inf_req_regular.set_tensor(input, fakeImageData); + + inf_req_regular.infer(); + auto output_tensor_regular = inf_req_regular.get_tensor(exec_net_regular.output()); + + // inference using remote tensor + auto ocl_instance = std::make_shared(); + + auto remote_context = ov::runtime::gpu::ocl::ClContext(ie, ocl_instance->_context.get()); + auto exec_net_shared = ie.compile_model(function, remote_context); + auto inf_req_shared = exec_net_shared.create_infer_request(); + inf_req_shared.set_tensor(input, fakeImageData); + + inf_req_shared.infer(); + auto output_tensor_shared = inf_req_shared.get_tensor(output); + + // compare results + { + ASSERT_EQ(output->get_element_type(), ov::element::f32); + ASSERT_EQ(output_tensor_regular.get_size(), output_tensor_shared.get_size()); + auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); + ASSERT_NO_THROW(output_tensor_regular.data()); + ASSERT_NO_THROW(output_tensor_shared.data()); + FuncTestUtils::compare_tensor(output_tensor_regular, output_tensor_shared, thr); + } +} + +TEST_F(OVRemoteTensor_Test, smoke_canInferOnUserContextWithMultipleDevices) { + auto ie = ov::runtime::Core(); + + using namespace ov::preprocess; + auto function = PrePostProcessor(fn_ptr) + .input(InputInfo() + .tensor(InputTensorInfo().set_element_type(ov::element::i8)) + .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) + .build(); + + auto exec_net_regular = ie.compile_model(function, CommonTestUtils::DEVICE_GPU); + auto input = function->get_parameters().at(0); + auto output = function->get_results().at(0); + + // regular inference + auto inf_req_regular = exec_net_regular.create_infer_request(); + auto fakeImageData = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); + inf_req_regular.set_tensor(input, fakeImageData); + + inf_req_regular.infer(); + auto output_tensor_regular = inf_req_regular.get_tensor(exec_net_regular.output()); + + // inference using remote tensor + + auto ocl_instance_tmp = std::make_shared(); + cl::Context multi_device_ctx({ocl_instance_tmp->_device, ocl_instance_tmp->_device}); + auto ocl_instance = std::make_shared(multi_device_ctx.get()); + + auto remote_context = ov::runtime::gpu::ocl::ClContext(ie, ocl_instance->_context.get(), 1); + + ASSERT_EQ(remote_context.get_device_name(), "GPU.0"); + auto exec_net_shared = ie.compile_model(function, remote_context); + auto inf_req_shared = exec_net_shared.create_infer_request(); + inf_req_shared.set_tensor(input, fakeImageData); + + inf_req_shared.infer(); + auto output_tensor_shared = inf_req_shared.get_tensor(output); + + // compare results + { + ASSERT_EQ(output->get_element_type(), ov::element::f32); + ASSERT_EQ(output_tensor_regular.get_size(), output_tensor_shared.get_size()); + auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); + ASSERT_NO_THROW(output_tensor_regular.data()); + ASSERT_NO_THROW(output_tensor_shared.data()); + FuncTestUtils::compare_tensor(output_tensor_regular, output_tensor_shared, thr); + } +} + +TEST_F(OVRemoteTensor_Test, smoke_canInferOnUserQueue_out_of_order) { + auto ie = ov::runtime::Core(); + + using namespace ov::preprocess; + auto function = PrePostProcessor(fn_ptr) + .input(InputInfo() + .tensor(InputTensorInfo().set_element_type(ov::element::i8)) + .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) + .build(); + + auto exec_net_regular = ie.compile_model(function, CommonTestUtils::DEVICE_GPU); + auto input = function->get_parameters().at(0); + auto output = function->get_results().at(0); + + // regular inference + auto inf_req_regular = exec_net_regular.create_infer_request(); + auto fakeImageData = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); + inf_req_regular.set_tensor(input, fakeImageData); + + inf_req_regular.infer(); + auto output_tensor_regular = inf_req_regular.get_tensor(exec_net_regular.output()); + + auto in_size = ov::shape_size(input->get_output_shape(0)) * input->get_output_element_type(0).size(); + auto out_size = ov::shape_size(output->get_output_shape(0)) * output->get_output_element_type(0).size(); + + // inference using remote tensor + auto ocl_instance = std::make_shared(); + cl_int err; + + // Allocate shared buffers for input and output data which will be set to infer request + cl::Buffer shared_input_buffer(ocl_instance->_context, CL_MEM_READ_WRITE, in_size, NULL, &err); + cl::Buffer shared_output_buffer(ocl_instance->_context, CL_MEM_READ_WRITE, out_size, NULL, &err); + + auto remote_context = ov::runtime::gpu::ocl::ClContext(ie, ocl_instance->_queue.get()); + auto exec_net_shared = ie.compile_model(function, remote_context); + auto gpu_context = exec_net_shared.get_context().as(); + + auto gpu_in_tensor = gpu_context.create_tensor(input->get_output_element_type(0), input->get_output_shape(0), shared_input_buffer); + auto gpu_out_tensor = gpu_context.create_tensor(output->get_output_element_type(0), output->get_output_shape(0), shared_output_buffer); + auto out_tensor = FuncTestUtils::create_and_fill_tensor(output->get_output_element_type(0), output->get_output_shape(0)); + + auto inf_req_shared = exec_net_shared.create_infer_request(); + inf_req_shared.set_tensor(input, gpu_in_tensor); + inf_req_shared.set_tensor(output, gpu_out_tensor); + + // 1. Pre-processing. Enqueue non-blocking copy from host ptr to shared device input buffer and barrier to ensure that copy is finished before + // inference primitives starts execution + { + void* buffer = fakeImageData.data(); + ocl_instance->_queue.enqueueWriteBuffer(shared_input_buffer, false, 0, in_size, buffer); + ocl_instance->_queue.enqueueBarrierWithWaitList(nullptr, nullptr); + } + + // 2. Enqueue inference primitives. With shared queue this call ensures that all kernels are scheduled to the corresponding queue + // before giving the control back + inf_req_shared.start_async(); + + // 3. Post-processing. Enqueue copy from shared blob with inference result to another output blob + // Enqueue barrier with empty wait list is needed to ensure that previous kernels are finished before copying the data. It's needed here since we + // create OOO queue. + // Note: inf_req_shared.wait() can be dropped in some cases, but if plugin-side post-processing is required, + // then the result may be incorrect without Wait(). + { + ocl_instance->_queue.enqueueBarrierWithWaitList(nullptr, nullptr); + ocl_instance->_queue.enqueueReadBuffer(shared_output_buffer, false, 0, out_size, out_tensor.data(), nullptr, nullptr); + } + + // 4. Wait for infer request and post-processing completion + ocl_instance->_queue.finish(); + + // compare results + { + ASSERT_EQ(output->get_element_type(), ov::element::f32); + ASSERT_EQ(output_tensor_regular.get_size(), out_tensor.get_size()); + auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); + ASSERT_NO_THROW(output_tensor_regular.data()); + FuncTestUtils::compare_tensor(output_tensor_regular, out_tensor, thr); + } +} + +TEST_F(OVRemoteTensor_Test, smoke_canInferOnUserQueue_in_order) { + auto ie = ov::runtime::Core(); + + using namespace ov::preprocess; + auto function = PrePostProcessor(fn_ptr) + .input(InputInfo() + .tensor(InputTensorInfo().set_element_type(ov::element::i8)) + .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) + .build(); + + auto exec_net_regular = ie.compile_model(function, CommonTestUtils::DEVICE_GPU); + auto input = function->get_parameters().at(0); + auto output = function->get_results().at(0); + + // regular inference + auto inf_req_regular = exec_net_regular.create_infer_request(); + auto fakeImageData = FuncTestUtils::create_and_fill_tensor(input->get_element_type(), input->get_shape()); + inf_req_regular.set_tensor(input, fakeImageData); + + inf_req_regular.infer(); + auto output_tensor_regular = inf_req_regular.get_tensor(exec_net_regular.output()); + + auto in_size = ov::shape_size(input->get_output_shape(0)) * input->get_output_element_type(0).size(); + auto out_size = ov::shape_size(output->get_output_shape(0)) * output->get_output_element_type(0).size(); + + // inference using remote tensor + auto ocl_instance = std::make_shared(); + ocl_instance->_queue = cl::CommandQueue(ocl_instance->_context, ocl_instance->_device); + cl_int err; + + // Allocate shared buffers for input and output data which will be set to infer request + cl::Buffer shared_input_buffer(ocl_instance->_context, CL_MEM_READ_WRITE, in_size, NULL, &err); + cl::Buffer shared_output_buffer(ocl_instance->_context, CL_MEM_READ_WRITE, out_size, NULL, &err); + + auto remote_context = ov::runtime::gpu::ocl::ClContext(ie, ocl_instance->_queue.get()); + auto exec_net_shared = ie.compile_model(function, remote_context); + auto gpu_context = exec_net_shared.get_context().as(); + + auto gpu_in_tensor = gpu_context.create_tensor(input->get_output_element_type(0), input->get_output_shape(0), shared_input_buffer); + auto gpu_out_tensor = gpu_context.create_tensor(output->get_output_element_type(0), output->get_output_shape(0), shared_output_buffer); + auto out_tensor = FuncTestUtils::create_and_fill_tensor(output->get_output_element_type(0), output->get_output_shape(0)); + + auto inf_req_shared = exec_net_shared.create_infer_request(); + inf_req_shared.set_tensor(input, gpu_in_tensor); + inf_req_shared.set_tensor(output, gpu_out_tensor); + + // 1. Pre-processing. Enqueue non-blocking copy from host ptr to shared device input buffer + { + void* buffer = fakeImageData.data(); + ocl_instance->_queue.enqueueWriteBuffer(shared_input_buffer, false, 0, in_size, buffer); + } + + // 2. Enqueue inference primitives. With shared queue this call ensures that all kernels are scheduled to the corresponding queue + // before giving the control back + inf_req_shared.start_async(); + + // 3. Post-processing. Enqueue copy from shared blob with inference result to another output blob + // Note: inf_req_shared.Wait() can be dropped in some cases, but if plugin-side post-processing is required, + // then the result may be incorrect without Wait(). + { + ocl_instance->_queue.enqueueReadBuffer(shared_output_buffer, false, 0, out_size, out_tensor.data(), nullptr, nullptr); + } + + // 4. Wait for infer request and post-processing completion + ocl_instance->_queue.finish(); + + // compare results + { + ASSERT_EQ(output->get_element_type(), ov::element::f32); + ASSERT_EQ(output_tensor_regular.get_size(), out_tensor.get_size()); + auto thr = FuncTestUtils::GetComparisonThreshold(InferenceEngine::Precision::FP32); + ASSERT_NO_THROW(output_tensor_regular.data()); + FuncTestUtils::compare_tensor(output_tensor_regular, out_tensor, thr); + } +} + +class OVRemoteTensorBatched_Test : public CommonTestUtils::TestsCommon, public testing::WithParamInterface { + void SetUp() override { + num_batch = this->GetParam(); + }; +public: + static std::string getTestCaseName(const testing::TestParamInfo &obj) { + return "num_batch_" + std::to_string(obj.param); + } + +protected: + size_t num_batch; + std::vector> fn_ptrs; +}; + +TEST_P(OVRemoteTensorBatched_Test, DISABLED_canInputNV12) { +#if defined(ANDROID) + GTEST_SKIP(); +#endif + const int height = 16; + const int width = 16; + + // ------------------------------------------------------ + // Prepare input data + std::vector fake_image_data_y; + std::vector fake_image_data_uv; + + for (int i = 0; i < num_batch; i++) { + fake_image_data_y.push_back(FuncTestUtils::create_and_fill_tensor(ov::element::u8, {1, 1, height, width}, 50, 0, 1, i)); + fake_image_data_uv.push_back(FuncTestUtils::create_and_fill_tensor(ov::element::u8, {1, 2, height / 2, width / 2}, 256, 0, 1, i)); + } + + auto ie = ov::runtime::Core(); + + // ------------------------------------------------------ + // inference using remote tensor with batch + auto fn_ptr_remote = ngraph::builder::subgraph::makeConvPoolRelu({num_batch, 3, height, width}); + + using namespace ov::preprocess; + auto function = PrePostProcessor(fn_ptr_remote) + .input(InputInfo() + .tensor(InputTensorInfo().set_element_type(ov::element::i8).set_color_format(ov::preprocess::ColorFormat::NV12_TWO_PLANES)) + .preprocess(PreProcessSteps().convert_element_type(ov::element::f32))) + .build(); + + auto exec_net_b = ie.compile_model(fn_ptr_remote, CommonTestUtils::DEVICE_GPU); + auto inf_req_remote = exec_net_b.create_infer_request(); + auto cldnn_context = exec_net_b.get_context().as(); + cl_context ctx = cldnn_context.get(); + auto ocl_instance = std::make_shared(ctx); + cl_int err; + + std::vector nv12_image_plane_y, nv12_image_plane_uv; + std::vector img_y, img_uv; + std::vector> tensor_remote; + + for (int i = 0; i < num_batch; i++) { + cl_image_format image_format; + cl_image_desc image_desc = { 0 }; + image_format.image_channel_order = CL_R; + image_format.image_channel_data_type = CL_UNORM_INT8; + image_desc.image_type = CL_MEM_OBJECT_IMAGE2D; + image_desc.image_width = width; + image_desc.image_height = height; + + nv12_image_plane_y.push_back(clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, NULL, &err)); + ASSERT_EQ(err, 0); + + image_format.image_channel_order = CL_RG; + image_desc.image_width = width / 2; + image_desc.image_height = height / 2; + + nv12_image_plane_uv.push_back(clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, NULL, &err)); + ASSERT_EQ(err, 0); + + size_t origin[3] = { 0, 0, 0 }; + size_t y_region[3] = { (size_t)width, (size_t)height, 1 }; + size_t uv_region[3] = { (size_t)width / 2, (size_t)height / 2, 1 }; + + err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_y[i], + true, origin, y_region, 0, 0, fake_image_data_y[i].data(), 0, NULL, NULL); + ASSERT_EQ(err, 0); + + err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_uv[i], + true, origin, uv_region, 0, 0, fake_image_data_uv[i].data(), 0, NULL, NULL); + ASSERT_EQ(err, 0); + + img_y.push_back(cl::Image2D(nv12_image_plane_y[i])); + img_uv.push_back(cl::Image2D(nv12_image_plane_uv[i])); + + tensor_remote.push_back(cldnn_context.create_tensor_nv12(img_y[i], img_uv[i])); + } + + if (num_batch == 1) { + inf_req_remote.set_tensor(fn_ptr_remote->get_parameters().front()->get_friendly_name() + "/y", tensor_remote[0].first); + inf_req_remote.set_tensor(fn_ptr_remote->get_parameters().front()->get_friendly_name() + "/uv", tensor_remote[0].second); + } else { + GTEST_SKIP() << "Not implemented test"; + } + + inf_req_remote.infer(); + + auto outputTensor_shared = inf_req_remote.get_tensor( + ngraph::op::util::create_ie_output_name(fn_ptr_remote->get_results().front()->input_value(0))); + + // ------------------------------------------------------ + // Setup to inference using local tensor with batch=1 + auto fn_ptr_local = ngraph::builder::subgraph::makeConvPoolRelu({1, 3, height, width}); + + // net_local.getInputsInfo().begin()->second->setLayout(Layout::NCHW); + // net_local.getInputsInfo().begin()->second->setPrecision(Precision::U8); + // net_local.getInputsInfo().begin()->second->getPreProcess().setColorFormat(ColorFormat::NV12); + + auto exec_net_b1 = ie.compile_model(fn_ptr_local, CommonTestUtils::DEVICE_GPU); + + auto inf_req_local = exec_net_b1.create_infer_request(); + + // Run regular input for each image and compare against batched tensor + for (int i = 0; i < num_batch; i++) { + auto y_tensor = ov::runtime::Tensor{ov::element::u8, {1, 1, height, width}}; + auto uv_tensor = ov::runtime::Tensor{ov::element::u8, {1, 2, height / 2, width / 2}}; + inf_req_local.set_tensor(fn_ptr_local->get_parameters().front()->get_friendly_name() + "/y", y_tensor); + inf_req_local.set_tensor(fn_ptr_local->get_parameters().front()->get_friendly_name() + "/uv", uv_tensor); + inf_req_local.infer(); + auto output_tensor_local = inf_req_local.get_tensor( + ngraph::op::util::create_ie_output_name(fn_ptr_local->get_results().front()->input_value(0))); + + // This network generates [1, size] tensor whether batch=1 or 2. So need to split + auto split_shared_tensor = ov::runtime::Tensor{output_tensor_local.get_element_type(), + output_tensor_local.get_shape(), + outputTensor_shared.data() + output_tensor_local.get_size() * i}; + ASSERT_EQ(output_tensor_local.get_size(), split_shared_tensor.get_size()); + float thr = 0.1; + + FuncTestUtils::compare_tensor(output_tensor_local, split_shared_tensor, thr, "", false); + } +} + +const std::vector num_batches{1, 2, 4}; + +INSTANTIATE_TEST_SUITE_P(smoke_RemoteTensor, OVRemoteTensorBatched_Test, ::testing::ValuesIn(num_batches), OVRemoteTensorBatched_Test::getTestCaseName); diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/callback.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/callback.cpp new file mode 100644 index 00000000000000..1bc86291780dba --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/callback.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/ov_infer_request/callback.hpp" + +using namespace ov::test::behavior; + +namespace { +const std::vector> configs = { + {}, + {{InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}}, +}; + +const std::vector> multiConfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, OVInferRequestCallbackTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + OVInferRequestCallbackTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, OVInferRequestCallbackTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(multiConfigs)), + OVInferRequestCallbackTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, OVInferRequestCallbackTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(multiConfigs)), + OVInferRequestCallbackTests::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/cancellation.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/cancellation.cpp new file mode 100644 index 00000000000000..7279f2b5e8657f --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/cancellation.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/ov_infer_request/cancellation.hpp" + +using namespace ov::test::behavior; + +namespace { +const std::vector> configs = { + {}, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, OVInferRequestCancellationTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + OVInferRequestCancellationTests::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/io_tensor.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/io_tensor.cpp new file mode 100644 index 00000000000000..543ca49de058b5 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/io_tensor.cpp @@ -0,0 +1,83 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/ov_infer_request/io_tensor.hpp" + +using namespace ov::test::behavior; + +namespace { +const std::vector> configs = { + {}, + {{InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}}, +}; + +const std::vector> Multiconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +const std::vector> Autoconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, OVInferRequestIOTensorTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + OVInferRequestIOTensorTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, OVInferRequestIOTensorTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + OVInferRequestIOTensorTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, OVInferRequestIOTensorTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + OVInferRequestIOTensorTest::getTestCaseName); + +std::vector prcs = { + ov::element::boolean, + ov::element::bf16, + ov::element::f16, + ov::element::f32, + ov::element::f64, + ov::element::i4, + ov::element::i8, + ov::element::i16, + ov::element::i32, + ov::element::i64, + ov::element::u1, + ov::element::u4, + ov::element::u8, + ov::element::u16, + ov::element::u32, + ov::element::u64, +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, OVInferRequestIOTensorSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + OVInferRequestIOTensorSetPrecisionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, OVInferRequestIOTensorSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + OVInferRequestIOTensorSetPrecisionTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, OVInferRequestIOTensorSetPrecisionTest, + ::testing::Combine( + ::testing::ValuesIn(prcs), + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + OVInferRequestIOTensorSetPrecisionTest::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/multithreading.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/multithreading.cpp new file mode 100644 index 00000000000000..10ea6764576f7c --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/multithreading.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/ov_infer_request/multithreading.hpp" + +using namespace ov::test::behavior; + +namespace { + +const std::vector> configs = { + {}, + {{InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}}, +}; + +const std::vector> Multiconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, OVInferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + OVInferRequestMultithreadingTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, OVInferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + OVInferRequestMultithreadingTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, OVInferRequestMultithreadingTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Multiconfigs)), + OVInferRequestMultithreadingTests::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/perf_counters.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/perf_counters.cpp new file mode 100644 index 00000000000000..02ccf0a3c05a78 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/perf_counters.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "behavior/ov_infer_request/perf_counters.hpp" + +using namespace ov::test::behavior; + +namespace { +TEST_P(OVInferRequestPerfCountersTest, CheckOperationInProfilingInfo) { + req = execNet.create_infer_request(); + ASSERT_NO_THROW(req.infer()); + + std::vector profiling_info; + ASSERT_NO_THROW(profiling_info = req.get_profiling_info()); + + for (const auto& op : function->get_ops()) { + auto op_is_in_profiling_info = std::any_of(std::begin(profiling_info), std::end(profiling_info), + [&] (const ov::runtime::ProfilingInfo& info) { + if (info.node_name.find(op->get_friendly_name() + "_") != std::string::npos || info.node_name == op->get_friendly_name()) { + return true; + } else { + return false; + } + }); + ASSERT_TRUE(op_is_in_profiling_info) << "For op: " << op; + } +} + +const std::vector> configs = { + {} +}; + +const std::vector> Multiconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +const std::vector> Autoconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, OVInferRequestPerfCountersTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + OVInferRequestPerfCountersTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, OVInferRequestPerfCountersTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + OVInferRequestPerfCountersTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, OVInferRequestPerfCountersTest, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + OVInferRequestPerfCountersTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/wait.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/wait.cpp new file mode 100644 index 00000000000000..4d37ffc6b8f3ac --- /dev/null +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/behavior/ov_infer_request/wait.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "behavior/ov_infer_request/wait.hpp" + +using namespace ov::test::behavior; + +namespace { + +const std::vector> configs = { + {}, + {{InferenceEngine::PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS, InferenceEngine::PluginConfigParams::GPU_THROUGHPUT_AUTO}}, +}; + +const std::vector> Multiconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +const std::vector> Autoconfigs = { + {{ MULTI_CONFIG_KEY(DEVICE_PRIORITIES) , CommonTestUtils::DEVICE_GPU}} +}; + +INSTANTIATE_TEST_SUITE_P(smoke_BehaviorTests, OVInferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_GPU), + ::testing::ValuesIn(configs)), + OVInferRequestWaitTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Multi_BehaviorTests, OVInferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_MULTI), + ::testing::ValuesIn(Multiconfigs)), + OVInferRequestWaitTests::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, OVInferRequestWaitTests, + ::testing::Combine( + ::testing::Values(CommonTestUtils::DEVICE_AUTO), + ::testing::ValuesIn(Autoconfigs)), + OVInferRequestWaitTests::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp index 6d13029f2a248b..460ca5fed23a9a 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/convolution_transformation.cpp @@ -17,8 +17,7 @@ const std::vector netPrecisions = { }; const std::vector trasformationParamValues = { - LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams(), - // LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams().setUpdatePrecisions(false), + LayerTestsUtils::LayerTransformationParamsNGraphFactory::createParams() }; const std::vector params = { @@ -61,7 +60,30 @@ const std::vector params false, "Convolution", "U8" - } + }, + { + { 256ul, ngraph::Shape { 1 }, { 0.f }, { 255.f }, { -18.7f }, { 18.8f } }, + true, + { + 255ul, ngraph::Shape { 6, 1, 1, 1 }, { -0.6f }, { 0.6f }, + { -1.52806e-39f, -0.2, -0.3, -0.3, -0.2, -0.1 }, { 1.52806e-39f, 0.2, 0.3, 0.3, 0.2, 0.1 } + }, + false, + "Convolution", + "U8" + }, + { + { 256ul, ngraph::Shape { 1 }, { 0.f }, { 255.f }, { -18.7f }, { 18.8f } }, + true, + { + 255ul, ngraph::Shape { 6, 1, 1, 1 }, { -0.6f }, { 0.6f }, + { -1.52806e-39f, -1.52806e-39f, -1.52806e-39f, -1.52806e-39f, -1.52806e-39f, -1.52806e-39f }, + { 1.52806e-39f, 1.52806e-39f, 1.52806e-39f, 1.52806e-39f, 1.52806e-39f, 1.52806e-39f } + }, + false, + "Convolution", + "U8" + }, }; INSTANTIATE_TEST_SUITE_P(smoke_LPT, ConvolutionTransformation, diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp index 5d07fdf8d3473a..f3d90f0ea72f6b 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/low_precision_transformations/fake_quantize_transformation.cpp @@ -48,11 +48,11 @@ const std::vector fakeQuantizeOnDataValues = { }, { { 16ul, {}, { 0.f }, { 1.5f }, { 0.f }, { 1.5f } }, - "Pooling", "FP32" + "Pooling", "U8" }, { { 16ul, {}, { -8.f }, { 7.f }, { -0.8f }, { 0.7f } }, - "Pooling", "FP32" + "Pooling", "I8" }, // nGraph: I8->FP32 Convert is not supported // { 256ul, {}, { -1.28f} , { 1.27f }, { -1.28f} , { 1.27f } }, diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/eltwise.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/eltwise.cpp index df69830326207b..5c29a24c20bb0c 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/eltwise.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/eltwise.cpp @@ -11,6 +11,7 @@ using namespace ov::test::subgraph; namespace { std::vector> inShapes = { {{2}}, + {{}, {34100}}, {{2, 200}}, {{10, 200}}, {{1, 10, 100}}, diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp index f7b4784aec8d87..9fb2778a7b7deb 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp @@ -88,7 +88,7 @@ std::vector disabledTestPatterns() { R"(.*CanSetOutBlobWithDifferentPrecision/netPRC=(I4|U4).*)", R"(.*CanSetOutBlobWithDifferentPrecision/netPRC=BIN.*)", // TODO: Issue: 67486 - R"(.*(EltwiseLayerTest|SoftMaxLayerTest).*)", + R"(.*(SoftMaxLayerTest).*)", // TODO: Issue: 68712 R"(.*.MatMul.*CompareWithRefs.*IS0=\(1.5\)_IS1=\(1.5\).*transpose_a=0.*transpose_b=1.*CONSTANT.*FP16.*UNSPECIFIED.*UNSPECIFIED.*ANY.*)", // TODO: Issue 66685 diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/plugin/configuration_tests.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/plugin/configuration_tests.cpp index b593c411af29ce..5f244c685e1f52 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/plugin/configuration_tests.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/behavior/plugin/configuration_tests.cpp @@ -282,7 +282,7 @@ const std::vector>& getDefaul {InferenceEngine::MYRIAD_NUMBER_OF_SHAVES, {InferenceEngine::MYRIAD_NUMBER_OF_SHAVES_AUTO}}, {InferenceEngine::MYRIAD_THROUGHPUT_STREAMS, {InferenceEngine::MYRIAD_THROUGHPUT_STREAMS_AUTO}}, {InferenceEngine::MYRIAD_NUMBER_OF_CMX_SLICES, {InferenceEngine::MYRIAD_NUMBER_OF_CMX_SLICES_AUTO}}, - {InferenceEngine::MYRIAD_IR_WITH_SCALES_DIRECTORY, {std::string()}}, + {InferenceEngine::MYRIAD_SCALES_PATTERN, {std::string()}}, {InferenceEngine::MYRIAD_TENSOR_STRIDES, {std::map>()}}, {InferenceEngine::MYRIAD_IGNORE_UNKNOWN_LAYERS, {false}}, {InferenceEngine::MYRIAD_FORCE_PURE_TENSOR_ITERATOR, {false}}, @@ -433,7 +433,7 @@ const std::vector>{{"tensor", {4, 3, 2, 1}}}}), @@ -614,7 +614,7 @@ const std::vector& getPrivateOptions() { InferenceEngine::MYRIAD_WATCHDOG, InferenceEngine::MYRIAD_PERF_REPORT_MODE, InferenceEngine::MYRIAD_PACK_DATA_IN_CMX, - InferenceEngine::MYRIAD_IR_WITH_SCALES_DIRECTORY, + InferenceEngine::MYRIAD_SCALES_PATTERN, InferenceEngine::MYRIAD_TENSOR_STRIDES, InferenceEngine::MYRIAD_IGNORE_UNKNOWN_LAYERS, InferenceEngine::MYRIAD_FORCE_PURE_TENSOR_ITERATOR, diff --git a/inference-engine/tests/functional/plugin/shared/CMakeLists.txt b/inference-engine/tests/functional/plugin/shared/CMakeLists.txt index ef26009a2b256c..a1c7d795127784 100644 --- a/inference-engine/tests/functional/plugin/shared/CMakeLists.txt +++ b/inference-engine/tests/functional/plugin/shared/CMakeLists.txt @@ -16,6 +16,11 @@ if(ENABLE_MULTI) list(APPEND DEPENDENCIES MultiDevicePlugin) endif() +# remove once CVS-69781 is fixed +if(NGRAPH_IR_FRONTEND_ENABLE) + list(APPEND DEPENDENCIES ir_ngraph_frontend) +endif() + if (NGRAPH_ONNX_FRONTEND_ENABLE) list(APPEND DEPENDENCIES test_model_zoo) list(APPEND DEFINES TEST_MODELS="${TEST_MODEL_ZOO}/func_tests/models/") @@ -46,6 +51,7 @@ addIeTarget( lptNgraphFunctions sharedTestClasses PRIVATE + inference_engine_legacy # CVS-55376 openvino::util inference_engine_transformations DEPENDENCIES diff --git a/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp b/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp index 6fcb0efc552ba5..7c4e595b9450b9 100644 --- a/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/base/behavior_test_utils.hpp @@ -104,9 +104,11 @@ class InferRequestTests : public testing::WithParamInterface inline InferenceEngine::Core createIECoreWithTemplate() { PluginCache::get().reset(); InferenceEngine::Core ie; +#ifndef OPENVINO_STATIC_LIBRARY std::string pluginName = "templatePlugin"; pluginName += IE_BUILD_POSTFIX; - ie.RegisterPlugin(pluginName, "TEMPLATE"); + ie.RegisterPlugin(pluginName, CommonTestUtils::DEVICE_TEMPLATE); +#endif // !OPENVINO_STATIC_LIBRARY return ie; } diff --git a/inference-engine/tests/functional/plugin/shared/include/base/ov_behavior_test_utils.hpp b/inference-engine/tests/functional/plugin/shared/include/base/ov_behavior_test_utils.hpp index 8cce834dc2b676..e5d693e13d52ed 100644 --- a/inference-engine/tests/functional/plugin/shared/include/base/ov_behavior_test_utils.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/base/ov_behavior_test_utils.hpp @@ -69,9 +69,11 @@ class OVInferRequestTests : public testing::WithParamInterface # define GTEST_COUT std::cerr << "[ ] [ INFO ] " # include # include - - #endif namespace ov { @@ -114,6 +112,9 @@ TEST_P(OVClassBasicTestP, registerExistingPluginThrows) { ASSERT_THROW(ie.register_plugin(pluginName, deviceName), ov::Exception); } +// TODO: CVS-68982 +#ifndef OPENVINO_STATIC_LIBRARY + TEST_P(OVClassBasicTestP, registerNewPluginNoThrows) { ov::runtime::Core ie = createCoreWithTemplate(); ASSERT_NO_THROW(ie.register_plugin(pluginName, "NEW_DEVICE_NAME")); @@ -150,7 +151,7 @@ TEST(OVClassBasicTest, smoke_createMockEngineConfigThrows) { #endif -#ifdef OPENVINO_OPENVINO_ENABLE_UNICODE_PATH_SUPPORT +#ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT TEST_P(OVClassBasicTestP, smoke_registerPluginsXMLUnicodePath) { std::string pluginXML{"mock_engine_valid.xml"}; @@ -196,7 +197,8 @@ TEST_P(OVClassBasicTestP, smoke_registerPluginsXMLUnicodePath) { CommonTestUtils::removeFile(pluginXML); } -#endif // OPENVINO_OPENVINO_ENABLE_UNICODE_PATH_SUPPORT +#endif // OPENVINO_ENABLE_UNICODE_PATH_SUPPORT +#endif // !OPENVINO_STATIC_LIBRARY // // GetVersions() diff --git a/inference-engine/tests/functional/plugin/shared/include/behavior/plugin/core_integration.hpp b/inference-engine/tests/functional/plugin/shared/include/behavior/plugin/core_integration.hpp index e95d4572dbc4aa..7213021011c6a5 100644 --- a/inference-engine/tests/functional/plugin/shared/include/behavior/plugin/core_integration.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/behavior/plugin/core_integration.hpp @@ -106,6 +106,9 @@ TEST(IEClassBasicTest, smoke_createDefault) { ASSERT_NO_THROW(InferenceEngine::Core ie); } +// TODO: CVS-68982 +#ifndef OPENVINO_STATIC_LIBRARY + TEST_P(IEClassBasicTestP, registerExistingPluginThrows) { InferenceEngine::Core ie = BehaviorTestsUtils::createIECoreWithTemplate(); ASSERT_THROW(ie.RegisterPlugin(pluginName, deviceName), InferenceEngine::Exception); @@ -193,6 +196,7 @@ TEST_P(IEClassBasicTestP, smoke_registerPluginsXMLUnicodePath) { } #endif // OPENVINO_ENABLE_UNICODE_PATH_SUPPORT +#endif // !OPENVINO_STATIC_LIBRARY // // GetVersions() diff --git a/inference-engine/tests/functional/plugin/shared/include/onnx/quantized_models_tests.hpp b/inference-engine/tests/functional/plugin/shared/include/onnx/quantized_models_tests.hpp index c0ddbde30a9880..33631d1a28d96c 100644 --- a/inference-engine/tests/functional/plugin/shared/include/onnx/quantized_models_tests.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/onnx/quantized_models_tests.hpp @@ -16,7 +16,8 @@ class QuantizedModelsTests : public testing::WithParamInterface, protected: void SetUp() override; - void runModel(const char* model, const std::unordered_map& expected_layer_types); + using LayerInputTypes = std::unordered_map>; + void runModel(const char* model, const LayerInputTypes& expected_layer_input_types, float thr); }; } // namespace ONNXTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/experimental_detectron_roifeatureextractor.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/experimental_detectron_roifeatureextractor.hpp new file mode 100644 index 00000000000000..4a51c18d9585f2 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/experimental_detectron_roifeatureextractor.hpp @@ -0,0 +1,19 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +namespace ov { +namespace test { +namespace subgraph { + +TEST_P(ExperimentalDetectronROIFeatureExtractorLayerTest, ExperimentalDetectronROIFeatureExtractorTests) { + run(); +} + +} // namespace subgraph +} // namespace test +} // namespace ov diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp index 4ef0b9c7dc18ff..5865e3f0c68758 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp @@ -12,4 +12,8 @@ TEST_P(GatherNDLayerTest, CompareWithRefs) { Run(); } +TEST_P(GatherND8LayerTest, CompareWithRefs) { + Run(); +} + } // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/slice.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/slice.hpp new file mode 100644 index 00000000000000..cf432f4ada6498 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/slice.hpp @@ -0,0 +1,13 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "shared_test_classes/single_layer/slice.hpp" + +namespace LayerTestsDefinitions { +TEST_P(SliceLayerTest, CompareWithRefs) { + Run(); +} +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/basic_lstm.hpp b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/basic_lstm.hpp index 7ae1d21a886e4f..a31e73f37b6942 100644 --- a/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/basic_lstm.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/basic_lstm.hpp @@ -42,8 +42,7 @@ TEST_P(Basic_LSTM_S, CompareWithRefImpl_LowLatencyTransformation) { manager.register_pass(); // LowLatency enables UnrollTI manager.run_passes(function); LoadNetwork(); - IE_SUPPRESS_DEPRECATED_START - auto states = executableNetwork.QueryState(); + auto states = inferRequest.QueryState(); for (auto& state : states) { auto name = state.GetName(); if (name.find("cell_state_1") != std::string::npos) { @@ -58,7 +57,6 @@ TEST_P(Basic_LSTM_S, CompareWithRefImpl_LowLatencyTransformation) { GTEST_FAIL() << "unknown memory state"; } } - IE_SUPPRESS_DEPRECATED_END // Run and compare Infer(); const auto& actualOutputs = GetOutputs(); diff --git a/inference-engine/tests/functional/plugin/shared/models/convolution_fq.prototxt b/inference-engine/tests/functional/plugin/shared/models/convolution_fq.prototxt new file mode 100644 index 00000000000000..37b8297c6020a3 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/models/convolution_fq.prototxt @@ -0,0 +1,199 @@ +ir_version: 6 +producer_name: "ngraph" +graph { + node { + output: "895" + name: "Constant_21" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 + data_type: 1 + raw_data: "\000\000\000\000" + } + type: TENSOR + } + } + node { + output: "896" + name: "Constant_22" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 + data_type: 1 + raw_data: "@M\371?" + } + type: TENSOR + } + } + node { + input: "894" + input: "895" + input: "896" + input: "895" + input: "896" + output: "897" + name: "FakeQuantize_23" + op_type: "FakeQuantize" + attribute { + name: "levels" + i: 256 + type: INT + } + domain: "org.openvinotoolkit" + } + node { + output: "898" + name: "Constant_24" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 64 + dims: 64 + dims: 3 + dims: 3 + data_type: 1 + raw_data: "\017\304/\251\354=1\251\353r\325\250M\202\016\250ry@\250&\006\234\'\004\260\212&\261k\207\247\000?\226\'\251w\204\250\020\336C\250`b(\250\n\3272\250p\345\325\247\230 \331\247\0037\215\247\2043[\247f\253\006\247\017\232\253\250\032\346+\250^\n\253\'\\\354\252\250\031#u\2504\267\370&\263l{\250,\326\t\250\232F\225\246=_\364\247\207\232\207\250\273p\000\250r.3\247\204\261\362\247-A\007\'\023\212O\247{\004S\247g\363\257\247am\246\247\2018F\'\305E\300\247\257\220H\'\2671\004(\226/\243&\322\377^\250F.,\250\303.2\250\0170\002(,\335\'(\250\364\005(4\301e(\215+\203(\232\331>(\201E\345\'\246\036\267\'\'l\003(V\"\035\250\201\252\005\250q\301h\250\343\243\221&\003R\325\'O|\022\246\215\311\232\'\363\022\t\'\277\351\202&\305\206\000\000h\017\000\2001\227\000\000\tX\000\000\"\247\000\000\331\322\000\200Yq\000\000\336\247\000\000\203S\000\000\020\363\317\246\375\313\225%\023\036\n\'\330V!\247U\310\r\246E\203\200\245\326m\213&\273\371\265\'\320\227L(\313\337\037\'\246\017\274\'\334\370@\'\371[\214\'Pv\253\'V!d\'\256\260v\247\213\261\227\246b\334\027\247_\n\216\250M\300E\250\204\314\t\250S\267\302\247\021\013M\247\360\362P\247\034\314\266\247|y\312\247\316\215\353\247\242u\036(\36061\'M\302\245&\002\r\346\'\357\236\273\'\2128\200(\365U\024(N<\226(Ws\341(\034\215y(\337\030A(\302\312\032(\246\253\202(M\254R(v*\221(\361\271D(\236\263P(\237R\207(\306*\303\250]1\242\250\365\352\334\250\320\306\253\250\3776b\247\340\271C\250Y$\223\250\323\007\037\250\356\025\276\247S\327K\250\221\232\357&A\3171(d\031\252\243\005z\360\'\005\236\237(\233-\330\247o%_\247\371,\345\'S0\264\247\215#\231\250\272\334\260\250\025BN\247\263\313\034\250\2004\367\246\341\361\246\247\261\2650\250\244q:\247W\311\270\247\355Ga\250{\007\027\250O$\311&\007<\002\247!d\224\247>\267\214$\314\205\225\246\022\262\031\247#m\322\245\362\274.\245\341c\330&\007\000E\247q!\032\'\337,\022(\315^`&\316\035\037(\211\t\206(N\261\347\'\3149\214\'?V\310\')\353A(\266\317\'(T\265\010(\315\016\024(\213A\373\'\230\367\361&\217\2170\250\242|\005\250[7g\247\247\025_\250\344\343\362\247\247\201\200\247\177\220\274\247\316*\342\247\361\210\240\245@d\270\247\307iW\247\207xG\246(\024\234\'4&\310&\354\350\021(\221\242\274#K\312d&U\231\\\'6\275\245\2502\020\200\250\362\344\250\247N\256O\250\021\227\372\247\372\313\353\247\004\317/\247F\211\"\245\250\005\001\247u\264;\250\371Z\231\247EW\225\246\315GP\247\203\347\247\247Y\366\023&u\313\344\247v\010\371\247R\231p\247V\246\000\000h\310\000\000\233T\000\000\205\215\000\200\014P\000\200\2237\000\000(9\000\200`\307\000\200g4\000\000j\017\233\' \233M(\340\235K(\240\335O({\n\237(\224\007\236(\304\344\333\'\367\031;(C\257\027(0\374\232\250\251\346\216\250\234\244]\250_\343\002\250\270\024\301\247\0328\213\250\024\231R\250\343\200\013\250\226`\003\250\001\014\344\'\276V-\'\204}L\'o\210\227&\020\377C\247-\250\'\200\317\247]\242/\247\323\024\256\'\217!\004(\334\014\035\'\27605(\263%+(\375_\374\246\303Q\301\'\341!\350\'\361dw\250?\253\030\250R\"*\247W\r\352&\236\271\362\'\262\027\005(\030K\214\246\301f\276\'i\214\252\'\235\275y\246\372D\000\247N\035\241\247\212\371\026\246:\213l\'\266\320\344\'\324j*\250@\222K\250_o\036\250b\2550(\030\232\"(IV\304\247\035\341\305\'>\003\314\'\031JW\247Y\261\207\247x-\371\246\313\252.$\320J\037\250\r\321\275\247\234k#\250B\333\227\247Rj5\247FD\217\247Q\3258\250]\305\010\250A\212\245\247\344\305V$;\202\207\247\354\236\234%\220\201K(\020?\t(\253!\237\'I\265\021(x?r\'\0274H\247klq\247\220\347\264\245\274\014\207\246\022\273\030(\370!m(U\321\354\'\361\273 \'\241u\317\'7\215\010\247(\264\236\307\'7\330\367\'\274\230&(U\253\\\'p-\362&,\326M&)\250Y\247\202\301l\'\200\255\310\'[F\211\'\243\220\254\247\370\230\217\247\205\253\205\247\355\323\000\200B\313\000\200%\233\000\200:\215\000\200!\321\000\200B\322\000\000\321l\000\200-\236\000\200Pl\000\200wg\332\247\360\304\017\250\030\tW\247\3534\313&4\301\234&\371<#\'U\216\243\247\213\0325\250Al\r\250\326r\000\000hN\000\200n!\000\200?\311\000\000\2242\000\200\013\243\000\000\242\214\000\200+1\000\200\270\n\000\000\273\016\343\247Y\211\002\250\204\"\245\247\312\213\000\250 \212\202\247}\344\303\'\024\361P&\313\312\001(\213\031\233(_\215P&f\031n%`@\252\247fv}\'\353\313M\'K\2729\246\014\211\207\')\237k\'g\226\001(\242\214\244\'W\243\262\'L\005\020(\207(\025(v\036\026(I\202l(\037\tA(|\254A(\351n^(\016@\225\'e5\250\'8\347\372\246\241\262)(\227\376P(T\373w\'\276\274\317\'\373\007\304\'\360\0260%\356\252\315\247\313\260w\'B\\\026\250\360\346\323\'\261\355\177(\347\274V\'AA\242\250\352)$\250\266\031D\250|\233\302\274\343\030\330:\343Q\325\254\274\'b\000\000w\253\000\200\017\250\000\00065\000\000{\247\000\000G\220\000\000\'&\000\200&-\000\200=\275\000\000|\230\017&\274L\2216\274n\234u;\201\307\001\275\337X\n<\006K\301\273\215>\320\274\234\225\263;\202u\311\273DVW\271F\277\265^P\274\206\r\305\274\334\303\254\274\367Vs\274\332L\310:\017\277\340\273\206],\274-\303\025\273\323\010\327\271\251\376\321\273\323\275\247\271\0322\320<\010,\252;\210\303?\273D\"\244\273\376\010\t\274\343\021\000\274{\305\022\274\007#\210\274\20160;@\310\n\275\316:u\274+$\217\274\332\353\t\275\375+\310\274s\024\314;\231\007\256;\330\2703r\014\274Y\274\002\275\357~\235\274\227\n0\274}9\275\275\t\022-\274Z\237\027;\336\311\310\274io\277\274\342wL\026-\274`\373\016\275%~\260\274Z\023!\275\206\307\357\274\200N\005\275{\222^\274\373M\343;p\346\253\274o\215\233\274\371\251\237\274\207q\016\274\221r\232\274\273fR\274\305B\023\275\362\311\272\274/\255\262\274\362\250><\213\270[\273\0321\026\274e\342\342<\004\211\361;M\007R\273\222\241\212<\302\221\326;S\254\304\273|wX\274\356k\212;\36334<\347\\%<\354M\t<\234\372\223<\364\206\234<\344\367\342<\222\212W;\0311\230;\321\3128\2733\370\033\273\271*y;\344Ir\274\324\360\322\273\242DA\274\021\274\022<\005\244T<:Q\341\274\240\202(:\271\032\326:\333_\236\274\316^\263<\257\216u\274\227\347H\274o_=\274\334\347m\275\376r2<\020G\244<\323\027\335;:\254\242\272\326\210\333<+\2275:,\332\267\273\337g%<\350\'\3509\244[\207<\322\370?<\307\250\006\271\350\3743<`\300\201\273\010r\371\272,6\311:\270P\225\270X\247!;98\032\274\026\030\222\273\322+\177\274\366\225\017\274\022\315\253<\035(\325\274I(P\274\214|K;\026`\005\273,\305\264;\031RB\274\263\342\333\273n\322\372;\310D\\;\273\335n;\251\303w\273k\316\227\272\357\266\252\273\342\312\254\273\005HS\274\024u\277\274I\326U\274++%\275\222\257\200\274\\8\206\274\375\310\245\273\232n\031\274\275\231\354;\247\235l<\177ep<\301d\206\273\037S\217\273\272\221n<\263G\303\273\320!\023\274\310\027\323;%\342\355;\300\30426\226\217\026\274@^\020:m\205\276\274\036\212\317\274}W$\274D\230|<=\336U<\215\275/<\0220\321;\276*^<\323\346I<7\257\r\273)&\346;l\224\013<\242\213\241;\010\373\277:\223\264-\274\271\2603:a/\332<\335v\215<\274\230\273<\376\340\360<\274\244\310<\353y\255<:\365[\273\232%W\273Y\247!\2745aZ\274\010\032\236\273\310\361\201;\340\247\302\272\321YF\273\037\272\263;\245\230\036\273i\3507S;=\014Yq=z\346\022= \247\332;gzX\272K\311\355;\226\240\320;\025;\311;\030\321\254\274\355\364\202;\360\355\007\273\210\235\300<\275X\363Y)\261\274\260~\255\274\247\r\246<\326\361\257\274\313[:=\252\014]\272\310&\372;\371\027\276:&\256J\276\231\237\006\275\377\377+=\317\007\221\273!{}=ZC\261\274\331Rf\274\343F9\274\tZ4;@_\023\275\237\310~<\211\031\217\273\233\377\226\245\2729\021\031\274\027\020M<\177\307\233\274\223\200\027\274\210\345\250;\'\302\272;\037\326\311\273\212\364\261\274+5\216\274C\216\346;2nT;;\254\371:\221d\205\273\372\2735\274h8\006=\366]\'<\265qq\274gB\234\272;#\312;\357\332\227\273\036(H\274\276\260\213\273g\373y;\234H\326;\"\246+<\241\365\347\273\3044\225\273`r\002:\033\005\217=\346p$=<\222\244=f\230\223<\004L,=Y\321\037;\244Q\021\274H\347\217\274\n\371\361\273+\277_<\200\220\251<\005\271\007<\227>\344;`\230\215<\225U\265<.\202\250\273p\202\261;\001\255\373\273\351\301C\273\000E\233\274,4y\274bn)\274x\327\375;`\250\260\274\372%\266;\251:\336\273\364\264\022<\236n\320:n\247R\275\r-t:q\010j\274\024\262\200;;\374\251<\275\246\307\274\032I\231<\361V:<(\375\211=\354{\300=v9h=O\337\t<\202\223|=js/\275\330\351\252<\301\272\352<\273<\237<4k\272;H=\331\273,\277.<\270Y\360<\260\270\330<\325\245\002=\365\310n<\356\346\350;9{\271\273\3023Z<\321\307\234\274\342\236\376:\243q3<\311\246W<\010!)<*U\244\274\036z\331<\205\304\262a\261<\203RL<\221j\246\271\236W\241<\243\313\260\2723\233\200<\004\322\312;\200\211\222<\375i\211<\024P/=&j\034=\026\364\235<\266w\321^\000\200\023|\000\000\330\271\000\000\232{\000\000\257\314\000\200\013\317\000\000\212\236\000\000%|$==\344i\274\274\024\013<\030&\037\273(I\201=\r\025\367\274b\220\352\273\337\332p\273\206\322\021=N%\000\2008\310\000\000\304\315\000\000W\'\000\200\252X\000\200*\304\000\000\237x\000\200\014\261\000\200\232\310\000\000\272\317\350;\302\350\273\274S^w\274\023\004\273\274!xY\275\377\325\256\274\306\336s\2742\'.\275\267\377e\274\316\016\203\273Q<\2709G.n\274}\214\207\274\216\033\033>\2170b\274\020\360Z\274P\247\256\272A\005\222\273k\341+\274\344=\251\2733P\314\273\364\221\224:\307\357\021<\262H%\273\323r\030\2741L\031;)\266*<\322\216\326\272\323\214y<\016\332%P/9=\252\340z<\214c\370<\310xM=~\365s9\341@\202<\270\267y\274\351\277\233<\355\322\253<\271(\207<\200\254\222\274\023\030\306\273\265m\013\275\360\2764<\362q5=2h\325<\273\017\026<\203\'\351;\222\007\232=\316(\331;\n\233q=\217<_=\256\225\377\317\313<\311pB=0\221U=\244\242\"=\r\204x=\241\370\242=\327u\366<)^%=\233\350C=Ym\000\200\260B\000\000\036\220\000\200od\000\000\310\254\000\200\313\321\000\200\247\321\000\200r\213\000\200\330\317\000\200\317\0001\274\211V\213<\266\265]<\025\3745 \314;\245\025\227\274S\346N<\357\267\"\273\251\024\026\274\206\357\212<\360c\335\273d\2101:3\237\010\274\200\267\254\274<\335\r\275^\346\021\234\274\323\301!\275O\037\234\274\270\006\372<\302F\256\273\377]C\273Z\274\000\000\373\203\000\000\322\255\000\000\347$\000\200\250\312\000\200?o\000\200\216j\000\000\226\313\000\200\0045\000\000 \355\240\274\314c\201\274\241\212\342\273\342j\000\275\3351\342;\330\302\315\274\252B\315\273\031H\344; \355n\274 \022w\275\313v+\275\013\004M\274\017\215j\275\275\357\256\275\363\234\264\275\356\233\243\274Ud\245\275\271\213\303\274M\024\333<\322\245#=Ma\275<\n\177\240:\037Ze\273\241#r<\325\230\324<\326\027\243<\374V\235<{\'\000\200\026\211\000\000\2453\000\000\224\231\000\200A\232\000\200\350y\000\200n5\000\000\200\252\000\000v\031\000\000\030k\227\274\004\327\243\274G\371\365;8\355\n\274\001\203\027<\253Jh<\227\356\034\273=\r\251;\301\231S<3W\263<\270\326Q=\265h\006=\007s\375<\354\273\000=\243@\204=\022\253\013=^\324\246=\270\370P=r\247\363;\016\310\304\273-\220\206\274\366\337\316\274G\222\033=\266q\027\275\335F\030\274\317\025$\274\225\260\216\274Zj\336F\264=\267\357\226=+\332~\274&ai=\255\360\247<\030\326Z;\337F\340\273\330S\257<\016A%\274\001\'#\274\332\330\235;CL\264:+\217\242<\3751\342<\330\274\213\006\004<\3150\276\274\347\260\316\2743\344\225<.\202J\273\254(\000\200\373\250\000\000\'\215\000\000X\230\000\000\331\235\000\000\202\213\000\000\223\247\000\200\2143\000\200\340F\000\2006\232\315\273\023\033\245:\301\340\364\273\372qR\274hP\036<\"E\362\273\274\215\327<\303;\304<\323\233w;\231\356\334\273]\276\371;\332\2332<\247N\312;yYO<\036\355U=\254\254\006<=x\020=\340^]=7\346F<\323<\317\274fe\254\274\252u\210\274\232\217\307\273\267\267\242;\236\366\311\273xj\205\273\340M\254\2741\\\250\274\000\005\004\274\260#\316\274\321\364\254\274q%\201<\035\357\362\274Z\263Q;\360>\177\273^\370\020\275\240\352\360\274yt\375\273\003\235\325;6V\004<\\\275\007\275A\234\335;\007\245J<\263\320\224<\320Y[<^\356\024;`\t\313\274\223\213\274\273 x,\273G44;\254s\177\274\375W\001\274\373bg\2746\302\277;k\205\016\273\2760\2718_Z\016\272\210\301\302<\366\346\264\274\322\255\240=\203\036\271\274\234}\321\273M\024\306<\234\033\230<\333!\021\273\247s\240\273\373!\345;\r\360\364;\2719\255<]\237\340\273\210\366Z;\254c09\367\306&<\222\272\356\272G\nq\274\025\277\026\274\354b\217\274\207\003N\275=\202\255<\213\210\315<\316\023\271\274\345\236><_}\000\200\022c\000\200r\257\000\000\311}\000\000\236\013\000\000F\255\000\200c\273\000\200\202f\000\000\025}\000\200\325\262*\274,\343\331;Y\203\321<\324|\353\274\204I\206\274\237\226\004=uJ\r\274P;n\273/\272\370;\313C#\273IeH<\026\347/<\374\263\'\3279\237C\323\272]\214\367\274\251\303\033<\2308*<\031\000_\2753\231\272\273\000p\324<\256b/\274\330\247m<\'\343\321<37\326\273\244!\273\2743\345.;|\316\245\274p~\010=\177\360\257\274\242J \273\343\004\007\2722]\355:\372\277\2779\347R\234\274\241\214p\272\22282\274\376\211p\274\005\236\025\275\225\301(<\263H\353<\247*F\273\n\343\354;\354\270\321<\336]\230;\025\244\375\274\351\035\344:` \003\275\312%\247\272\003\t\242\2727K\014\274\270\231\021:\264\352\004\273\370\255K\275qO\375\273\212\356F;Q\275B<3k?;\261\267\177;\t\325\261:=\365\370\273,t\240;nU\004<\'\0045<\255\006\035<\007\265\034=\236\245p;\031&\270;\226\352h;\214\2413\273\375\224\251;.\352\236<.\027\030<\273y\201\327:\370\234\255\272\202\333B<`\361\305\2731\331\037\275\372\223\205;\254\037\243<_]E<\342\370\262\273yMu;J\221p\271|\3340;\3114U\272\023\363\302\273\3600J\273\010-\210p<\3557\036<\255\327\243\303;p\013\r\273\000\006\201;-\027p=+\375\264<\362\252y\273\247\360\267\273!\351j\274\372<\3358I\202e\274\026\230`\272lP+9m\347=\275\373z#\274H\242\225<\023S\223\273t\034\220\274/\314\000\000\275\303\000\000!a\000\000A#\000\200\275\255\000\000\224\217\000\000Wu\000\200\211(\000\200(\311\000\000\006\313\177<\212\333\033=\335\260\363<\315Xm\274h\356\004=\347C\005:\350\261\275S\273\n\307DY=\325=\244y\214=\336n\374<8r\037>\221\200\236=\257\205%>\255\256\340=\004\2470;c\364PS\030\271%\207*;m\026\264\273\303~\317:\321\"\207\274G\224r;9\333\241\274\314\254]\274u\342T\274\242\231\004\273ke\260\274nB\241\273\277v\021\273\262\347\246;$\211#\274\374\317\354;>\305H<\376/\220;\223\377\206;O\363\227\273\030\035~<\327r\240;\344\210\343\273b\223u;s9\240;_\335\221<\036\036i\274\237\233\324;\357}\231\273\n\362\014\362\314\273_G\302\274\230z\207\274\364\227b\271\201\257\036<\220\237H\274\227\272\307;\177\014\204\221\026\327\274V\210\274\274\206\343\007\275r\254\367\274\r5\226\272\207&!=\017\251\002\275Z9E\275\347\300\"\274\311\010\232\274.\'\003\275*)\026\275PD\025\275O0\200\274\225b\243<3\372\343\274*\323\364\274!\3275\275\372\312\357\274=\325\306<\025\362+=]\312\277\274\360\205\255<0\022+\275\"s\246<*hb\273\301\001g\274\240\232w<$K\355<\212\335\004=\335\257\215<\214\017\252;F\036\036\274M\330\254;\204\223\266\274\327H\265\274\225~\013\274\242\211\311\274R\273\204\274\215\341q<\031\302O\274\240\306\251<\344\325\316;\247\372\374<\346\342G\274,n\264<\222V\345<\270\201\306\271\306G\364: \312R\274\275\023S\275\344O\276<\215y\310=aE<\272&\322\000\000\234\256\000\200\244{\000\200\240\037\000\000\362\312\000\000CY\000\200\307\004\000\000\277\234\000\200s*\000\200\030\352=<\'\256\236\274\373:\231\272\237I\002=\214\323\223\245\351\020\275T~\033\275\r\321 =\266\225\216\274\342\373\031<=u\304;\333\2221\273W\031\365\311\025\275/\254\024\274[\301\003\274\254\200C\275R\351\214\274edB=\222\270\342\274\020\253\260<\234\240@\275ef^=\005\256\221=p-\010\274I\003\t=dH{\275;\246T\274*\302f\274\234y\001;>]\242<\340\267T=\316\236i=I\336\207\274J~\005\275\002N\230\274\265&\000\000\300\325\000\200\210\243\000\200\263\216\000\200\304i\000\200-\325\000\000B \000\000\205\272\000\200gR\000\200K#m=\270\315\271<\247V\001;\325[\223\274\252\331]\275&\363\272\274D\341^\274\002\206S<\304\234y\274\2415J\274\221R)\272^u\331<\3100P<\013<\323\273~g\001=\001\006*\001\274\255\356\206<\276\215\221\274\312\244.\275\352\255G\235\303\275 \262T\274\237(\243\274\203\002\211=\023\330\312<~\210\245\274\001\304\033\272\240\r\255<\265\316\271\273\321 .=\371\344\026\275P\324`\274\305q\210\270\022C\274VR\363\272Q(\201\274\223\376\000\275\345\005\206\274jJ\323<\274\243\220\274\220\264\211<9\032f<1\247\010<\322\3628\274\3149\367;\271B\260\272$\034\335\2730\177\265=j\\\244<\030\325\261;\367\333\330;\330\322\340;\004\254\232;\214`\210<\207z\037<\263\005\352;\t+\376:|\335\207\273\227\377.\272h\245,;\312\002\023\274\217`%\273yG_:zc\027\273C(\377:w\362d\273\247\304\314;]\226\021;U\204\321\272\273$\0272\243\270\253\222\215;\216\220N;\016\031\036<\270zZ;\350\331\350;\0326\312\272\2518\225\274#\0301<\355X[\274\272\227\221\274[\320\215<\255\205\217\274\030\262#\2743\333\026<\t\000\203\274\277\031\034;K\376\333;\344\361n\272\0175=\274\322\303\241\033\273\260\'\362\273\211>>;\274\031\307:\037Mg\273o\254\233<\320\240\345;l\327\003<\271\177\004<\342v\002\274\220!\2249\376:\247;\343\242\302;f\210\355\273yP\337\273\377\313i\273\224:\224\273\211\307\037\272\274\377:\273O\013\002<\201\254W;G\216\306:u\2143=Ew\252=\351\020P=O\351\205;\322\351^;f>\330\272\246\".<\255\014\236\272\242\251?9\263Of<\305~\202;6\213(<\376\0222<\3169\264;d%.<\375_\010=\020\203\365<\021{\331<\367J\226<<\032\013D\273\333_\241\271\034>\263;\222\357`<\305z\000\200\233)\000\0008\312\000\000\240\202\000\000\374\321\000\200\255\324\000\200(\\\000\200\316\306\000\200}h\000\000v\321\347\271K\240D\274J\326\255\273D{\032:io$\275@\224?\274\017V[\272T=\033\274\372\004\213\273\325\333]<\226\035?\036:\237\205\335\270E\254\340:\013y\2769;\363\316;\254\267\316<\321\230D\261;\240\032\262:{DT\274\004>\004\271\274\035\025\273\374\212\203\273\201\355\303:0\307:;\n\337L<\340\002\002;\272\214\261:\224\256\021<\316\204$<\0161p<\257\036\t<\211-P<2xP<\312\325\013<\266\037Y\273UNU;\367?\315\274\005\003\344\273\210\364n\274\212/B\274\223D\331\273l\214j\274\273\323:\2749\026\221\274u\375M\274\252tK\275\024X\214\274\rS4\274\361\020\275\273\025 0\274\331\034]\272C&\213\274\316\024\276\273\204kT\274\320\316\226\273?7\020\275\2677\216\271\253\250\016\275\345!\355\274s\205\337\273@\003\255\273\215\273,<6\313\016\274\307S\3579E7b;Z\202z\274tk\245\273\277\247\366:\366\304\217:\274\314\227\274\220\307\247:\240\271\261\273B\0063\275\365\207H\274H|~\274\333\202\366\272\014k6\273k\371\242\272\206\017\177:\340\360\350;\037\022\310<\253f\232<+\341\026;9\211\274<\032V\030<\177\366\231;B\357\010<\306c\346;\265\234\207\272D\302\367\272\021\207x\274\354$\243\273\323\026b\274\372\301\\\274\023v\224\273\3572\336:\241]\'9\301\253\304:\307MO<,\242\235;q\325\337;\373\024\027;\276\211x;d\264\255;}T\227\327;\253\311\260;\227\351,<\007\223v<\006\'B<\330\271\307;\277g\200<\0246n<\226^g\272rw\246\272E\246\254;Wf\201\274\223\262k\274I\271f\272\r|\215\274\023\375{\273uNM9\024\273\232>\266\273f\233u\272$\3577\274t\2366\274l\310;9!\207\253;\332&%\274\243\373\230\273a\261\340\273uA\357\273\275l\':\271?R:\"\2025;\322\315\272\272\3612v\274\305\342\350\273\215\310\276\272n\325\224\273b\301\344\273\205\221\267;\202\333o\206<\276F\231\274\314I;;\263\345t\000\000\032\326\000\000\0079:\2746\260\242\274\333M\003;v\265\223\274\347\336\246;pDp<\210\260>\272\002\3579\274\242\233n<\330\245g\274u\355i\273*\027-\271\013\036\226\274\246\330$\2755\030\226\274u\r.\274\242\314\207\274z\216\204\273\332Q\360\273\016$\344\273\375\027\221\272#\']\274+\272[\274@Y\277;\344\003\261\273Y\001T\272\261\332\000<6w];\205\266\004\306=*\273(J\224<\225>\315\274\314\305\234<\320\317\224kU\274\366\341\266<\303\347\227=3JE=\204\014\261\274W\271\214\274\236\371\221;8\255\214\275\220\270\242=\355\035\016\275\213)\202\274\362,.\275\rp\007\275_D\023=mC\346=zN\250=\335Z\'>?q\351\276Ye\023>\274q\250=\303\220\002>\367n\336=AH\273\274\370\204\030<\226\337\336\274\001#\322\274\"h\216=\221\225\230\274\350lq\274\335\365*\274T;\201\274\001\376\331\356\315\265=\002\035\307\273\236R-\274\241\201\325;\210\325\233\274A\025\310=\013\306\014<\320\005\005\275\201r\205\274\0176\215\274!\341\236\273y\303\010\275\375\374\206\274o]\035\2758Jh=\r\027\036\274\220\3155\274\303\034\220\273;\2262<\351\340/\211o\000\273\307\030\007\275\266\347(\274\0046\021eI\351\2741C:\274\262U\022\275\233\033\345\274[\303\000\000\214\215\000\200G4\000\200#\217\000\000U\303\000\000@\247\000\200\275\304\000\000\357\255\000\200\367\211\000\200Q^\355;5R\022\275B4\r\275{7\237\274m\215\312=\027\270\340\2742>\352\273MLZ\275\200\326\342\274$?\000\000\365\303\000\000\222\252\000\000\006\276\000\200$\005\000\000\211z\000\200\353d\000\000J\316\000\200\342\'\000\000\rJ\304=j\224*>\376\016\220=\333g\032>n\346\357\276\264BJ>C\032G=p\343M>Ps\031>D m\021<\022\201\320\004\374\275\223\375\274[e\367\273_\375C\274\221\367 \274n&Y<#\300D=\273\026\371;t\363D<\037\245\177\276\016\312\211<\373+\222\272\027K\324\342\325{\275\333U\007\274\"_\027\2759F_\274O/\217\271!\341P\274\212\204\253\274\344[\261;a\233\263<\206\030\335<\227\226U\272\226\312\365;\355C\267;\216%\326<\013\240#\274T\356\'\274(\245\024\274\3516f\274o~\264\274\270\343\222\274\247\365\001\2740\3047<\217A\014\273=\022b<,\022\263\272O\213\260\273\213x\336=X)\003=\254\355\263;lX\227<\217\2167\273\212\232\257\274\355\"\231\274\026\302L\272R\246\365;=\222\266\275\240\301\244\274\037\207\266\273\254\2700\274\0170\271\274C\360\263;O\003I\274|`W\2731\327\232\274$\203vG(\031;#e\004\275\324uf\273\246\234i\272\3468\000\200v6\000\200\340\315\000\000\366/\000\000\337\312\000\000\014\202\000\200\200\266\000\200t4\000\200\027\267\000\200\303\265-;\224\007\365:\243>\365\273=%\317<\367f\034=A\210\270\177\273\340J\302=\"[\023\274B_/\272!\276Z=kS\344<\346\316\000\000\360}\000\000\343n\000\000\321\216\000\000\\\320\000\000\217\271\000\000\032\303\000\200\201\310\000\000\245\202\000\200\225R\340<\334pL=\030\321\324\274\202\251!=G\341\315<\\*\002=\020\324\"=x\362\235<\261\301\341<\257\253\017=@\332\037=\033\t\022=*\235\000\000vh\000\200[\305\000\000$\274\000\000\314u\000\000\316\322\000\000\374k\000\000\202%\000\200\360\214\000\000\227A\223^\'\010=\371M\214\233O$=\030C+<\361\006\021=\373CUC>\377\363\256=\232\033\014=\302\3649=X\256L=\325\213\037=a\204\267\275\245 \332\274\271[\341;eG6\274M\356c\274\304\335\001\274D{\241\332;\343R#<\234\320\350<\341\264y\273\327\354\277;^IG\274\035\244\234\274\324uk\2759)\266<\345|\004=\\\217\277\273\006Z\321<^\272\000\200\"\205\000\200\274\310\000\200\274\321\000\000\342\213\000\000\257&\000\000\317$\000\200:\245\000\0002\312\000\000^\222\223\274\201\357\253<\0214<<\231|\226\274\223\314^=\342p\\=Eo\331\274\\y\r=\363[\211<\364\321\014\275\233\201\022\273\213\320$<\354\255\277<\177GO=\030\213\3027\033\317\215\274\217\201\271\273q\271,=\317\352p\273\206\340\357;6\343\014\273\324\264\276\2743\217)\275\336\242\007<\246\026\021\205\236\246\273\337\027\014<\377\266\023<5\263\335\272\320j\002;N\224\003\273{\316\031\274B\202y\274\343{U<<\305\030<\273r\225\272\370\243`<\305\260\037\272yk+;\207z\032<\177\004)\274\260=Q\274\324\026\024<\222D\022\274*sZ\273\254*\016=\322\305\251\272\275k\306\274s{\234;\264\214\037<_|\027\2745\303\022\272\353\230\030\274V\360M\274\034\033R=\262\210\215\274\237\201\337\27417\352<#\227g\273F\226*\272\273\"\332\271\221\274d<\033\316\315\272\032$M\274\3448J<\315\001\200<\007G\224<\2071\320<\33695\275q\365\211\274\325M\302<\310Y\030\275^\335\215\274\312\264\224=\r~\273<\216\244\214=\237\245\337=\372*P\274{\003\336\274W\364\227\274\250\034q<\272\214-=\342s\330\007=\264^L\362\364;\340}4< \017\"\273>e\001<\254v\234\273\355\325[\274\3454|\273uM\333\273q\250\275\274\211-\250\274\371\3113\274:\313\016<\315\327\256<\320\0222u\274m\343,\274\342\352\037\274\211s@\274\352I\203\273\357\247\r\274\031\307\222\274\257g\036\274(F\007\274U\034\203;\243\224&\273\337\317\245\274\000\032\276<\333s`\274\264\202\354\273*-H<\332iwciV\274x\336\313\274*\327\263\274]d:\274\236\003;\273zD\036\274Z@^\272\2702\261\271n\177\305\272]\246\026\274\251\246\203;\341\2734\274\372\237\324\272\204\355r_\000\274\255\307k\274C$\247\272$\001$;3\334\r\273\014\013q;u\210\014=>\305L:\310\004\351;\310\225\002:\201\262B\273;\316\000\200$\024\000\000q\030\000\000p\320\000\200\202\320\000\200\235\305\000\000\253\203\000\000\032\262\000\000\325u\000\000\331\236\231<9\n\004<\316\013\237;\214\273\206<\232\'\307<\233.\240\271\177\344\315;\231\357!;\014\211E9N\210\000\000B-\000\200\317z\000\200\215\301\000\000\342\234\000\200\305}\000\2009\322\000\200O\312\000\200\244\007\000\000\035\007j;\366\227\220:\244 \253;\221\253\350;\'|\311\274\276A-<\373\224\335\272\371F\177;\315\033\226g=\214\017\032=\016\324\345\274\\\252L\2752\227>\275-o\344\274\230\354\211\274WF\373\274\364\374\'\275_\334\030\275a\354\240\273\021\322\300<\026\355M<\201uk<\017\010\007\274Tg\343\274\"G\204;\306Q\346\274\373\352\230\275\035\250\230\273#\276\376<\332u\3309\357S;;\003\354\305\234\010\273[[p\274\241\310i\275?}\233\274\306\354\222\274u\002\211\273\330\357L\274%Ry\274e`\245\274\355a}\275\026s`\275j2\270\273m\0163\275\303\223\324\274\217/\020<\225\246\030\275\264\367\245\272\362\000E=\026\025\216<\250\335\320<\263\206-;\226UL\2752>I:\210\'\2139\274\227G<\304\202K\274N\303\335\274g\214\210\275\252v\030\275u\311O\274\314\367\230:a.\205;\0213\272\273\032\306\001\274\331\307\213\274\227*\337\274K\334\223=:(\035\274\\\237>\274=\001>\274`\310\214\273\t\n\245\2745h\032=\317\276S=\0105\252\274r\302\220<\361\312\020=\354\034\266=\003>\344\274\364\326|=\336Dd=\374\334.;m\334-<\241\000\274<\207\2267\274\020\022;<(Q\002;\373\343\345\274\357p,=\316B\023<\351\025\000\200v\275\000\200L\006\000\000\033\177\000\000\312\315\000\000\311y\000\200,\223\000\200T6\000\000;9\000\000\'\270H\273\007\222\363\274\262\344\210\274\010#\323\274T@\324\275o7\247\275\327\177K\274\025\272\220\275\370>\037\275\036\347\010\274\032\224\256<\347\r\016;\327\236|\274}`\014<&\310\024\274;\035\033<\204\027\030=\nR\346\274\313U\322\274[\331\300;\363\333\356<\375\363\303\271\216\225\337=YE\236<\037\005G<\270G\016=\253\032I\274\003q\000\2001\317\000\200F)\000\000\317j\000\200\305\227\000\000\320\307\000\200}G\000\000\345\273\000\000\035n\000\200\360*\207<\224\037\"<|!a<#\211\270<\256m\307\273U\240\3169|\362Y\'\263\247=\010P\237<@\263\233=!bP=\014\032\220\274\307V\354\273\304\205.<\177\354\335<\023\302\277\274\'6=\2733\327\334<.\271\267;\307A\232\274\3641\313<7\314\256=\261\337N=\355\243\036=\213\362|>\003G\000>\273\3241=\223\230\373=\345H\316=\374N\214\273K\376X<\004\244\321\273\237]\224\273\337\316n\275\331\305m\274k\303\223\273\210\251\277;M\333\242;\tYC\340`\274\005\231\000\274\234(\202\274N\027\237\274\234\270\265\273\231O-<\247\351\221:\"\021\311\274\216b\270;\265\375D\275\n\245\r\275\333\024\214\275\027\333O\275R\260\263<\341\216\272=\303\265\202=+\277?=\01655>_\337\365=}Rj=\272\016\031>\\\270\257=\343L6;\014z\200<\343\3408<\031\rv<\345Bi\273-js\274\277!\224<\014t>\273n\367R\275n\255\177=\307-u\274\377a\025\275E\341#;w^\377\274\336\351\271\274\\]D\275\033\3417\273\332w\272\274\306<\024<\0269\344\273;Z\366\274\261\216\000\275{F\334\274N\343M\274Z\317\263\2734\364\241;<;>\273\353\241\334\274\311\031=\274o\013}\272%\223\243< \332\221\274\323(\275;?\337\276;\"1\034<+\215\207;\230\220\230\274\375\373\027;\217-\004<\207\303\327\273\2053\037\273y\357p<\217\356\313<\342\342\351<\024\301\245<\343\233\027=.J\265\244;\021\\|\272\273C\000\000AN\000\200%\200\000\000[\t\000\200\244\233\000\000\024q\000\200\t\310\000\200\356\304\000\200\220\305\000\000\\\231\"\274p\235\211\265\376\203=/oK;\177z\254=D*\320<@\375\376;1\352\233\273r\032\206<\326\324\372\274\274\251\251<\201t\030\275\036;m;\217!\232\2741\312\t\2741G\021=\266\001\364<\351Ox;\354q\003=\216\357\316\275\'\350#\275\340O\340;N\037\030\274\300K\001=J\216\373;\201\t0<\334\310\254\274\211!\000\274\005~\002>\016}\253=\036\265;\274\315\\\211=\300;^<\315\271\273F\213\211=\301\223);\315f\245=`z^=\2452 <@\023y<\325\222\304<\014M\265\274\r\376<\275\366\367\202\273\274\023\334\273\251\022<\274\267!E\272a\020\000\000\315\230\000\200:E\000\200*\306\000\200r\275\000\000,\215\000\000\227\217\000\000\000\273\000\2009\322\000\200\035\343k\272g\265G\274e0C;/\266\223<\346\034\021=7\212\000=8D\000=\372\361D<\330r\320<\225?p\366\274\236-\014\274\213y\031\274\271B\251;\314\254\302\272\027w\026\274\361\037\237<\344\\\013;\345\247(\274\022|\347\345}<\201\260\226\275\037\346\204\2744\303\030;\344\333k\273\306\331\025<\374\371n<\24229;\356u\034<\'\223\036\274,\247E\273\243\226m;\177@\343\274\335\020\231\274Y{\354\274\020E\333;\377~\315;\207hp<~M\004\274|(?\271rU\025<\352/\3239D\341I=W{\022;M\365\206y;\302p\217<\375\266Q<\010\265\274\273\204/\t< ,\246<\370\037M<\310:|;\016^\335;x\320D\274@\366\177;\302\032z<\r\255T=qF\310<\3467\031=\245\2249=EM@=\3333\333\225A\247<\347\324\017>\236O#=\224\255\000\000J:\000\000d\247\000\0006\212\000\000Y\274\000\200\215\324\000\000`\305\000\000]\320\000\000U\220\000\000<\377\247\274\\Sa\275\251\005\003<\342$\327\274\234\266]=\313W\230\275\362)\311<\007\307\\\275\211\000\345\274bJ@;\227\266H=Z\346==\306\240\215\273[\343\016<\213\217\277\273T\\\357:\371\336\201<\240\r1<\276\277Q\000\000\367\317\000\200L\216\000\200\217\"\000\200\353\304\000\200\013\233\000\200\307\263\000\000pV\216\274\212\211\376:\010Ud\273\370\373@\274\022,\337<\03135\273D\325\\\274\212\313M<\235S\225\273\310\307\253;\201[\265;o\305\317<\3268\220<\2009D=\026C\031=\331\274\261\273\244\261\007<\313dp\273\371:A;\234\250\347\273\220|\031\273\314\230I<\244\361D;\346\023\327\273@\245\035\273\247\332\023\274\200e\235\273b\004\000\000PY\000\0009\301\000\000[\312\000\200\216\305\000\200\371\032\000\000\272\320\000\200\351k\000\200\010J\000\000\234\315\255:D)W:q\366\264;RSu\2737\001\001\273n4-<\023\372\275\271\200\354I\273\t\306\022;j\2676:\273\257U\2737\302\351\273\272\026\216<\3333\301;a\272G\274\370\365\272;\360A\264;\000\371.\274`\003\202\273\233^j\274\003\254\311\271]\2464\273\372kX\274!\343\332;~\215 <\014\273\317;\227%L[\273\333\2631;xG\024:\201\204\322\273C\251L\273\230\243i;\315\367\276\272+\347B\272\022\362*9\301\346\327\273\020K\205<\031\372p<\303e&<\300\226-\272q\321\365\273\\\324J\273V\370\r\274\016;\373;C\274,\225\013\273\005\327H<\336\275\224<\300\025\266\272\002\267\246;E;\215<\320\021\3358\372\224I:\312d\375;\345\362@\274\013t\255\273\251\233\023;\263\213V\274\322\353L\272\263e2;*\235\355\273\002b \273Q\224\320;\361z\225\270_-\213\273;o\2559\241)\204;u\320_:\024\321#\273X((:\301}\007\273$\223\n<\206\004>:%\271\322\271<\254?\370<\253\336\337<@\264\321;-,@=\t\370\270<\237<\206=\364Uj=\223@\231\274\016\"\3178\335\306\006\274\221\301\267\273\025\212\224\273Z\256\';\014=\'<\217Al;\375kaQo\275\211]\330\273\371\r\255\306\273\375M\311;4\312\205<\022\271W\272\010\333\021\274\375\001\204\273\006\331\221\273\331g\'\275\235\320;\275\205\217\371\274\207\222\236\274b\242\326\274s~`\275\273\246R\275j%\204\275\243\024\234\275\021\233\220\273&\255j<\227y\t<\030p\010;5\307%\275WV\020\274c\306\214;m\222\036<\026\r\352;5|\305:<\017[<\335\255\313;\034\276\202\274M&\n\275>\303\264\273\312N\260:\230\340\202\360\324\247\300B\330\2470\215\215\247GbX\247S\216\003\247\332T\253\250\215\213,\250Mj\253\'l\351\252\250\007\330u\2506=\364&\237\255|\250\266\362\n\250\237\376\232\2462z\365\247\345\020\207\250\022\021\000\250\325\0354\2472\336\361\247`\331\003\'\303\360L\247\3750M\247\r\037\260\247\212\223\244\247\201\274P\'\262\274\271\247\2179A\'J`\003(\221\263\253&^\177a\250\245\005.\250\213\0142\250\251\r\002(\256\307((\330b\007(@.e(\373\240\203(\333\211?(\023\276\342\'\374|\265\'\366\023\003(uK\036\2504\374\006\250\247\341i\2500\323\216&R\370\325\'\234\305\036\246o\006\231\':7\013\'\341\016\203&\307y\000\000\371\325\000\200Oz\000\200\327b\000\000\340\301\000\000s\240\000\200\3076\000\200\033$\000\000l\254\000\200\317\313\346\246\211A\361$\364M\000\'\324\272\'\247n\212#\246\1778\261\245h\021g&D\340\262\'\371VJ(F\312!\'\263\255\274\'\022:G\'C\367\212\'\240\301\252\'\251\334g\'\024\027u\247\341E\225\246\335\210\022\247\300\263\216\250\024[F\250\331\316\n\250\256B\304\247C(L\247\270\244U\247X\261\270\247\031\363\312\247\216\256\354\247Z\362\035(\256$.\'wu\245&\345\337\344\'V\221\272\'[\344\177(\363\243\022(N.\226(\335a\341(k\214x(\'EA(\247\022\033(o\371\202(\250\311S({A\221(Z\nE(\006\317P(Yy\207(\026}\303\250\235\370\241\250\225\030\335\250\312\231\254\2505\200_\247q\346D\250\364\312\222\250&3\036\250\007<\276\247\210\353J\250\307\353\370&\341\'3(+\005\222\244Y\317\356\'s\000\237(\364\347\331\2478\255Z\247D\356\344\'\262\242\262\247\tn\230\250g\266\260\250\004>N\247\216\025\033\250\233\277\354\246f\314\247\247|\3161\250\202/=\247x\177\272\247zXb\250\316&\027\250\314\304\304&J\331\004\247\357R\226\247\330\037\022$\271d\235\246\337v\036\247Q\273\276\245\001\030G\245dZ\332&\314\252E\247\334\253\026\'\202A\021(\224~W&\r^\037(\252\007\206(C\245\345\'U\242\213\'Tf\306\'\031\217A(x\235\'(\335\271\007(\374\365\023(:8\372\'\371K\355&\251\013/\250\362\366\003\250\340\261b\247\\\315^\250\036\335\361\247\272\321\202\247\371\025\276\247Gb\345\247Xp\345\245_\262\273\247[jW\247\262\354N\246\022j\233\'2\322\304&a\235\021(1\313\202\243p\241a& \377]\'\037\177\246\250\0248\200\250bL\253\247\023\237P\250\330\337\372\247\363\340\360\247\334\3624\247<\341\036\245\267g\n\247H]=\250,\215\230\247\003/\213\246\000\314X\247@X\251\247\323\034\034&\302\234\351\247\274\343\375\247\000\347u\247\265\307\000\000\376\320\000\200\222\243\000\000\314\317\000\200q\317\000\2002~\000\200=\317\000\200\344\312\000\200\330.\000\200\374\202\233\'\275\327L(\260AL(\020(O(\"\263\236(\361&\236(\033\352\330\'|]9(h\332\027(\331\254\233\250\312\326\216\250\035$]\250;.\005\250a\017\301\247c`\213\250\335RS\250\210i\014\250\372\311\003\250V\373\345\'\001\236/\'\031\214M\'\243\262\233&\304\006B\247\307\020\313&\221<=\247\201\231\346\247\032m\320%Lg\000\000#8\000\000m\310\000\200\232\307\000\000\243\"\000\200\224\202\000\000\242\271\000\200\347u\000\000+M\000\200\334/\325\'\277P)(\347Q\355\'a5B(\272\324Y(\340AZ(\3364\240&\231\255\204\'\002\025\024(,\341r\250/G\020\250\307\313\313\247\214gX\2505\3107\250Dt\367\246\221Z\252\247\033,B\250\"\235f\247\346f\357&\200R\216\'\376r\257\246\326\215\000\245\276R\371\'\235/\241\'\366\365f\250l\326\252\247\272j>\246\346\034\273\'\330$\252\'\204\356\202\'\216\206\255(/\345\263(\302c^(\362\023\230(UO\242(b\203_(\202\322*(\252\033\240&\324$/\247\013+\261\'p\235\364&\251\261\377\'t)\222\';\200\372\'?f((89\303(\271\252\300(\212\217\202(*\014q(\253,\202(\254sH(\274Q\344\'\204\373\021(.V\024(!$\177\247\020\021\267\247\027\225@\250~\000|\246i\375c\'0\310U&f\266\200\247Ux\301\'\366\205\226\247\225\016\220\'\324\267C\'\274\224\226\'p\025)(\233\374.(\217 +(\214\233\322\'3Z\206&?0l&\256!\232\250\017(\243\250\307cF\250\237\0048\247\236\237\225#4&\327\' \'@\247`\256_&\251\r\216\'\312y\321\250[j\240\250\016o\222\250v\252\201\250\233e\177\250\200\0338&#o \250;\n-\250\206\354\317\247:\0303\247\250\t\254\'\000L\004(\257\371\025\'\30724(\351\246+(\202\332\005\247\260M\276\'\210:\350\'\016\250x\250\360\033\032\250\306G/\247\353\031\331&\317\342\357\'We\003(\0266\231\246j\211\275\'\257\034\251\'\232]r\246\213\320\374\246\346\317\240\247\265\214\014\246C\225q\'is\346\'\323\210)\250O\'J\250\257\374\035\250\322\3011(\256\267#(e\215\304\247aP\304\'\331Y\315\'Y\206X\2473@\211\247\tO\361\246\246\375\236#X\t\036\2501\351\267\247Z\246 \250\317\315\225\247\221\030.\247\267N\212\247o\0239\250N\363\007\250\235\r\243\247\013\3747\244D\231\211\247\365~X%\217\231K(y\034\n(~\264\237\'\356\301\020(~\202r\'2\366E\2477\022s\247U$\221\245\351\245v\246[T\030(\307\373m(\357a\354\'s\035\"\'_\313\322\'\354\032\005\247\276\004\356\246\245\037u\'`R\025\247\324\246-(\244\330v(\340\026\250\'\177\336\236\'\247\350\335\'\236l\252%\312\236\"(\274[3(\320v0(j\322h(\226/\207(\317\013~(R\270D(\324Y\031(_\276\t(Y\235h\251\212\205N\251\374U\362\250d<\264\247\251*\267\247N\010d(\306\250\272\246\275p\206\247\321\214\021\247\250I\246\'\351u_\'\310\'\273&W\305\265\'a\"\003(4~\204\'7\316\017\247\2374\022\247 \220\013\247\226\260\230\247:\375\213\247\302\200\210\246E\374e\245(\377?\246\037\315#\2458\214\334\246\001K\274\247s\374\211\247\316\226C\250B\245\251\247\215\343\231\247CF\200\250Y\365;\250\001\030Q\250\201-\225\250\0231v\250\351W\276\247X\250\323&\314\215\201%\203\204\307&\316\374\332\'\"\372k\'\233}\236\'f\375Q\'>\333\253&B\231~\'\225V\261\247<\002[\250\024\330,\247\235o\330\247\350K\211\250\001\032\000\'\3465\245\247\022AJ\250\217\211\302\'\226\347\234\247\237\264\254\247iQ/\250k\373O\'\356\364\020\'\033Q8\246\315\367\340\246\217\034\277\247\372\200\225\247\376\240\212(]\326W(\355=\343\'\014\343B(<\226=(\212\033\305\'\024c\366\'\371?&(\314\305Y\'\007*\000\'\321\201v&\233\013O\247\211fs\'\300\307\315\'\334W\215\'\236f\251\247\004)\214\247J\307\202\247\300\253\000\200\010\254\000\200\252\013\000\200\255Y\000\000\020\326\000\200K\264\000\000d\310\000\200\224f\000\000\343}\000\200SY\334\247\276\262\020\250\244\322X\247\2145\304&\032\377\231&?\227\"\'\361\253\245\247}\3316\250\343\233\016\250\337b\000\000\313k\000\200d\007\000\200=K\000\000\234\312\000\200\014\215\000\200\363S\000\200]v\000\000\031G\000\000\200A\341\247\036M\003\250\t\215\246\247\0103\000\250\353\t\205\247\271s\276\'\361\225E&C\270\002(\362\255\232(\300\3673&\241\2506%\215\037\252\247ZGw\'\027\tM\'%\333.\246Z9\205\'W\344f\'!?\001(\200\326\244\'\260:\264\'M{\020(\0363\026(\264\352\027(\343\311m(\000\351A(2@C(\266\241_(\252\007\224\'\236\356\250\'\231\345\372\246\307\177)( \214Q(\236\241w\'\201*\321\'\0004\304\'\340\273.%\355R\310\247-&\207\'\213\276\017\250\nM\320\'\211\013\200(4\353`\'%\372\243\250O\000&\250\235\347C\250\256\014\305\275g\020f\276\005w\020\276_s\232\275e\304W\275\032\240\200\275\"\210%>\334\235\261>\025\357N><\250#\342<\324\3073=\2750l=\220I\236\275\372\341\302<\243\"\006>\325\252\251;\356\313#<\312v\373<5\335\254=\270\035\254<\314c\247\275a\320E=\235\204\t=\374\340\024\275\262\2447\275\256\264\214<\013\t\325\274\326^\223\274\026\331\225<\003\335 =f\204\306=G\361K>\315U\031>\367Y\360\274\210\275\230<\217S\356\274W*\270\275\235`\351\275y\177\311\275\216\231\312<\307\266\210;M_|<\351\313\270\274\3167+<\211%\304\274E\354i;g\237\352<\\j\333<&#\242mI\323=\210/\013\275E\302\242\273\2541\377\274\366=\261\275\003\243\344\275\312\374\313\275R\276\022\274\037\2346\274\023\320\231\274E\275;\275!\252\367<\206\030M\275\270W\235<\311\212\331=W\034\013=\232Oc\273/<\317\273\345\274\'\272\035.k\274\256\234&\274\330?\252\274\005;\310<\350\213\362<\004\003\226;T\321p\274\327\026\250\274\243#\031;w\017\376\274\005W\207\274\210\320\203\274t9\335\273&\"\001=/z\230;\035f>\275\203Ih\275D\210*\275p+\236\273{pA<\347\313\336\331>\322\"b>\270FC\274\212\215\222<\344h\274\270[J\010\273\232\374\265<\016 \307\270$\201S\267\252\205\255K>&^/=4\350\230\2754&u=J\204\246\274@@\245<\030\237\022\275\254\026\017\275\317\367+<\302\2420<\366\326e\274eY\033<\257>\234\275\301\020\036\276\225<\335\275\014\200\231=\274\331\204=\341\304\233=\206\3551\251\254\342>\347\007\237>\003\373n\275t{\211\272\367\263Y\275z![\276\374\n\270\276\214yy\276\321qw<\010\005\250=\206r\016=\204\371\240\274\272\247\371\273\323\366\322\274R\300\335\273e\232Y\275cp&\275\217\305\022\274\305;\226\240\325;\227\246\035\274\021\375\233\273\216\275x\273\231.\254;dHD<,\247\204<\025T\347;\253\275\203\274\305\267\177<\311\377\345<\220h\210<\010\344\240\271\207\320E\275\033\231\r\274$\241y\274\tC\"\274\276\302$=@\351\233\274vP\026\275\273\332,\274[\353\n\275\360\203\000\200\3127\000\2006\272\000\000C\234\000\000\223\255\000\0001#\000\200\336\'\000\200\251\316\000\000\225%\000\200h\320\326\274\226]\004\274\032kg\274\337\370\r\275b$G\273\333E_:Rw\026\274\246\'\230;\236\317\204<\217\002b\274\277\010\362\274\007S\233\274j\204\257\274-\205e\2741(\361\2745U\370;\225\241\003=\340y\014\321\205\305=\373\310\316;{7\350\273*O7:b\314\004\275U1<\275%\266\276<\007X0\274\310\362\217\273\307\202\222;\177\021#\275\2618\020=\031\272R\274Q\201\211<)\217\006=\014\200\326\273\310\324\006\274\206x~<\264\007\014\274\241o\237;\277\354\214<\227x\255<\354;m\274\275\257\361<\003_q<\351\300\005\2759\024\313\274\377\264\247\274b\340\362\274\221\320\2278yh\222\273\344%)\275>\335\277\275\230*z\275%\317-\275?w\027\274\210\271\304\274\256\031\351<3s\000>\222Y\205=\030\365\265<\346Y8=\304\331\346=\003\203M=s\014\030\274`\341\200\275\024\032j\274\000hh\273\352\253,\275^\316\344\274*\220\275=\242-\023<\224$\016\275\325p;=\224\376V<2\250\271\272\246Yl;\327\243\202<|\r;=\213\245\004=]\221\370\272\330E-\275R\307X<~\320\240\274@\207\365\274P\203\302:\355\273\000\0007H\000\000\356\211\000\000\n\321\000\000\266%\000\200\237t\000\200\035\265\000\200\305\312\000\000\267{\000\0005\310<<\236@x<\346\355O\274:\241\230\274b\223\023\275gK\020\275\256\372\030\274\371i~\274\2570\\\274\275\246U<\365\326\350<\345\206\355<\243T\302\272\257\035\322<\006z\260\273\333\267Q\274%\364\006:\215(`\275\265\262\354\273\'&\342\272U\354\";\201\2179\273\241p1\275up\002\274\316l:\274U\267P\274\244\232\033\273\006\213\000\000\306t\000\000\243z\000\000\305\211\000\000\355\025\000\200\375\260\000\200h\313\000\200\206\310\000\000\312\217\000\200As\013;1\201\"\3607\275D\3654;\202\021\224:#z\000\275\014\023\203\274\360\344\246<\345-\"\275\334\274\315;?\035\247<\360\252\311\273\241\332\274\274\276\221\315\313<\236\327E<\007#\272\270\3119V;\357\267D;F\262\333\273f\311\265\274\253\315m\274\333\371\t=\2440|=\327pa=\205\273\232\274T\366)\274\302Q\202\2747\236\200;wV\226;\035\265\203\023\305\265=\357\370\375;\350\263J=\225\375\014;y\257\005\275\330\323\232\274\376\014\255\273,J\205;\334c\356\273^(\017<^}\332\273C\255j\274r\372i<\3633\027\275\205g\200\274\372Y\217\273\205\335\275\274\243\364&:]\356l;;\260&<\013 W\274\000U\236\273\337k5=A*\034:\n\361\343\273\275\035\263\273\360\245\327\273\372\335\227\274\034\036\003\274\226=\345\274\013\340\304;\217K0\274]\343e\273\273I\271\274\271\224H;&\334_\274\275\344C\274;\363\320\273U\t\335\274\332\030\327;u\256\374<\251\371^\274%\031&\274\236\307\260\371C;\234\306\217\273\014\227\226\272?\221W\274O|\352\272,~\223\274gX\006\274\337>\261\274aX\203\273\272\345\326:\274I\242\274\303\230t\273\235\272\245\273\272\036D;\325Ii\273\255v@=\023\241q<\244Z\374;\247\212`<\342\002\000<\036\234\000\000\212[\000\000\034\311\000\000-\221\000\2002\322\000\000W\306\000\000\356\210\000\0005\'\000\200gT\000\200A\224\n<\363\311K;\240\2226;,\317H;\027\267\013<\344\006!\272q;$\2749\021/\273\320O}\274\210\344\376\274\313\216\260\274\nR\334\274\232\247\230;\036\213b=\2620\346;\200\354\303\272\026\311\310<\340)\304;wb\256=\365)\243=\320@\257=Y\356\214=\327\276(=\355\347\310=2\214\273=\200\376\355=\177\270\016>Yf\005:\356Cg\273\305(\310\273\325\360u;m\355\230\274\206lZ\273k\267\026:\303vU\274..\202\274\234\344\361;b\346i<\0317\276;\345\313\333:\330\274\371;\303)\272;\266\225\304\273\024h\244\273\241\310\210;\346\246T\322\362\034>2\341\033:T\2345\274\030\000!n\243\273wd\265\273I[A\274z\343Y\274xZ\236\273\037\r\002<\r\271\303\273)\'\313\273\355P`\273\336%W;\022`\325;{y.;\350\363\324<\017-A:\240\252\276\273&\2039<\315h,\273\001\246\036\273!\313\016\274|\014\"\274\353\373\177\272\356\313{\274\037\3742\274j\271\271\274\271)\203\274\206&\t\275\311\344\360;,w\345\273\261\027\363\267\026\244};\203\374^\273\337OI<\013-)\274\315\177\306\273\235F,<\277\354x<\374HF<\rC\330\270nN\204<\234\372\363<\005c9\274\302\210y\274\301I\222\274\313\327*\274\370\260\335\273\"|\035\273\265\263\343\273`\365A<\350wE:\307\362N\274\271\337\212\274\'\342\031\273\375\224\001\275Q\367K\274\200\002\311\274\022\342/\274\202\203\213;xU3\273F,{\2741\247s\274Q\254\255\274\037\304\037\274\021c\304\376-\274\265\372\353\273=\334\231\274^\237\033\274\253\030\006<\305d\005<\212%\276\274\002\260\207\274\273\330(<\003\230.\274\312\244c;\203\222\222=\032\247`\275\033\034&{\003\275\327\037\t\275\222\232r\274\213\320\034\2755\254\302\274\253\257\247\273\336\273\031=\367\260\330<\203\275\274<\274\312c\274\236)\310=\332\324\266<\256\210\300=\210\376\373=\216\345e\274HD\317<\234\376X\274\247+\016\275\345\357\320\274h\336\016\275\225|\016\275\273\376l\326\262\273\261\016\257\273\000k\254;\230w\255\274\306_\243\274\352\321c\2747\334\3549/.\353\274\017j\225:W@\241\274@/\236\2749\315\314\273\337\346\224`\273\266\002\356;\2207\017<%\315\303\241\372\'=\'f:>\\bj>y\313\204<\206k\260\273%pR;jI\031\274\333\262\220\274\033\016\000\274\316#B;\264\014H\273g\210\2059Q\3449\274AL\217\2720^e\274\371\306\303\273\333\333\212\2727\375l\2740/\245\274\020I\221\274m-\313\274\202\005\232\274\252`\005\273\370\365!\274H\333\237\274\346\357\020=\006\342\257\273i=C:d\034\363;\362\255T;\306\233\010\274R\327\225<\010\0141=\311H%=\311\002@<\023a\375=\335\222\013=\242n\367=^\022\355=\371%\272;\352-\206\307f\230=\202\216c>\246\216h>s\200P\372\373<\335w\323<\027\264\312<\017\006\262\273=\2400\2739\316)\275\227\306p\274\245\254=<\'\304x=wz\005=\231\027E\274|\364\301\274\235\300B\274\374\256\304\274\232J\r\274\220w\017\274\305\222\253\274.\226\244\2723\257\236\273m\310\223\274c\333c\271\352\035\242\272\332\221\031\274\253e\231:\241Gd<\030\376\307\274L\263\200\274\364\t\232\273\365r\311<\247\311-;\200}\247<\243\010U\274W\207/\275\3757\023\274\277P\'=\213\374r=e\322\005<\221\211\020;\2010I<\234#\217;u\326T<\005\014\377;\222%\307\272}\370\247<\356\212\t\274m\322\277\272Dn\227<\361bO;\374\266\376\273\303!\376\273pj\223\274\372D\226\273\023\215L;\376I\024\273\304F6\2758\'\311;o\340\322\274r\035.\275]\225+\275I\026\344\274\002Q\305\274\266\211\306\273\017d+=QD(\274\244[\000\274\305y\023\274\230\314\306\274\327g\244\274j\000\030\274\252\246*\274\305\000,\315\273Q\312/:/\260\025:})\">\274\354\014\323\273\353cP\274\304\t\200\274\247\261S;\353 \231\274T\213=\273\253uV<\233\210\206\274\257\300\364\273\270\246\220\273\n\022\231;\324\337\0248x\301\205\273G5H\274pE\027\274\351%\250\273\267\341\327\274\265\036\3509i\013\360\272\230S\312<\270x\206<|\332a\274\345.8;\306\034k<\351\3379;\246se;\274\024\030;o\317\004\217<\226>\236;+\304\217<\372\235\020<\263\356\260\273\006G;\273\230\026J\260E$\276\375/(\276\035\204@>\321\332\335<\025\375\207\275Y\345c<\022\n5;]\007n\272_\362d\274\330\215\220\2749\232g=#\t\253<>+\022=\337L\272<&d^\274D\376d;\027\252\242<\021\002\000\274Dr\252<\273`\204<\360\340\212\272kd\222\274pN\344<\253*\203<\014\206\336:8k\273\273\325\237j<\270\236{<|@\306\274\2303\344;\241\250]<\253\025\026\275\372\345\200;rs\245\274\306\376\013\275\331j\330\274\313=\232<&\352\240\274\263\360.\274U\226\251\274\303B$=\023\202\256;\360Ld<\370\331;\273!\376\243;\r0U=\003\017\025\274\037\237\257\274\005\017\325;\327j\232\2740\"\214=\266;\334\274i\377[\275\32438>Be\354\275\261\355\241\275\220\205\362=3\020\001<\332{)\275\245,\337\272.Lx<\346N\222\274\200\007k\274\312\331k=\026a\202<\001\'6\275*\235.\273\327z\r\274\220s\024\275\203\221\373\273W\'\355<\277\271\037\275\323\336\343<\251\325y=\305\303\002\275\236\001\030\275N%\350<\232\241\216:\273 \207\273\313\2436\273\235\203/:\337X\206<8\211\021\272\221 \217\272r\246\247;l\005 <\220\037\020\273\221\001\210<\034\376\322<\260T\200\273\3537\022\275\252\217H=e\303Q\277\027\326\274-\313\017=\362\251\017\274Q\215\t\275\037\3076\003\275\335/\240<\016\314\230;\023k\013\275\030\325n<\376[\320=\216\2258\275\254~6\275\nd2=\326}p\274\334\312;\275\306\001\211: \333O\274p\342\270;\343\310\361\274\356\204\234\272\r\031\227=c\376\274\274*C`\275\177\252:;+\247b\274\024\260m;\023\320\326\274\301x\317\274\362?\235\275\330\332\024=\345\230==\325\316\003\275\\\341\237\274HY\207\272\231.\321\273\263\231+\270\337\342\362;y\371M=-\320\'\274k\t\024\274u\2403=-\035\371\273\202b\252\274\213\227\271\274\354B\376;\304,\'=\006\341v\2751Tu\273~4\241=\332\303a\275\271\265\031\273\035rz=k\356w\274\362|\322\274;\256\223\273K}\220\2724\027\032\275\371\222\203<8\nx<}\270\006\274Mhy<\211?0<\227\312\222\274\211J\214\274\314\367\244\274\220t\235\274v\010\264\273{\317\243\273k\037\037\274\033\006\212\274\360mQ;7\003.\273^\301\t\274\261\236X<\202\211\260\274\307\272\024\274M3\366<\034-V;\347\327n\273\215\007\347\274\024\002\360:\022V\n\326V1\276GT\264\275\210\316\031>\3559\253\274]a\234\275\335\327HQ=\256\277!:\267\r,\275\217\340\024\273\347\240\235\273:\034\241\2754g{;\255\326\214\273\235&\225\274\237/8$\222;0k\373<\271\020\002=\207\2776=\353\204\245;vz\215\275{\245b\275\242\364\r=\315\002\037=U\313:=x\347\225<\301\270\035\274\215\347\222\273\026&\016<09H\275[\261\363<\324\365\240<\t\'\312;\216\027\231<\376H\300;\231\272\251<;\260s\273\026\322\014=?2C=\266\016\203:\035=\260\274h\007\312\274\324\215\t\275l[\007=\354\035j=\024\343W=\253\343\025=B\216\302\273?\314\177\273N&\223<\246\321B\275\355J\025\275S/\332\270\243\316\363:\306(\202<\213\307\212\274\274\002\022=\367w%\275\271\326$\274q\246\224\2737\322\230\274O\201;\266\240\227\274\270\225|\274ym\221<:\374+\274\247\331x;\242\036\014\274\275\263\210\274\330Pd\275\230\2430\275\032\\k:\330\226\241=W\n\274;\267\017\212\274\367\014\251<~q.\274E\004\226\274\037`\'=D\227\356\273\367\227)\275\241\306\236\274\320\014\307\274Hg\000\275!\245\203\275\301\264(\275\310\272\342\274\222\026\t=\322K\370\272\352\335\356\274\024\001\035=\225\t\327:\364\261/=g\354\322<\362\t\341<\251q\265\273B\305o\274\035\353w\342HoJ<\214\366m;[!(<\367$\r<+\312\254<\231_\243\274C\331,<9\016U=\013\371\007\274\362v%=\177\216\222<>\202\375\274\222\216g<\025a2<\216#\032\275\247\216\203\274\357\332\220\236\273\260\026\215<\026\330\303<\331\343\323M\365*=\351N\023\274\374\351\301\216\204\274\ni\316\273\272(\002\2745\215\367\273\265\265\300\273*\244~\274\377\313\310\274X\237\320=\177\275\227\273\226``<\267\304\341<2\227\375;D\316\335\272*s\274\273\267\370u<1\316J\274;\037`\274\243\346\320\316N\233\274a~\204\274\374\200\205=H\326\323\273\324\221\355\274\301\361B\274k\253\343<=WS=\\\n\177%\275h\203\365\272\025\210\217=\203\340\227=\004\315\250<\226w\377<\3517[\274\201\370\303\274\274\214\236;\350\235\260\274\240Z\000\274\020\301o\273Xq\262\274\325\'\221;\224\315\273;\346\242\213\274\257\357\334\272\377\tt;t\023|\274\345Z\017\274\035Z\330;f\2678\274\t\021\375\272\303V\220;\323\341I<\324O\375<\241\\m<-\346d;\030\337!\273\"a!=j\333\231<\225\265\215\274IV\374<\263$\247;\360u\315\274}\341\366p.\322<^m\333\275E\207\\=\023\206\235\274Ji\222\275\272r\336\273\246\263[<\366[\203;p\003\335<\007\242\202=\213Wi=\002*@\274w0\014=O\324\266<$_\247<\216\201B=N\304\364<>\206\025=\257\005@=^\310q=\250e\272Q\000^\373\272?\022\t<\370V\001\275]e\207\274j\020+\2746A\262\274\332\265r\274v\321B\274\201v\313;G\r\023\274\302\027\021\274\204\235\352<{\026\310;\t\274\320\274\303x\221:\323\236\211\274X\t\301;[\233\003<\344\303\355\273\215$P\274\273j!<\006\344\200\274+\246\304\274x\205@\274\010Q\317\274\3321\027\274\213<\301\273\367\206\333\273y.\013\274\t\345\355\273\327J.\274.E\366\272\225\031\343\272\265\260T:\342\007\320\274i\031C\274\336\016\221;L\250\263;\237O\233\273(\326\240\274\304p&<\326\177\373<\340/_<\365h\320\000\200\321\257\000\000\347\210\000\000%\233\000\200:T\000\000\267\022R\274\035q\276\274(Z\222\274\273-c\273\006F\366\274\242\221\032\275\031\213\306\274V\320\256\274\314\024q\274\2427\001\206^\222\274p\206\031\274ted=*\017\004\275\343eO;\365\352\221;\"\214\032\273\337\273\233\274\353\023\216e;\216\253\253\273\314\312\220:\220N\372\032J\260=\251\356;;\311\277\221\274^_\023\275\202D\265\274\221\257\330;e\321];-\204*\274\340\230\237\273U\261=\274\013\367y\274\226\254\262;L\302\336\273\357q(\272\210\022b\273\310\"\230;X8\022;\275\3425<\r\323><\240\023\016>\3242\037\273N\t\353;\021\202a\274\316\237\026\274\356E\274\274W\216\023\275\215~\227\2730\031%\275\020\035l\275\356.\371\274\020\370\217\274\244\310\363\274\257\360N\274\320\307\"\275\024\345;\275\365 \275*\027\n\275\210\240\355\275\200d\036\275M\243-\275\006\211O\275\212\245\030\275\354?\"<\364!\373\274RE\245\273@[\255;\216\240^=\017\031\201<60\004\274k\331\000\275\004;\007=\210\026\373<\020\262\214\274G\234M\274:\313\022<\233cs<@\253\214<\354\354S\256\321\274\207\244E\274\0060J\273\264\271\374\273\263\231\020>A\346\334\272\r\222\030\273\240\361\357\274\260\307*\273\324\251\353\274C\n\031\27503\003=O\257\030\275iH\"\276\375\266\031\275\227\014\033<\264\002\256\274(y\255\274\2733\000\000\024\220\000\200\324\211\000\2004V\000\000\276\236\000\200\315\320\000\200(\325\000\200\223\275\000\000\356v\000\000_\326*<\244X^<\272`\004=/\306\220=c\360\200=\307i\010=\037\364\031=\203\215c=F&\241<\221\223J;\335\3430\274\331\325]<^\326\213<\271\030\027=\036\034\026<(\025\r<6\210\221\274\033\212\234\273\241\264\021\274\207\322A\274k#\177\274\321!L9\006\226~\2757\345\t\274\300\3755\272\222\322\026\274m\205k\273\303\316\000\000\361\311\000\200.;\000\200.d\000\000\022f\000\000\323\250\000\200`$\000\000U\276\000\200\td\000\000\351\260M\273l6l;o-\250i\271\261C\215<\203\370j<\225\333\273;\214\216\035<\351\004\033\350-\240\237\273$h\213:\263C4;\245#h;\240\256_<\375{A<\212\005\305;\332\273-;\337N\241\273\343Z\215\274\237\261\r\274\263q!\274\355\321\365<\257\276\024<>\271\323<\304j6\271\025\312\272\251\2740\364\005\275\032\376\002\275\0229y\275Z\331\206\274\225=\267\274\301\200\372\274\3628\037\274`P\363;\305\360K\273\241\202\202<\206\275<\274\321X\343\274+7\177<\361\265\005\275tcM\274k\2358\273F\205\372\274n\275\225\273N\315\311\274\243\010\301\274-l\213<\372(\311<\271\025\316<\262[\330\274f\024\246\274v\313\247\273\217\254\244;\277\\@=/kO<\004%v\275\323\026 =\211b8\275\250\212m\373\323\273\273s\246\200\275\220$\227\274\215\327}\274\220\337\234\275V}D\2752\354\002\274\032#_\275\245\346=\275y\350\026\273\035\004\352<\324\035\"<\340\3662=\3450\006>m\351\231=m\306\375\205\'\275.\3634\275\356\264\030\274A\360\177;\207n\244\273\341Y\000\275\032\030Q\274\357\220\367\274\325\006L\274\026+c\274\264\315]\274\377\230M\274\026\211\230\274]*;\274L\350B\275\214\207\311\274\r\303I\275\232\2638\275wdL\274\226H\227\274\274\224\031;\2113\212\274+u\244\274&\"v\274\336\300\026\274-\200\272+Z\277;^\302\252<&\311K<\016\271\017<\265\324E;\331\274\305\273\215\214Q\274\342[\363\274X\373\326\273\262j\207;\306\377R\202\2751\226\004=\224i\213\273f\253\314<\377\002Q;\377\317\302:\344\275\323:$\341\302<\177\376o=\332\361\225=\245=\211=\r\357\010=\026\307\277<\375d\267<\207d\373<\355\373\316<\215\304\300<\025\313\020\274\323\366\362;\360\024\270\275\027\307\213<}Nb<\300\307Q\274\320\277\376\273\220\226\273\274K\206\352\274\337\373\000\274=l\243\275\257\256\256\275;sO\2743\310\'\275\\y\370\274\035-\237\273\224\345O;\327\023\335;\251\204\226;\030\212\300\273\215\241\302\274\270\320\312\273\353\306\234\274\341\007\233\274\300\031-\274w.\210<\016\316\022;\nl\262\273\026\253\221\274\246\325^=`w^\274\220\354F=\3764\034=3`\312;\035\226\376:\243/\236\273\337P\336;`#\275\273\326\313Z\274d\330;\273\372\204\010\274\277M\330\274\024\274\244<=\312\230<\207_\211;\036\306Y=\336P\024>v\364\233\256\342\227=\002\203!<\271k\210=>\254%=\025\212\034<\037W\200M0\275\346t@<\254\376-\274B\t\211\274A*\007<\213\357\n8i\027\\\2748Z\275\274\2130_<\252?\233=\200sl;d\372\277\274#\242\237<\007\325\260<\016\2649\274\r\304\236\274\\\304J\004\216\256=*Z\010=\316\303\310=xt\232=W\240N<8\233\304<+\217\271;\272p\031=T\376J=\3116\271=%\304\337\273SSS=\362\240\262=II\"\274\003~\'\274\222\004\321;\274\220\356;\243\037h\216<\325\337U\274\300X\262<\372\354\202<~\022\254\274\356(j<\224e\300<:u\212<\240\346\267\272\267\233\t8\016\256\007\274B\361\211i\217;=\276SR=\213a\242=r\000,=u#\017;\006\313\275\206L\242\275\240\022\362\275!]J\275\024,\250\331-\231\275\232F\031\275\022\352\254\275\013\035\006\275\331\222\210<\212\300\356\271\035V\276\273\215\306J\275G\251\252\275\214c;\275\372`\305:h\027m\273\022\244\217\274\275\200\036\274IH\310\274\371\036I=\275b\025=\353\331\223\272\206\245\000={\245\303\275\016j\220<\3200\334;\025\027\024=\225\260\010=+\306`\274K\274\027\275\345m\347;\321a\302<\236\361\202\275\337\356\276\274\330\343\207;\264\302\004=W\217\362<\364\321\000\200\245y\000\200?\220\000\000\342\313\000\000\377s\000\000bg\000\200-\257\000\2003\312\000\200]\317\000\000\335\220\245<3\350\315<\247n\224\275B\262\261\274\353JL\274C;\374\273\261\251\027\275\215q\346\273\330\353\345<\2132\365\271A\345\276:\325\361\375\275\222\220#\275\013?\001\000\000\213\310\000\200\222S\000\2006\256\000\200Y\'\000\200P\214\000\000\226$\023<*\022-=LS\216;\231%\374\274F\0319\275\312\262\215<\310\357\200=\001\263\267\273\021\273?=\303o\000\200\003\305\000\200\234$\000\000D\312\000\200\210x\000\000\300>\000\200*4\000\200e\031\000\200\312\n\000\200\307\315\037\275K\246\356\275R\254E\275v\357\320\275K\313\216>\320\017\372\275\021\374\016\275\213\363\007\276d\250\177\275\223\3527<\034\242R\274L\020\266\274\243\213\325\274,f\301\274)\201\201\274\316\025\t\274e\375E\274dM\355\273\346\243\020;\213\364\034<\2706\277<\331\'%\274\364\345\256=h\363\256\274\372\231?<\t\304P\273\000\214=;]=\240\272t\353u<\004\366\n\273\271\021#=\375\251\023\276\264\317\260n\000\200=\307\000\200C\226\000\000\271\236\000\200\266\231><[\364\020\254\202<\254\307t=\347\223\376;\026\"e\274\025=!\272\233\021\252<^\020,<=\r\255\2749\020\025\275\027)b\274\200k\026\275\333\315W\274\022X&<.\314\025\027\000\000\331\314\000\200K\315\000\2006\214\000\200<\311\000\200\341a\000\000\242\320\000\200L>\327;\035\215\207;\033x\214\273q\326,=y\376\025=\344\217,\273\345\252\363<\032\204\002=O\'3\274\022\300\207;\366q\023:R\320s\273\365sV<\227\317\351\274\255\367[\274aZF<\370-P<\251\3432<\225\006\331;r\001p\274\226\373\235\274\n\236v\274_\210\021<\327\370`<\207\275[\272\315\261h\274\235U\224;\242\024\233\274\000\277\311\274\266\210\223\272N\261\014\274\303=\014<\034\023w\2733$Z\274%\t\214\273\311\332/\274\256\301\252\274M\250o\2748\003\252\274>\016\213\274\024r\357:\313\305\262\273\316e\227\273aG\265\274K\201V\273e\035\220\274\220\002*\2743\327\004\274\036\247v;\262\244k;\232\001\315\273!\252\313\272\210\277\036<\326\214\2618\230\311\251;s\267%<\3070+\274*8u\274\311\335\224\274$b\203;\261\364J\274\361\250r\274#hK<\332U\2609[ \272;\231\272\000\200\020\242\000\000||\000\200\214\245\000\000 P\000\200\241\261\000\000,2\000\200\234\302\000\000\317p\000\200\251\036%\274\354\365\230\274\372\3270;\305\350\023\273\t\367\345<\335\240M\224\241\273\237\014\237\274J\220\307\274\265U\301:1@\255<\362\246\255<*\342U<\274\217\023=\265\345u<:U\215\272\275\254^\274k\226\236<\266\362/\272~\027E\274a?\272\312\252\331\273#\211\322\274\345\246N\274cg\321\274|\014\020;*\301l\273\216\311\262<<\205h<\323\310\265;\350\365\023<\316Y\000;(\206H<\243\303B9\266\225\360\273i\354\371\273}\304\022\274\374`\232:\375\357G\273o\254\207<\332\272\326;\357VA<@\014\360<$\322\r\273)\346\321\273(+\360;Y\262\276\273P\027\210\274f\022\220\273t\240\370<\377\311!=,h\206<\367\307?\000=p\021\242<\267.\207<\376\347\021\274\224\037Q<\030\266\032\274\2762-\274>\260D:\006\374\206\274\262C\262\274\333OD9\310\302\215\272+?\253;]\337\371;\203\237#\273\335[F;..\373;5\'\034\273\202\0310;\263p\203;\001\t\035\274\304\242\220\273\252\013\225:\000\004H\274\256\010\003<\016\023\017\2743\023\027\274\360a\262\273P\337\230\273B5\000\2001\307\000\200]r\000\200\375\273\000\000\201\314\000\000UI\000\200Y\311\000\000\024)\000\200*\315\000\000N\325\010<\207/\034\274Q\\\275\273\025\027\307(L2=-:q<\324\257\017=;\030\253;\000\037\253;\321q\020\274\222\212\330<,~\317<\366\3524<_\275;\302\005\3009z\273/<\365\306\274\273\243\212\002<\034\014\035=\210\367\'<\310\'r=U!\030>\265\343\222=n\333\341\273\276\\\021=\301Od<\335;3:\000\377*<\262\036o7 a\220\273\235H\225<\375:\225;\245\202*\274\307\276z:?\241\341:/mX\275?\300P\275dm\367\273_t{;]\221\206\2741[\331<5\232\202\274\0224\202<\373\026*<\240S\356\274q\256B\275s\253\026\275.\245K\274[\374\324\275^\360h\275\372\213\036\275\216Z\237\275\330W8\275\325\273\301;\273\211\212;\361@\"\274\003~\242;\300\253k=\010h.\274\006\014:;<\274\317<\243\006J<\232\334\213\270\0241\233\273KTX[<\2245\002\275\'\270\006\275\204wK\275\2117\333<>I\372<\353E<<\\as<\004t\316\274\323E\316\274\276\213y\274o\251y;\031\313\035\275\270\265\030\275\330Y5\275\354\3134\274\220\274E;J9~<\000qkJ<&\372n;\305\203\026\275\353\222\010=cHN<&g?<\033\316\020\275\201\322\323\274\245\t\225\271\006|\305\273\353\372l\275\316A*<\0239N\275\017\267\t\274pZ\247=\177\230s<\273&\211=p\312\334\275Z\244\327\2726\010J=:\034\024\274\373C\035<\257I[=\344\311.\276\031y\026<\264\022\345<\200P5\275\266P =3\rE<\266H\245\274+\301\230\274\002V\215\275sE->\356dD=c\226\246\274\361\234\202\275\304Q\"\275,\320\217\274\3230\225\274\244\201\323\274\013\376\336\274c6\210=9(\007\275[/f\274>\005`>=\212\352\215\274\221L\236\274\274\270m<\270H\022\274\204\254O<\361J\032<\365\251\370<5?\260<\t\014\266\2755\024&<@>\346<\215\365\343\274(\031\033<+\214\204;j\331\240<\254j\313;\3533\314<\316\2172\274\335#\326<-\022y\325\226\273\024\2210\275\347w%\275\341\257-<^H`\275\232\252\330\274\372\341\225=\306.\211\275e\nn\275\323\226g=C\333\360<\006\327\024=[O\006=\301E\000=\321\274\024=8\365\366<\372\177\026\274!\251\243\2752\206\024<\001;n\274\373d\370<\345\262U<\030n\207<\305\013\'=@\005 =Okt<\3411 =td\231<\262\204l\274\276\246\241\274\327v\355<$\337C=\372\t\010\275\362k\232;#K\324\273hD\276\274\027,\332;$\200\371;r\263<\274o\222\033=\3673\320<\357T=\274\020\217*;\032\261b;\242I\310\274A\2575\275\260\003\034\275x.\2269\356\260\232=\236\341\270\274\311\225\207<\027\360\274\350\271%\275\rh\340\274\266\277?\274p\357\351<\027\337c\274\377`\236<\026\201$=\357\t\273;\356\241\254<\205p\220=\373*\211<\232\010~<\027\202\212\274h,\361<\265\310)\2719\204(\273t\035\330<\222\254L\274\205\331S\274\205\035\370\274O\361\205\274\301?\254<\211\337K\275\003\001\237\275\325gl=\313J\260\274m\023\241\273\330sn=2#\000\200}\005\000\000L\272\000\000\335x\000\200\272\204\000\000\321\232\000\200ViV\2757\372\313\273n\025\r>\214\306\251<\363\220\331\274\252\242\"\274\236m\216=\323z\030<2\216=\275\243\325\343<>\016c\274\362VJ\275\366y\031:x\2529\273\306\303\206\274D\223\326\022K\247\275q\275A\275\026\320\316=\216\246:\342\351j\275\035\226 \275\t\302\217=[\302T;\261\242\206<\330\345\210:\322rm<\022^\332\273\000\256o\274\314\017w<\302\202\232\003x\275\216r\006<\203\357\202;\330Y\245\273\304\274\345w\017\247\275\226 +\275\240\372\322=\343\360\265<0\326<=\236\363\226=\220\255\256\274fjp\275\240%.={\270\003\273\223\".\275n\206\034=\261\000\310\274\006\270\037\275\332`\242=\001\n\r\274\334\'\013\274\342\221M=p\217\257\2734\324\272:\326\246\003>\237\021\247\273\007\222\256\2755l\216>r\233\014=\010dv\276\001\006\036>\345#\017\275\214\255\032\276\244eO=_\tZ\274K+\314\2743\337!={\205\244;\222\334K\275K\'?=m\302\271\274\223b\364\274\206\'Z\274\352\211\274;\2149e\274\332Z\265\274z\260\225\273\330n\305\273\037A\227\274\202=\222\273\241\275\374;{~\324\274a\345\323\274\346\024-\273\014f\215<\375\323~=\370{\027=V5\014\274\241\377\335<\376\236\316\273\315;%\275\206f+\275~9\214=\245\307\237\275\032\225\272\274\202~=>\233i#\275\374t\027\275\177\313\222=HYE\316\033\002>\362%\322\274\216\220\235=o\257\373;\257o\266<\364q\3078\017\330j;\342n\311<\014\371\021\275\270\304y\274%\340\204<\322\2252\274\311\252p;\312\023\304\273Q-\223\311\000\000\314\007\000\200{6\000\200\215\324\000\000\017\271\000\000\033C\000\200\233w\000\200f\332\257\274\333\274\226\274-\331\224<\354GD\275\236\337\322\274\262\336==\027-$\275h\321\311\273[\002v=\235B\367\274\352fZ\273\331\250a=\354\316\220\276=\201\021\223?\301\032\275\252\035\005\274\222\342\356;\0317\r=\270\302\223<\\\334\335\274\325\354\317<\002\334S<\346&$\274\010\016N\275\341\016\250\274C\367(=SZ\277\275PF\024\275\037t\265=\372tL\275)\312?\274\354r\214=\275\321&\274\221?\276\274\006?,=:@\010<\017\243\007\274\034\271P=\356\247\313:\021\033\021\275\\\2024;Cc\326\273\007\243\232\274(p\374;\277\254\r<\335\027\030<|\313\005=\232m\361:\247\322U\274vI|\274M=\034=\357Su\274\274g\r\275\310J\240=\217\300\222;v)z\275\263W{=\304\300B\275\0062\202\275\302U\024<\273X\375\273t>>\274\\\231\256\274\315\214\234\274\330\335B\273\363\311\323\273%\027n\274\257\337\223\273\243\345\367:\204]\254;$\023\007=\264-\266\274n6\202\275tF\265\274D\337\2029\010\202\260\272\203\360\005=\243\236\334:\256<\014\275\271O\002>\036H\322\274:\313\254\275x=\242>]\355\017;y\274m\276\035\256->\025\362S\275\361\360\"\276\313\3260\274\020\303]\275\322=\246\274T\365\177<\326\032\362\271/~\363;\257\334\213\274Y,\333\274\260\374 <\237\223^\274\357\265\2079n\024\342;\341\036\252;k\366\030=\362\333\243\035<\005\"Z\275\331\244\326\274\260\036\205<\325\304\335\273\207\033\271<\351OG\274\346\324\216\274\266\270\316<\327\264\316\273y\344U\274\020t\256\274\005S\244\273\274\314\022X=x\242\000\000\266g\000\000X\266\000\000\247\215\000\200\247\200\000\200\236\205\000\000&{\000\200\210%\000\000\333+\000\200vO\024=\327\261]\274\365\242\023\2744\215\205\236\273\365\263\314\273\217\233\220:\212\013\242\275\003T\244\275ek\004>\212\324-\276\020|\r\275\211#\273>\3050\000\276\303\337\246\275\202\005Q>\207T3=\036\037\313=\246\263\232=%\200\252=\326!\323\274\327\221\032>\344h\310=yg+>\2345\n>\254\347P=|\241r==&c=\246\265e=\326\201q\2741[\273=\243\235P=4\304\271=\362\306\227=\221j3\274\373\266\367\274c\007\312\273\'G\206\274v\200\244\272(Q$=\r\347\372\273\304\260\340\273\027b\242\273lZ\334;\220\304\252\273M\247\226\274\330\263|=2\346d\275\261\226\270\274=\240\317;\255\037Z\275(\r\362\274\255\267P\272#wg\273X70\274\322\307\343\274\242\323\262\274l\272I\275v\334\232\274\004\235@\275\306\310\345\274;\306f\2747\315\251<\253a\271<\362\352\223<\316\221\356\274E\350\001=1\327\306<\2164\333<\010\036\323;\374\261\231<\352\030\203<\271\236Q<\222a\024<\240\355N=\262rk\274\253\'\251\273\337PT=\375\327\247\275\207\351\223\275t\336\022>\306bS\275Z\347/\275\035a\002\275\001s\010\275\034\210I\274\3621\240\274\337k\016\273\365W\216\272X\205\025\274LLj\274\274\264\252<6\215\276\273.\374\320;a\333\321\275j\311\204\274\n\251\231<\241\353H\274\001\267~;TL#;\030\033\\\275&y\r\275~\025q<\365\216\267\237a;\247\034%=\224\304\021<\005l\346\2730;\005\275\372X\013\2751\346\227\274\342\334\216;Wl\021;\203\312\323\274\013\002z;Z\240\000\000\004?\000\200\374\201\000\000\271\312\000\2007\321\000\200\3027\000\000\033\'\000\000r\311\000\000\006\004\000\200\366\347\262;\314\370D\275\206\212l\274d\266\000\000\251\270\000\200\026\244\000\000\307)\000\000j\315\000\000\304\303\000\200\215\236\000\200\300\177\000\200Q4\000\000\330t!\274\337\217\262\274\242\253^<\027p\264\274\020#\246\274\206k\030<{\'s\274\320|\272\273\322\213};\263\365\201<\255Y%=\222\225\311<+\274D<\374\325\025=\331\315\313\273{\0106:\035\177\020\275\n\247\244\274H\244\231:4mm\273\225c\204\272C\247\007\273\t\2727\275\255&g<6\234\'\272{\372O\274\336\236\260;Ro\223\274#L\007\272<\275\264;\235?\026=\312\304\274<)\312\n=S;\304\275v\277m=|H\022\\\256<\311v\326\273\001\362\353\274\275\220 <;\237\032<\033Q\242<\345z\010\275\207TT<\\\004\222\274\311\263\023\275k7\205\273\013\370\213\256\27366\205\272\t:\007<\271\221\210<4)\377<8A\035=\216\255\005=\"\177\277<2\324\031=\033\357\355<\324\3001<\3442\241<\274\324\376;\355-\217\273\353v\"<\245\025\013\274\226\036\271<~\352,\275oT;\274\251\204\262\273\210\340N\274\320\200\240\274Y\274\000\200-9\000\000\307F\000\200Gj\000\200\217%\000\000\370\255\000\200\204~\000\200\276f\000\000\371\311\000\200)\004\227;\030\276\377;pM%<\305\337\000=\016\031c\275yU`\274\377%8\274\237\326\372<\300\032\r\274S\255\000\200\372\212\000\200r\234\000\200?y\000\200QS\000\000\027\243\000\200g\215\000\200\255*\000\200\253\216\000\000d\2141\275\205v3\275\264\202\027\274\260\306\322\274\240\363%>\235!\036;93\213\273d\227\207\274\355\000\023\273\277\303\354\274\362\260m\274w%\027\274R\313B\274\214I\220\275\275\325\273<\001\334\267\273Y\320\034<\317\254\261\273\260\235\366;M\177\244;\347\365\237;\310\253\210;X&F\031\252\274\031\247*\275Z\256\323\274}\223\003\275#RM\275$A\037\275\303\255\343\274Y\334\212\2755=\013>\344j\205>\332\023)>\347\003n<\203\347s=w\342\350\274\251\313\321\275\230\303k\2765\0309\276\311\260\270<\352\202\250<\330\240H=2\237\237\273\252\321<=s\000\264\271\367\273e\274t\336 \275\277\006\360\274\207\334\272=b\314Q=\000\035w\275\353(\333;dG\340\272\024\343\020<\321l\200\275\234\204S\275TI\255=E\271\002\275\347\310Y\271\333n\251<\014\r\020\274\014\376\335;\202\372\301\274u\355\022=\014\013\235=\314)\000\275\230\346B\275\346\262\316\275b\334\262\275\313\256\357\016>-\265\246<\315-\013=\221\371\260<\207_\210\274Oo,:Ne\302;\274\227\t\274\212\316\266\274\230\275\023;\2739\326;\344\323+=A\2022=\327\234\222\274\326L\303<&\0173=\026\205T<\365\364\005N\322\204=\033\244\355\274\222\316\236=\013\273\320\273\3474\347:\276\235\275\274\250\202\257\273?\224\310\274n\265\231\274\347\270\323\274d\266E<\346\241<=8\3767<\230 \207;\321\366e\273\240\"/=\216{\224\274\237\211\371\274\366{\316\273\234\224+=E)\306<.\212\014;`\352D=4\031j=\312\010N\274\002\262\243\274Y\223\331?\271\357\370&;\204\327\235\273l^b\275\345V\355\274\223\250\334\274Lq\317\274\276\3225<\026\246\261<\376\025\220)+1=}Q\371\274\004Zn=\321\0077;\016&\000\200h\217\000\200\313\250\000\200\207\234\000\200\245.\000\000\323*\000\000\311\n\000\200\262#\000\000K\304\000\200\022\203\340\274\222kM\275\022)H\275\347}\246\274\247\373q\274v)\024\274\241\007\002=)\240\212=V+\306=\354\222\030\274^\222E=\320%\027<\372\227s\274\340\000\017>|\357C=I4\221\275C\374\210<;W\244\274\005\254\034\275\005\212\231\275\t\223\227\275v|$\275i_F\275\224\357T\275W2M=7Q\006>_\343\261=\327Ag9\264\202\353;(k\245<\371\361\371;\350\303\312\272u\316%\274\000\035p;\335|\226<\226\024\213<4\203\377\274\235}+<\226\274\t=\017\265\021<\272\343\025\274\303\222\303\272\220\211\336<\260\013\333\274\203\363\315\274\213=\027\275\230\277}\275\313\004%\275F\357\\\274\360\267)\275pM\376\273\253#\025=\312-\220=\240\221\227=Y&<\273\326\257\026\275\311M\320\274\302h\211\272q\226\032\274\013\271P\274U\307\225=\023\370\212=\017x\025=,\367K\274{\361/\272\345\263\331\274\027\216\n\275O<\207\275w\206-\275R\240\023\274h\024\027\273:\037\375\274\377\222+\273,\272H=Y\314\332;\215\204\250\274Y\351-\274\314\205}\274\037\013B;\213\276\226\274j\241\372\273\236\2329\275r\227\035\275\252v\233\274\205\236\246\274B\007_;\320\353\005=\360w\021\274us_=\320[\227;U\370\360\2740{\303\274\261\356\312\273\tn\201\273X\320\031\274\223M\017\275\361\033\020=\321g\n=\031\361\013=\235w\202<\234\005\315<\007\204 \274D=\003<2T\200<\032\337\260\274\311\205X\275\362\036\260\2746\r\263<.6\365\273\372tI<\004!2<\362(S=\306-\272=\277\021\343;7\332O\275(\243\274\275\230\212\220\275\257Q\007\275\270\316\336\272\216\023\361\274\263\020B=\234O\322=\340\271\270=\261\262\016=\276\036}<\334\343\307<\332e\230\272\tY\"\274S\013L<\242SX\274\313/\204\275\261f\346\273\214\353\363\273X\000\307\272\376z\310\273\376\212\313\274\017*\212\273G&\205\274|I1\274\0223A=\025\257\225<\375GF\273\363}\240\273\213E\361\274\356}7\275\267\007\200\274\315\370\230\274\022\376O;\347\232\026<\034o\232\203\312\230>\304\337\036>&=p\2734\3279=\367\3432\275\214\241\002\276\270\002\204\276\007\251?\276\206J\010=wn\025<\324{\\e\267\274\004\315\003%\213\277>\3304}>\247\326\311=\360p>>\006\2266>\274\253\302\275\036\2759\275w\341H=\230B\002\276\244\2355\276X\274?\275\202\236\207<\274\234W=\361\255W=h\3269\274n]\340<%?#=Z\2139\275\336\354P\275\326J\300\274\000V\014=\263\317>\275_k\271\275\3374\247\274\241p\211\274\233\365\007\274\332\331Q\275\330\253]\274R\177\n=\323\270\255:\r\213\030\274>\210\010=\305\256>=\270\013\224\275G \274\274\343\337\321<\226\261B\275\355\227\227\274\027[\235<\037\303\316;\336\353\244;\245f\370:6\221\031<\300Y+\275\333\326\262V\366\207\274\244\241\372\274\354\001\205=\202\313w<\023\351\217\274\020\340W=\322\200*=\035\304v\274j2\324\274\254l=<(\247T\273\315\202\023\274\231\237U<\001\221\017=\n\004\375<\344\222\346\273<\177b\275\006\325\036\275\2071\300;NL-\275\022\345\317;\377b\235\271\350VS\274\036\312\316\274\226\220\274\274E8\010=\301\244\017\274\365\271}:\361\177\333<\245k\347<\355\212\227;\234\307\320{z\274\037\257L\275\214\260\316<\247Z\023\2745e\035\275\001,\221\275\312\3451\275;_\216<\217u\247<\223\326\356\274g\364\303\273SU\217\273\346Ek=\033\276[;\337\301\367\274\202\255V\313<\240\324\021\274\'\3463<\353\227h\274\036mq\271.\325\257\207\275\340\230\233\273!\314<=\342\021\336\274U\016\374\24654>0dY>rn\270\275\t\022\313\275\307\372R=\305\324\357\275\210\223\027\276\215\325;\2745\023\231\274.(\003<`\253u\270gT\364<\361\246\262\273t\322\330\274\201\203\322\274\374\360\217\273Y \014;]\251\225<`\271\323;\223\315R4\247\261;\031\254A\274q\023\007=Z\243\244<\243x\307<\371\232\326\274L^\204=\337\256R<\254-\202=\314\200G=\237\213\231\274\370\025\036;\232\312\005;\315\364\232;\356\260\031\275\356\302\233<\247\t\325\273\224\374\374\226\274\265\251O<\031b$<\370\274\262;4+/\273\300Z\230\273W}\201\272+\r\036\265\274\204\240\001\274\257\023\372:\242\311\333\273\276\250\000\0008\323\000\000\215m\000\000[)\000\200\035\206\000\200\373\234\000\000m\312\000\000\245y\000\200\242\316\000\000\207\302\222<[\273\r\274\256\343\353;\365\371\347;\371\314r\274f\234\344\274\346\251\311;q\225\362\273+|\242\273\344$\347\274\336,\303\274\264\000\203\274\247\217\006\275\234\235\t\275n\217*\275\306\255\314\274\237.\320\274i\241\363\274\364\235\223\273\334!+\274\272\364\026;\020\333\307;{)\230\274\331\206\037\273\335p\223\273\372\310\346\272b\"+<\177D\000\2000\231\000\200m\312\000\000\253\177\000\200O\255\000\200f\213\000\000\005\215\000\200\020\260\000\000\314h\000\000\240\260\344;\nR$;\036Vg<\014\262\013<\257\351\021\274y\014=\273\235\206g;\333\365\036\274+J\276\272\233\350\243\274dl\006\275\021\001\274\274\236\035\2608\356\270w\273\325T\n\275\227s\270\272\3751S;\322\364\206;\220w.=O\252/=\016\304\"=Y\003\000=\004\210#:\272\300\234=~\311\315<\265\232\275=\004\027\327=\360t\030<]\274\206<\300;%<\n\364l\2747\3319\274F\305\213\274\336,\375\272\232\321G\272W\240\201\274%\226\256\273-\230\232\272X\0067<\200\362\227\274\004\270\275<\241\033\241<\272\311\225\272\342\2442\274\240\020\303:\267\001K\274y\331\325\273S\373)\2734\274\224\273\374Z\004\274eS\224;\202\267\306;B\233\344;v\310=9\2110E\274\222\335]\274\272\226y\274b\256~\2747y\212<\205\325\321\273\274B\031\274\332\307\272:\202q/\273f\233\022\274\330%_\273h\242\332;\307V\325;\006YS\272A\016 <\205}P\275\334(9\272\026ut;\307\303\377;\364k\031;M\373\211;\255%\227\272\004H`\273\3179\353;\325\217?\275\302-\022\274q\312\3068X \302;\312o\266\275z\333i\274\225_\231\2752\331d\275\345n\227\275\271[\267\275tp\037\274\201\254\031;\366\221\022;ur\235<\347\261\200<%\263\232<\325\321\265<\201\241\206=\000\275\037=\022\332\271\273o\024\341<)m\357<-\275$\274I\240\303;Ih\262<`\250\204\272\242\254\267<5h\325=M\200\033=\326f!<`\352H=\036\330\236\312\270=\370\006\213\274\0170\354\273;\216\'<)\353\200\274w\321,\275K\340\256\273\032\001m\273\010\241\314\274>\0019=\005nL\273\3714=;\356\320\244<\014(\344\274\333\214g\274H\030~\274\340\235\374\274\005\353\326;?\234\351\274\352\202\002\274\214\'@\274\213j\r\273\332G\270;\275\t9B\237\030\264\005=J#\230;J\035O=\\\332\323<>\347j\274\205\251\210;\216\303u\2722\310\007\275\n\007\301\273\035(\232\274\367Q>\273\205w\311<\365\212(\274Zk\236\274\323.\013=\360\335\342<;Ww\275\342\014r=\351r\037\275\346ND;!\226-=\'`s\275\320>\2379\244ng\273\305s\021<\271\036\331\274\325\336\212=\317\205\227\274\204\216N;\234V\243<\357sz<(-\000\200\254\236\000\200\304\260\000\200\350\001\000\000\036\216\000\200\275G\000\000\013s\000\000\271q\000\000\327\317\000\000\310\350^\246E\006=W\225m\274\263^\265<.\377\262\274\n\242\000\000F(\000\000\2205\000\000\013\307\000\200\300\322\000\200:\310\000\200\355\267\000\200\010\236\000\200\262\256\000\000\214|6<\264\372&\274T\225p\272\n4\353\272\003\345\014;\242a\206;\235%{:\307\250\217\273\261\327\273;\370\r\200;y\333\355\273\240\375\200\274\010\030 <\357\262\273=\331\035\027<\032\030\315;\200\355]\342\276\202=\177\367\t\274\\IE=\304\315\205\272RVx\2745=\311\274\364\005\303\274m:\255\274d\273|\272\255] \274\306K\007\274\272_\217\274z\343\332\273\352\2270\275\374%n\275U\215\352\274^\264\213\273\351\003.>l\245\242<\036\264J\275@2~\275\337\322\204\275\027\217!;\006\004}<\336\200\271\214Q<\211\030\303<\341Q\007\2756\257\215:\346\256K\274\235\355\200\275y\022#>\027\214\'\274\222\3644\275Ky\026=\023\364\036\274K\265\003\274J\366O;\001\330\2669\377]\205\274!\375\235;\262c\013<#\336\315;\312;Z\274\017\225G\274\230\0227\032\026\235<\0100\331\274\023DG=,\307\032\274\323V\323;yv:\274f\327d\234:\217\310\000\200\373\310\000\200\364\005\000\000\320\320\000\000tM\000\200v\233\000\000\0058\000\000\265n\000\200\316\254\000\200\030\006\036=:N\241<\272#\244\021\224<\370z\027<\242FS<,8\255<\252\363\002:y0w<\240j\320<8\322\253;\3271\342\273\275\3579;I\000\304;@\367\216;p\316\347;)Z<\274_\303\022\274\t\217~\273\244%\007\275\204Q\224\274\226\363\027\275\336\277\275\274k\217\001\274.\337\256\273$\024\000\200\270R\000\200\023l\000\000\214\314\000\200\301V\000\000\324q\000\200\202\243\000\000\357\234\000\200\007r\000\200\244\255\236\274|\\h\274V\333\202\274u\335+\272\305\302\233\274J\372;<_]\303<\021\317\334:^\367\226;\244\352T\274\306\256\305;\317\245\3068s\263\360;\260\250k\274\201\302&:\363R\317\273\210\200\225;\340\260\274;,/\241;\316\337#\275\2471\216\274\3179\026\275\033\317\223\274Qk\270\274\023ld<\230\261\217;\314\024k\274\013\206\375;\302\\O\274o\000\216\273`\337\337<\203J\210\275D\313l\273\273\330\200;r\004\274\274\254\264\025\274b*\343\274\372\274[\273\205\217\262\274\033e\003\273bx\013\275\226\\i\274e\036\265\274{\342\276\273\316\350\337\274=}M\266\274\026q\220:\006\"\220;Nr\304;F\033\001<.\306\001:\016}\204\273T\245\223\274+\350\252\273\230C\000=\202-\266\273\025\200\271:c\306\2219\r\254\334\272\334G\214\274\326g\251:\225#?\274\277\336\273\273\365\313\212<\201\316a\274\222\245\343\273\004\256B<\365?\267\274!\303\004<\025}\t=\212\316\263<\256\231\226<\373\007!=\3672\245<\2228\005<[\307\371<@\031\262<;\226\321\273K\007\260\274G\347\023\275u\034\334\273\2505\210<\335\321/<\302\020\003\275\326\332\222\274\027\336\230\274\002\255><\255\252\010>\364\2767=\306o:=\253\355F>\325\356\321=\241\242B=\360\332%>\016Hs=\355(\n;R\315\266;?p-\274\266K\007\275G9\304\274\251\025\2209\354|\230\273T\2510<\\\255\251;T\340\003\275\030\220\214\274i\342\000\275\351\004=\274F[\336V\200\351=\302\365\3170=\354\237\217=f\341{=q\334\331<\202N\306<\2262\343\212\343\273\213\211\266<\035\324\225:\324r\013=Z\272\\<\217gv<\'\274H;Q\377\340<\261\261\024=^n)\274\354z\203\273s\267\200;G\037\234;\311\302\350<\271\232\364\272\267\332|;\354h\363\272\307\014\307\273a\333\276\273K/\370\272h\327A\273\242\035R;*t\000\274_i\256\273\214:\033\273\270\271w\273\316\306Z\273\352\032\000\200\007\313\000\000^X\000\000g\212\000\200%\031\000\000\262>\000\200\354\217\000\200<\273\000\000P\213\000\200\323\340\336<\206x|\274#k\312<\217\212s\274D\310\013\276Q\240\306\275v\336\014\274\212\001\236\275\261r>\274\237\254\000\000/)\000\2006}\000\000Z-\000\000\347\024\000\200^\313\000\200u$\000\2006\2758\361\034\275\227\320?\274\357qi\275\277\004\010\2756\353\230\272\036\351\212\273\023\252A\273\2461w;]G\350\272f\3441;\375\2644\2733\277\277:\227E\311:d\364\026\274\376 >\274\335\0055\274%:\026\273\000\362\250\274cz\314\273\331\340\367\273\'b\224\274\317.\216\272\340\"\224\274\',\213\267;\021%[<\232\376B<\335\214\216\274\257\341 <\351mQ\274\1776\367\273\360\025\"=\263\211\010\275\216\323\322<|\365\302=3\232\222\274P\246>\274I\021W\274\324\\\301\275\241\0230\274\222e);\341\024\367;\270o\233\274|\366\324\274\212l&\273\\\235\376\273\271\244\027\275N\027\022\273\007\346\250;\363G\366\273qX\267\274\027\307\276\274\362\202\224<5\324\325\272#\321\302\274\375J%\2740r\261<\304_\004\274N\251\271:\037\213\300<$\237\220\274\260\rI\274Z4\311\273e\212\n=Eo\276\274\240\231\270\272B\265\254=B\260,\274\001\207\234\274\237\225\236\272-\264\325\275t\313\316\272\363mF\274`\300e\274O.\234<\303\333\236\274\200\020W\273\310uV\273\213\020\036\274\327\225`\274\263#\206\274aDY\274\0237\215\274\300\032#\274:-q\273Gk=:\217\355\203\273\003\307}<9\234\216\273\377\352\017\274Q\032\375;\201\027\262\274\274\033/:\206\244\203\314\274\374\344z\273\345\005\376\274\367\325b=\037\254\256\274\243S\257\274\3533\364<\2271\005=\233R?=m]\006=\375\303!\274\265mL=G[i\362\273SE\374\274l\017H\275\273KC\271\355E\000\200\235|\000\000\222z\000\200(\005\000\200\346E\000\000Q\315\000\000\003\250\000\000\2048\000\200n\314\000\000\203n\010\275\022\360\326\274H\234\216;g\240\017\275\373%\261\273\2024*\274Nd\220\313\236\221<\272\230\n\275K\317\204\272\354,\217<\'\251\\\274_1M=\220\024~=X[>=\263eG\276\215\';=x\000\274=yZt<\227\353\034\275\205Gj;\225\231\215\273\004\300\000\275\260h\2153\237\211\275)+\020\274\202\360\277\275!\324\225\274\357\232\300;\262\273\177\274K\234\214\274Et(\275\225\356\020=\340\2768\275X$\377\274\335\222\234\2753\307\032\275\036J\327\273b\360\253=\305\036\364\273\342\273\017=\354\365G\276\203G\002=\276\016\007=&a8=\225I\212<\330P\276\274\346\232V<\2143F:r\003Q\274ZA.;\377T\211\274\332\336;\274~\010\360;C\250\377;B\266\n\274\244\332Z<\222a\343<\"\340o<~\274\241\275\274\374\216\273\331\267?=r[\271:~\314\365\274\331\337N<\035Q]\273\354\214\004<\177\037\026\272\312\355\361\274\367\264\262\274)+y\273\240mX<\271\341$\004\335\t;\3017\024:\271n\'=\314\"\246($\364\274lD%\273\363\314\332\273^=\362\274\341\3372\256\000\000\256\262\000\200)\212\000\200,6|\273U.\031\274\375\006\207:\330\233\377<%3\261\274\001\n\201\274b\245\t\273~\251\353\272\000\201\305\274\026\014\336<\ts\021\2757\364y\3616\215\274\304\204\311;1\354\376:U\216\0248\334\305T\275\004\266\024\000\204\273m\326\275\274\316=Q\275\020.\022\272\321\277y\275zWb\274\016u\036\275\032\236\324\274\022\214\244\273\364\340\004=W+\225\275\276(c\274\354\323\'=\330v\000<\335[\371\274V.M\2740\322O\274\247\312\263<\354\264\036:L\240\336\273\306\2302=\030\202\310<\365w\246<\261\262\321;HC\005=\"\307\352<\265!\243\273\376\272\r\273\206\251\320\273\005\026\027;\027K\033=v\306\244;\256\301d\274\327\321/\274\236bZ\272\274W\351<9\037\301\273\277\306\306\272\327\271\214\300\305,=\311[\300;q\267:==\344\342<\374\254\371;\377N7\274*\017X<\252]\3109\021\331p=\317\326b\274\366\270\265\274\233PB;\307;\311\274h\014*;<\0255\220<#\277\323;\200n\306;$)\225;\270\244#;t@f\273\261v\001<\252\264];m\0364\273\245\255\203<~\217I<\"\336\036\273l\260\223;\227m-\272\2048\214\271Z\374\t\273\351\253K\274\343\3117\271e\2105\274^\237O\274\325\260\203\274\3335^\274%C\222\274\331\370\220\274j\000,\274\013sy\274\002q\220\274\336-\350;ccL\274\354\023\367\274M\362\357\274\001\263\364\274\302/\025\274h7\216\274Ge\021\274\200\344E\273\307E\210\274\003\034#;0\006\275;\220\234\261\274\336v\r\274\305g\000\000c9\000\200\344\255\000\0007\013\000\200\'\007\000\000\262\320\000\000\325\324\000\000\225\005\000\000.Z\000\200:\330f:\366\321\213\273\212\177%\274\245\243<\273\370\340\026;\r\217\377\273\010S\265\273\261\200u;6\025\353\272\001\303\024\274\241\302\275\273\322^9\273v\013\016\273\337N2\274y\007\214;\212\344\"\274\rT\325:8\023\262;i\356\305:\024\010s<\301Fh<\004\367\274<\3304\365;\370\274Q<\n;\220\353\232\274[\374\315\274\300\216\323:\317\210\026<\375\3654S<\001z\325;\246\202v;H\221\014=\2447 \274I\201L<\027\273\002=\367\0135\275\255JB;\266\\\222\273]\211\253<\263\373\306;\377{\302\274%\357\252\273\2314Z\275\2763\325<\322\322P\275\033Te<\344D\270\271\252\035\010\274\245\253\241\274\264\267a=7D\341\274\366q,\274\311b\203\274\364:\001\275\035\210<=uX-\274\272\226\210<\364\002\261\274\257\340\344:a\257\256\273\026\325\200\275v`\202\274\226\211\325\274Wf\r\275z\374\020\275\020\03469k&=<\320\343\220;\021T\207<\201Y\241<-X\212\275\202\242\r=\332rw<\331\016j<\206\252K\222j;\317\270$=w\260\227\257\275\301\271&\274\005\204\\\275\321\026d\275\314\002\025=\352{\357\274b\277\320\274\201VL\275\215\304=\272\243d\316\274\313\365\016\275\020\t\225:\016>t\275\364F\"\273\014\341\312\274\207\311q<\255h\377<\272:\275<_uC\272\177\017<<\021\261\355<`\211\376;P)\000\000J\246\000\000\022\306\000\000.I\000\000\032\256\000\200\364#\000\000P(\000\200\237i\000\200l~\000\200Ol\337;\003X\236<\336\tl\274Qa[<\212\037i\274G>\321\274\223\010\257:u\236s\274\344B\243\273A\263\327\273\256\356\244\2733\366\324<\255S\006=I\0336=E0\341<\001\"\341<\nSR=\334\314\244<\234\037\240;\230|D<\264\207\036<\337\rB:sl\220;D\267\003\275\315\225-N;CR\205\000\253<\371\306h<\254\2641:g\373w<\244X\346;\032\300\231\274\\\004\302;&5\033\274U9F\2745\267`\275+\232\373\274\207\344\366\273\227Q6\275\304=#\275\214\216W=\003\351;=hJ<=\202oI=\007\213\321;\351\326a=\272\360A=\2631\313<\355?\002=\227\207\303;\027\262S\275\253\236\207\274i\312\272\274\242\2438\274\273\335\206\274\276\201D\000\200\345\031\227I\304\276=\001\213`\274s\345\260\274\246TZ\275\364\366\244\275\262\3308\276]\007\331\275;I\2249\013H\004\274?V\313\2740X\222<\010\032\347\274\217#\237\274\321\343X\274\336a\225i\306o=\375\371\017\273NgO\274+\227$\275\201\3333\275\2664\375\275\035s\230\275\325\241o\275\257h\230\275\320\336\225\275\273\340\r\275\200\304J\275\'P\355\274\235M,=\016\361\232=\360V\177=J\236\023\275&\374+\275h\235\000\275q\352\314\272SX\003<\351\265\226;\244\000\327;E|\0169F\233\377;&Bo\274g\037]\275\344\350/\275 \003m\274|\210O\275\240\355\314\274\017\243\314<6-\244=\3572\210=h\352\257\221)=0\257\000\000\243\252\000\000\231\'\000\000\\\033\000\2004\211\000\200\030\306\000\200c\037\000\000a\315\000\000\233\214\000\200#2\220\274\372gb\274<)\320\272A\331\311\274\332E\261\274\024R\032:7\3323=\231\334\271=\357\315\205=\232n\\\274\005c\025\275R\264\377\274/8f\274\324>\021\274\275l\226\273\225\334\322<\255\206t=\262\031==:h\213\274\3209\020\275y\241\024\275|\261\203\27450\024\274\203q\302\273\204\004k\274mp\277;y\355\365\273~\270\000\000$\276\000\000\213o\000\000?\305\000\000~\203\000\000\343\320\000\000$(\000\200\325\215\000\000\216z\000\000\3054#<\256\243\000\274L\005\204\274\352\267\343;\264c\322\274\223\334\313\274.{^<\270\321\350<\262\024\323\256$;\206\215\257<\345[%<)\217A<\3472S=O\010\260<\004x\332\274q\307X\275:\267$\275c*\355;\375\336\200;<\335\333:\0206?;S\337\037=\212M\345<\214\372\270<{s?\274B\307\230:\rO\245<5\332\277\274qV\302\273+\352\224<_9\032=\301g\320<\305b\351\273%.\351<\370w\274pr\274\010\361e\273^\t\362;\376e\326<\313\264\324<\r\216}\274y]\243\274o\257\340\274\301\274\261\274\231\232\025\274\225\210\n\273\235\262\337<\036\332\3248=\315=\023\373+\274\230\317\006\274\277\366u\275`\347m\275\202)/\276M\203\372\275G\300\310<\337U\316\273U\313\225\272\252_o\274\367a\234\2756\276\340;[\371\240\271\035\032D=\373\356\227<\221\363\"=iSb=cCY=\356\243o<\342\272\235\273z\312$<1<+\274\341\375\006\275\326\205|\274Y\267\212\274-\270y\275\217e\201\275\3433\230\274\n[5\275t\2127\274X<\246<\300\014\311=\237DC=\034+\373\274\013\2231\275\177\000\257\274\210N\031\275=\300e<\032\005!\274\000\324\005=\300\331\265=9O =8k\266<\374\376\313\275 \312\273\275r\302\203=\362\312\243\275\006\020\003\276\304\220\013>\006r\207=_!\021=\235X\230;z\242\006\275\220\201\033\275.\241\373<4Kf=\246\330\270\272~n\277<\333a\t<0\000\365;fJ\"\275q\324\315\274\340-\213\000\000G\237\000\200\200\007\000\200\031<\342\216\340<\006\241\347\272xM\335<\272\225\342<.V\n<\266\232*\346\250=\0343\250\2740\031}<\232\030\3009Z\006\261<\031\000\253=\t\242\355<\024\370\361\273\311\204-=\013\254q\274\345\364N<\202\344\341\273\355\376b\275\335\245\226=\037\330o=\n*\266\2752\224\206\274\244\202\000\200\340\254\000\200\366\324\000\000\310\025\000\200\036\315\000\200\226F\000\000\347R\000\000To\000\200ZW\000\200\010:J=E`\362\274\361\217\017<\351\367\035<\213i\312\275\217\031\214\272\247u<;\376\000\022;\256\347\232<\222\234\326<\023A\010=\335\355\247\274\236\0331\274\351Z\205\272\323\341;\275\311;\223=\357\316C=\315\257f\275\205\r\374\274\021\334\243\274\367+}\337}\231=z\211\262=`^\201\274\3641\t\275\221Jb\274\340\336\353<>\303N=~\326\375;t\006\"<\331\347\005\275\222\337T\274\375%\370\273\023o\265\274\206)T\274\267\216\231\273\216\341\232\274\'\334\037\251\275<\007\273\023<.\266\252\273W)Y\272$W#<~\010\264\273\016rS<\304\261|\371\307;\273\3762<\3715\026=1O\261<\021K\211\273\366\375\257\2745\224\220;\236\n\304\274|\376\216\274\317\032\262\274\263\203\227\274\323Q\245\274T\365?\274\021b\334\274f{\213\274\024\264\356\274\2640\244\274\274v\004=X!\237\273\341!\n\275%=\"\2753\314\302\274\007\025\302<\363\026\013\274\344\017g<=t\225\274\300T\030\275\347\014\343\273\243\025\000;.\371\355\272\022?\260<\035\253\000\200\251\264\000\200\024\270\000\000\246\267\000\000\317{\000\200\330W\000\200\374\213\000\000\230\267\000\000\376u\000\000\311\001\010\273\017g\022\274\306\265\232\271:\n\206\273\366\016\002;^\027k\273\241\336\025\274\356\316\033\274\312\335\203\274\266\237\276\000\000\316S\000\000\'\010r=<\321|=\305\014w=\030>z=d;\300=\036d\255=\266\252,=R\024\204=\331(\255=|\246\257<9\340\021\274\252\302\312\274\311\302\223;\220\206,=\264\020\365\261\275o\233\030\276\314d\312\275\004\362D\275v[\302\275,y-\275\034t5<\221!\235\273p\251a\274\374Y\235\272\231\276,:4\252\007<\016\214\023\2740\013\312<\211V\360;\371\214\361;6\236\002<\250V\n\272\264\'`\2738\204\n<\355\254\210\272\314\245\036<\245T\022<5f\355;:Y<<\2659\251<-S\235<\327\004|<\025\340\235<\363\023\t\340\212\273u\242\341;u\221P\275\361\243\202\275>\256Y\275\277U\203\275\235H\302=\320\223m\275\325\300}\275&\331Y\275[\322\200\275\014U\222\2751\r\261\274\354jO\275\031\357\327\274\027\227\331=\227\252q\274./\202\275\375\265\322\2742Iu\275\216\266\005\275\246Z\353\273\350\221\231;K\3629\275\305\345Q<\024\345,\275\330,\275\273\252\353\260\274\311-\314\274\371\212\007=Y\243\357\274wSa\273c\t\311\274\032\245\227\275\206`+\275iO\207;\031\032\333\274\2561=\274\366\321~<\374\tK<\352\300r<\242\032\202<\223F2\275(b\350:?\346\016<\205\200\246;\236\203\003<\366$\302\274~\317\344\272h\014);\371P\375:\244\224\031=\207\035\230;\206\365\251;\201~\240<\n\r\246;\010t\263;\314R\370\274\004\230\237;\230\227\004\274V\001\346\275\000\202@\275\272\271\245<\034*!\275\274\322\03695\245\000\200$W\000\200\345l\000\200\307\n\000\200\307\322\000\200\345\007\000\200|P\000\000\355\215\000\000A\312\000\000 \316\226:0%\001\275\205\222r\274\326\257\240\274\241\346h;\002\002\300\274\307jq\273]>\375\274Q\345\310\273&\246=<\256:\355\272\243\376P<\333\332=<\277\024\235\275\224\007\220\274u\037\264;K$\020\274\262\333\277<\035_\244<\366a\0269\027i\263:%\2341\274\254Eh:\276\007\263;\002%F;\262\252b;~s\316;\356\255\226\273*\355K=0\253\004=p\303p=\274vO\275\245\250\231=J\204\256<=\215\016=\371#N\274\272E\237;\335\220(\275h\243\370\272\342d\023\274:\251\231\275\266\021=\275a\233\212<\314\3700\274\216\002M<\326\313\037<\363\262\274\266\3732\220\274\352\334\260:s\375\330;\226\274(\274hz\216\274\267\307\223\274\025\374\317<\253\222\032<\204\326\255:\021E\006=\035U\325\274\177X\243\275\317I\002\272\254\355\000<^\270\275\2745\207h<\262\247i\274\226\314c;\365j\230<\037}\205\2748\030\220\2730\334{\274\004\224\317;\201\014\000\274Rn\272\273\001\033]\271\201\353\334\274\037O\231\273>K\327\274Q6\241\275\361i\020\275\010\204\351\273*\324\253\274)R9\274\352\254\345;\236\3020=\330\356\222<\273\000\373?%\270U{#\273s\266\203<\337j\013;J\372H\274l\345\234\273\221h\002<\337\341\t<\202!=\t\274\352\222\022\274\247A\227=\025\000\"=\307ET=I\020\000=\305\201\264\275\377u\021=\202g\007=\257\246\264<\237=l=\256\361\013<\014}>\274\023#\256<\231\366\261\274\201\016\347\2751~\025\275ivy<\337\356\343\274\236\332\333<\2020#j:\300k\260\274\341`\246<\2248n\274\032h\302;J\221(\274%\377\311\273\264\235\377\273\224*\215\274\246\306\300\274\373\227-\274N\355\021\274~u\236\274$-0<)\233\325<_\314=<\3739\303<\037\\\013<\026\327\0009\224+\003;%\343Q\333\353\273M\366\346;\311\272w<\332X\264\273\230J$;\213tZ\233x\275tR\232\274\231\363#;\177\036d\275\222#G\274\327\241D\273N\250\300<\032\363\014<\301\245v\274\001\304\266\274\324\371\331\274D3}\273|\374\305<,\233(\272h\365\273\274\354\210X<\323\350h=`\375\240\274\n\273\271<\n\241L\274Pr@=\\\335\236\274\251\354(=\326q\211\274Xg\215\275\205K\264\274~7\335\2749E\232\274\r\226\264=\'\227a<\272\364\277\274\321\372\256<\265\272p\275\230y\007<\336\202\232;\225}n<3\213h<\310\005\010\275C\211\006=\307\025s<\333\354\337<\232|\000<\277\354#=\177\304\203\274\014\245\2159\302\377\246;\305\361S\275\000\216\204\2743\265\020\274\252\253\312\273_\345\033=\"\000<\274\010\354V\2746\013+\274\366\366n\274\257\200\241;\233\364\332\274;\371\213:\3250\257\274D\021\240\274\355\374\343;\212\256M=\201J\\;\361J\273;\265\016b\272HZ\251\274C\263p\274\263-\031\273\320\3503\275O\366x;\244\000\250<\200\177\362;\013:\230<\301\375\235<\3104\205<4\330\312\273\372\2529;.\016\003\274y\240\023=\230\316\220;W\"\211\273\0009\355<.Y{\273\024\361\260:\276\314\324<\rC\200<<^{\273\312\013\203<\201\220\n\274\177\264q<\224\035B;=\237\252\273\344a\212\274\017\007\013\275\251\311\235<\234_\256;\332h\260:\206\365\234<\216y\240:\037n\307;\177\n\241\273E.+;\333\242G\274\nH\225\272$|#\274\237\246\024=\315\000\365\273\377R\366\274J\255P;d3\235\274 \327\200\273\313\324\034<\017\373\332;\314\370\032<\352&\264\273.\332$\274j\025E;=Q\351\274N\317\0179%\r\233<\246\325v\274\375\270\207;\356\340\353\274\"\235\244\272\223\020;\274\371\331\343\274\025^\355\272$<\233<\371\0312<44J<\336u\002\273\343\264\023\274>\236\212\273\361w\300\273\362\316$\274\177#\313\273\353\210\021<\030D;;f\034\263;D\010P;Z\001\034\274hy\336:\2470\331\272\217f\332;\317u\221;$\2408\274\274\353P\274b\246\315\274\225\256\212\272\326\354\236;\267\322\342\272\300\302:<\361\331B<\252\026i<.\007\370;Nw\233\274\016 \301;\3531\212<8\027\317;\034\320/<\327/\013<,\216\216=\027\031t<[ZB;L\351\264;\362\372#\273\222>z;_G\3459\247\236\333\273*\032 \274\360H\374\273G\3735\274<2}\274\255w\007\273\357\3130;\203\346\r<$I\267;[\236=\273\312\332h;\0325\252\274\022X\027\275\262\357\305\274\013R\306<\361g\251;\247o@<\202\257\232;\335\372\247<\323\226X<\241\274\036\274j*B;,:\260\273\026\233\000\274\230\270\254:i\225\016\274\233\217<\274\365\337K\273}}-:\320\356\320\273\262\327\006;2A\206\273\235\224\357;\016k\375:\006\321\017<\021s\327;&\340\346;p\033\212\272l\326\240\273#\217\345\273\343\304\000\200<\314\000\200\005\311\000\200?|\000\200\323*\000\000\320\004\000\200\301\274\000\200\022\311\000\000z_\000\200\3237\037;%q\001=\367\322\371<\2221O<\226\233\233\274\014(\013<\025\237\252\274{\315\215<\323\374^<\250\226\000\000\354\321\000\200\207\323\000\200~\214\000\200l\262\000\200\237t\000\000\336\271\000\200Vj\000\200\264\206\000\000\001kj\273\313\306t\275\226\3741\274\334\2448\274\240L5\2757}\274\2736\354\332<\226\306\212<\030\251\215\275WA5\274\373\014\215\275\351\205<\275\033v\'\275j\035>\275L\330\376\273O\240\270:\315B\003\275/\247\226;\273LL;\357|p\274\327X\266;\037\2660:\317[\223\273\241\313\273\274\003\372\005\3702\273o\366d\274]\216L\273\310\t\212<\3774:\274g\244l\274\226\236\330\273|:r\273\030\177\377\273\253\024\031\275\326]\r\2743T\226<\345\241\233;\217DF<\000\257I<\352t\307;Q\314}<\000qC\274\350\334\226\274\275\232\205<\t\352\007\274\254\rU\274#\361\262\273L\216\000\274\004\315O\274\243/\227\274\306#\021\275?E\320:<\007\035\275m\303\350\2744\276v=\215U\224\273\304\343x\274P\3152=\'\256\234\274\250e,<\326\242\360;|\253\211<\341\250\211:0\315\263\274\305\2731:\221\025-:\016j8\274\230J\004\273\336\2209\274\t>\211\274B\3061\274\216\262W\2736O/;\370\357\345\273\253l#<\226\335:\274\004\325\236\273V\341g\273=\314\302<\tG\006=\367\030A<\205\350\361\273\356`\023=\361\302I\274\313\304\252\274\362\344><\302\322\265\274\234gr;\240\261L<7zf<\240\267\226\274\233\245\"=\202&\034\2741\322\r\274\177\340T=\266\225\024\274|g\331:\337\311\204\274\314E\023\274.a\241;8\235\013\272;\225\375\274\234\260\223\274\267q\002\275\033\247\361\273\307\377\003<\355\214q<\374\217\263\274X\260\370;\njY\274\321\007.\272\271\366\2779\034\034\250\273Z\216\310;6/W\274\0107\216\274BAd<\346\3628\274c\"\004;\317\006\303\274\255\306\311:\302\nu<\347\014\262\274\315c\335\271\372X\203\272\265\301\005\274\337\261h\304:\313l\201:ibn:\360\231g\273}F:<\332\272\365\273\300\234\246;\231\210\256;\006\002\020;H\001\202<+\311\326<\256m^;\210\335\241<+\303/<\321\350\225\274\252\016\222\273%\316\034;\237\340c\271\347#\253\274\266H{\273\2054\t\274\242\264\253\273\013%\2219\267\200\000\000\247\305\000\000=\323\000\000\304\306\000\000J\n\000\200w4\000\000\025\314\000\200h6\000\200\032\322\000\000{\032\262\274=c\305:6;5\274\324\232S<0,\353;5N\364:t\335\216:\372\306E<\006\257\245\274\307\211\000\200(\216\000\000\353n\000\200\314j\000\200\223l\000\200\307\225\000\200Y\211\000\200\263\314\000\000\376\321\000\000\332W\213\275\360\373\214\274\035>v\275W\275[\275\371\'\242=\263\r\037\242\275L\002\200\275xKZr\000\200\3279\000\200\317\255\000\000\215\275\000\000\264\032\000\000qk\000\000\017\304\n\274{*\322\273bL\016\274\352\217\267\273\263\337R;\274\316\236\273|\334\016<=\017i<\365\001\236;c\254\315;\377\242\362;\214\003\245\272I\021m\273g5\321\273\353b\313;\351\207\310\273\002I-\272\034t\225<\002x\220\273\007\"A\273t)l<\177I\350:\324\347j\274\357\214n\274>\200\202\2748\252\344\273\206\032\266<7\216\205\273\267Q\'\274p3)\274\027\332\273\273\341u\321\273Z3\255\273\202\206r;\272W\n\274\213\347\327\274mn\200;\2212\"\274<4\270;\303\336\222<\334\010\000\200\314\216\000\200x\302\000\000u\317\000\000W7\000\000\313\314\000\000i\237\000\200\3166\000\000\201E\000\000\306e\240<\267\234\370\037\272\032\373\204<\340d\244;#\3371<\327\225`<\177\353\030\274/\375\":Ql@<\031\206E;\361\322\216\2749\214\213<\347NG\355\272\313\000\356;\372\357\014\272R\332d\274-5\205\273\007\247 \274\234\246c\274\331@w\274%\236/\274\356P\253\274\230\351\'\2735c7\274@\233-\274{\032\372<\323\300\233\237\271\274O\231\213\274kJ1;\033\2166\274\024i\375\273%\205\237;\324\233\020:|J\226\274\356\024\322:\270\n\022<\023@G\2711\364I;_A\003\274\222\2444\nF\273\270\256*\274~vS\274\027\247\207\273\321\2610\274\014H\\;\000.\024\271\177]\266\227\204<\324qt<\271\336\022<\2271\360\273\336\316C\272I\030\001\274Q\r\352;\205p\252<\357\004\232<\260#\262;\375O\271<\246\301\336;\336i9\336\231\273\r\210\311\273j\236\n\274o\367\350;U\230\347<\316&\205:\204\323\260\340\274C|T\274<\273r;\352\010Q\274\253ef\274\234\210\014;1\3658\274\374\233\216\274`PO\274a\036\351\274QD\304\274\004(\237\274z\034\375\274\221\310c\272\036\326 ;\373\231\340:.eh:\261\273\350:w\314\3479\252f\231\272\272\273\212;\201\204B;\004\014\207;\037J\375:a\202\231<\376\0204;\207\370\016\000\200\251\307\000\200\301L\000\000\314\240\000\200\337g\000\000r~\000\200\305\200\000\200I\t\000\000\264w\000\000E)\000\000#\304\000\200\262\007\000\000 \212\000\200\314\273\000\200\312r\000\200\321m\000\000\252Y\000\200\241X\000\200\006\031\000\200:\317\000\200KR\000\000\002\273\000\000 \013\000\200\323;\000\000\023\204\000\000\305\273\000\000\263R\000\000\202)\000\000wc\000\200\'\234\000\2002\253\000\000\024\235\000\200\362\271\000\000n\273\000\000\036\264\000\000-U\000\200\341\310\000\200\300<\000\000\273\230\000\000\273!\000\000^\216\000\200\226\277\177\212%\225\326\214n\301\000\000\247X\000\000\017\005\000\200\321\220\000\000(\'\000\200\326q\000\000\305\304+\211\325\250\000\000\357\\\000\000\022q\000\200y\223\000\000\233s\000\200\353\223\000\000\3632\000\000?\214\000\200\013\276\000\200G\035\000\200\246\240\000\200\007z\000\200\3742\000\0000H\000\000\001\303\000\000\256y\000\200 \013\000\000\342\256\000\000\343\023\000\000JK\000\200\312\034\000\000r\035\000\000\312M\000\200WW\316&\253z\000\200$\200\000\200\351!g\203\354\177\000\200\023%\000\000\244\273\000\000(\030\000\200\265\277\r\200\214t\000\200b\250\000\000\372)\000\000\270c\000\200\2550\000\000\002\225\000\200\372\014\000\000\365u\000\200Y\301\000\000\364\353\023\226\371\222\000\000\017V\000\000{\366\215\214\211+\000\200\235\\\000\200x\246\000\000\307\r\000\200\373\027\000\200i\274\000\200V#\000\000\034\030\000\000\202N\204\2171\311\000\2006\247\000\000Or\000\200P\270\000\200\350\221\000\000\204\252\000\000\0173\000\200W\256\000\000`\272\000\200x\264\000\200Aw\000\200\375y\000\200\032\303\000\000\312\302\000\200\026a\000\000\307\246\000\200{\032\000\000\251c\000\200\347M\000\000\331\277\000\0006F\000\200ow\000\000\214\031\000\200\316\225\000\000s\233\000\200{L\000\000\245g\000\0009\300\000\000\323,\000\200\217\262\000\000\256\363\004\003k\231\366\200H\237\000\000\206%B\t7\246\320\rKt\030\206\214\306\000\200w\207\000\000\272u\000\200\177U\000\000\254*\000\200\221\254\000\000\242\017\000\200VF\000\000\232J\000\000\333)\000\000\004\317\000\000\037o\000\000\222l\000\200\203E\000\000H\031\000\200p\026\000\200\306\n\000\200a\211\000\000\221!\000\000\024\377\001\200\213\002\000\200\356\224\000\200\272\220\000\211\003\264\010\035\302d\000\200\222\234\\\013\303\201\247\216a\330\027\014\020\262\000\200\365\016\000\000Cu\000\200\032G\000\200\227\003\000\000\243\211\000\200~K\000\000X\276\000\000\256\304\000\200q\000\000\000?u\000\000\246\032\000\000\372g\000\000,#\000\000\372\247\000\000 \014\000\200\005\271\000\000g|\000\000\270\231\000\000\240\267\000\000\372k\000\200Q\205\000\200\207%\000\200d{\000\000\3365\000\200m\234\000\200Q2\000\200\021j\000\200\372\270\000\200vf\000\000\321\211\000\000\301\306\000\200.\266\000\000`8\000\200h\306\000\000\366\027\000\000[g\000\200\217\006\000\200\207j\000\000h\002\000\200\240\007\000\000\357\036\000\200\366F\000\200\016\274\000\200\253|\000\200\325>\000\200\000\016\000\000*a\000\000Th\000\000\213\037\000\000\370K\000\000\310\256\000\200\231-\000\000\360\262\000\000,\023\000\200\201\t\002\200\301N\000\000\215j\000\200V@\000\2005\224\000\200\034[\000\200\342\233\000\0008\006\000\000\235\235\000\000\2053\000\000nt\000\200\350\004\000\200 D\000\200A\303\000\200~L\000\000\225\375\001\200\355\005\000\200\324Q\000\200\346\227\000\000Y\316\000\200\\-\000\200\242N\000\200\206d\000\200\316Z\000\000\267,\000\200&\205\000\200\264\243\000\200\336\252\000\200\317^\000\200(&\000\000mW\000\000\220\003\000\000J\301\000\000\'Y\000\200\252[\000\200\243\\\000\000x\267\000\000\033\\\000\200\372g\272\000{\267\000\200B\221\000\200\373\274\000\000\322\016\000\200\334k\335\2375\036\000\200a5\000\000\217w\000\000\001f\000\200\217\007\000\000\201`\000\200jf\000\000\324\213\000\200%%\000\000x\230\000\200WL\000\200G\207\000\200E\275\352\205\313\201\000\200k+\000\000\256>\000\200;\220\000\200#\210\000\200)U\000\000;\034\000\200\375?\000\000\353\232\000\000\210\013\000\000JB\000\000;\271\000\000[\256\000\200a7\000\200\357\032\000\000\003\036\000\000z\244\000\2008\236\000\200\267\034\000\000\252\r\000\000\355\223- B\370\301\214\036\277\000\000\201\252\000\200 \216\000\200\375\213\000\000\361i\000\000\370_\000\200\007\"\000\000\265\037\000\200\334\220\000\200*\266\000\200\332#\000\000N=\000\200\274[\000\200\005\203\000\200\224W\000\000u\r\000\200l\320\000\000\026\225\000\000\325g\000\200[\232\000\200i\202\000\000\316\264\000\000Q\306\000\200W+\000\000h$\000\000\311\234\000\200CJ\000\2003\273\000\200\342 \000\200\2109\000\000\337\264\000\200\022\276\000\200!S\000\000\274\036\000\200\322-\000\200Bt\000\200\327\221\000\000\320V\000\000\0200\000\200\\yC\200Q\273\000\200\324\"\000\000\2206\000\200lu\000\000EX\000\200K&\000\000H\232\000\000o\253\000\200FO\000\000\345M\000\000\334u\000\200A\224\000\200\023\207\000\000\252\225\000\000\260_\000\000\364\256\000\200X\224\000\200\351\207\000\000\016\031\000\200\017)\000\200\223i\000\200\230I\000\000=n\000\000]v\267\213\302\275i\237N\201\000\000%\036\000\200F\237\000\200\337I\240&3P\000\0001J\000\000\227q\206\"\2568\000\200+&\000\200\370\272\000\200\320\253\000\000UW\000\000%\265\000\200\217\307\000\000\3778\000\200j\255\000\000\r\213\000\000B5\000\200\275\211\000\200\252\306\000\200I\246\000\000\362u\000\200\"\262\000\200P?\000\200\205\315\000\200Ry\000\000\204t\000\200\033\212\000\000Z\010\000\200\251\202\000\000\036\023\000\000r\253\000\200\031M\000\000\301\214\000\200{\232\000\200\315\275\000\200\335\002\000\000f\301\000\200\031\206\000\000\210\253\000\200\357M\000\200&\276\000\000BV\000\200\354\252\000\200Iy\000\200\245t\000\200j5\000\000\273\275\000\200\023E\000\200\346+\000\200\271J\000\200L\023\000\000\207\027\000\000\275B\000\000.\022\000\000\037L\000\200\303=\000\000~O\000\200\253\022\000\0007!\000\200\001b\000\200\374\207\000\000\340\007\000\000\241\304\000\200\005K\000\000\276h\000\200\\}\000\200t\206\000\200\325#\000\000vx\000\200A\034\000\200\031\267\000\200\233Y\000\000\334\205\000\000\365\303\000\000\213=\000\200rw\000\000\363u\000\200\025r\000\000ty\000\000\351\321\000\000\355S\000\200M\310\000\000|\273\000\000\003T\000\200\024\214\000\000]\'\000\200.\313\000\000\"\261\000\200\202\005\000\0005\255\000\200\363h9\000\330:\000\200L\\\000\200\322\245\000\200\222P\000\200\314D\000\200K\006\000\200\330\307\000\000H?\000\200X\311\000\000\253\305\000\200=\032\000\200\nR\000\000V$\000\200\350Z\000\000\310\362X\200\207Q\001\206rG\000\200$\010\000\200\250$\000\200h\262\000\000k\233\000\000R\204\000\200c@\000\200z\274\233\r\027\265\243\200\365A\000\200\005>r\236rm\376\234\265\343\020\206\300X\363\217&el\021\253\241\203\001\022>\000\200\243\210\000\200\271\250\000\2009B\000\0001\221\000\200\352n\301\216\3717\000\000$\\\000\200\000\263\035\221\"`\000\200\377\303\000\000gu\000\000\356i\000\000T\013\000\200H\211\000\000$\022\000\200$\260\000\200\372b\000\200\256H\000\200\206\261\000\200\204r\000\000u\2736\221\3048\000\000/c\000\200v_\237!\021\205\000\000\013\262\000\200\263\365\302\274\346\362g\273,w\346\273\310VQ;?M\240<\245\200\005=\177\375D\273\312\021\216<\317\243i<\356\275\244;k~s<\246\027(<\332s\231<~\020\201<\2469\016=@u.<\016\204\365<6\355\210<\365\354j\274\341c7\274\226\373\032\274/\2501\274o\2035\274N>z\274V\002\250\274\2712\253\274\205\272\276\274]_\276;\276\236r<\313\373\033<\307O\251\273\034P/<\275}\232\272Y\255\'<(\326\026<\227\251\207\273\361\2738\271\345\253\004\274\206\332\"\274\367\026\203\274\250h\035\274*\227\301\274\272:\031\274G\301\277\273\025\017G\274\337\205(\274|^x\273H\264\307\271\0143:\273\222\2044<\276\0304;7p\245:\301\013\205\273:q|;H\306I\274\245?\210\274\220ye\274\355\255x\274c$\253\274z\000\001\275\366\273\330\272\250\003\230\274+\255\263\274\226|\000\000\310\277\000\000J\236\000\000n9\000\200\373(\000\200\"6\000\200\374&\000\200\325\023\000\200\3165\000\200\363\037\316\273\025h,\274\025a|\274\342K\217\274\302\322s\274\377uT\274-\350g\274K\320\004\274(\306\316\273\362\'\223;\261T2\335\235\274EN5\271T\315 \272:\364\260\274\004\373<\2748\217\331\273S\336\"\275\013\005\320\274\221\211\214\245<\263\023w;d(X<\036U\240<}\311\321\272\242\213\233<\030\250\207`\000\000\230\270\000\000(\230\000\000\217\256\000\000\272\321\000\000\210Z\000\000.\026\000\200\317\275\000\200\265C\000\200s#\'<+\233t<\002\240\237;\200\250k;\340Ve\273\346\343=\273\224\213L;\016D\035;|\322\310;-M:\274^_!\274\272\204\373:\210^\321;\333Q3\272\340\026\323;\321QJ\273C\336\241\274\317/\273\273)\000\372\272@\204\211;L#\276\273\t8\330\272\252U\343:\207o\000\274\300\017\240\274\353\363\020\272\321\323\244\273D;\214;\314\3337<\355\370\r;)Z\022;h\240\223\273l\222\"\274\206\372\237\273\340\2245\274\340\370\217\274q\353\332;C\246\332;\226\207b;LcV;\264\235\223;\3251\035;\213`\330;\2254\244;\254\001];\243\360\016<\325\0059\273>\030\277\273\321uQ\273l9\225\274\336K\007\274\255\222\320\270du3:\254\313\202\273\"\352\246<\361\264\210\024\233\007\033(\246\373\202(\221\320S(\202E\221(g\030E(\n\337P(\003}\207(t\205\303\250\003\000\242\250^\037\335\250U\227\254\250q\277_\247\372\360D\250Q\320\222\250\2159\036\250\302A\276\247\322\365J\250G\226\370&\232\0333(\334\000\225\244O\315\356\'\022\001\237(\350\362\331\247\334\265Z\247}\347\344\'8\270\262\247Gp\230\250\350\273\260\250~2N\247\323\026\033\250O\321\354\246\017\317\247\247\242\3101\250\377\"=\247\200s\272\247/Wb\250\003+\027\250\257\355\304&\254\317\004\247\032C\226\247\216\213\025$HY\235\246\321N\036\247\225\020\301\245\003tI\245\317\322\'\316\027\005\247\021\352\355\246\376\036u\'\365U\025\247\321\255-(\013\335v(\001\033\250\'\257\350\236\',\357\335\'\335\322\252%\242\241\"(\351]3(\211y0(3\325h(\3430\207(z\014~(8\273D(FY\031(2\275\t(T\242h\251\220\216N\251\254b\362\250\331J\264\247$R\267\247\307\375c(\321\221\272\246\022~\206\247}\246\021\247\327L\246\'\207\216_\'?<\273&\320\322\265\'\2225\003(V\204\204\'\251\266\017\247\341,\022\247]{\013\247\212\276\230\247\320\014\214\2475\245\210\246H\003w&\361\001O\247%\262s\'\210\350\315\'\362i\215\')^\251\247i\037\214\247\270\302\202\247yx\000\0005\276\000\000b=\000\200O%\000\200\341\207\000\000\022*\000\200\364\301\000\000\360\213\000\200\250\303\000\200\212G\334\247k\260\020\250\211\333X\247\264\037\304&\0006\232&\235\221\"\'\271\241\245\247\373\3246\250/\241\016\250\220\306\000\2008\215\000\200hH\000\000\r\275\000\200=\320\000\200\2058\000\200\372\303\000\200A\237\000\200y\320\000\000\264L\341\247wM\003\250=\217\246\247\036F\000\250Aj\205\247i\217\276\'\376\252E&\267\250\002(^\263\232(\241\2354&=W9%:\024\252\247llw\'E\036M\'\372\270.\246\301H\205\'\344\364f\'\005?\001(\027\264\244\'\326\374\263\'\371Z\020(\203\004\026(\307\225\027(7\215m(\245\306A(]\014C(\007v_(N\027\224\'q\370\250\'m\312\372\246\356\205)(\212\226Q(\036\300w\'[1\321\'\355B\304\'CW3%}U\310\247u\001\207\'\326\264\017\250\343\230\320\'\232\024\200(\203}a\'w\340\243\250\"\354%\250\005\263C\250\3551\246=x\221l=\234\022\026=!I\n=\014\nZ\274\374\360\363\274\002\352,<\300\325\031\2750\034N\275\366x\355\273Z\237\351\272\311\367\\\273\2604X<\254Tz\001=\361\370\243<\373\311\226<\361\021o\273C5{<\364[0\274\376>)\275_O(\273\005\343\335\271!\0165\274`T><\355\201\207\272\377\307Q<\242\002\023\274o8Q\274\367\334\215<\205\227`\274\211\213\205\274\372wb<\374=\";>\323{<49L<[\372\037:\252\256s;%\276\205\273\277\344|\274\223<(\273uG\343\274\355xw\274\376\321 <\203\342\245\272\372\277Z\274\332j*\274DB\206<\335r\275;\251<,\177\334\272\325\302e\274\001\346\277< \362p<\340\222\311\274OZ\206\274+\211\025\274\0035\227\274g\327\354\273X\2760\273,Tc\273\030\021\377;:\366(<\177\"h\274RF\306\273\004\037\206\270\302/\224\274\340,\311<\023\374\017<\201\"N:\031\025\333<\2729\224<\020\265\000\000o{\000\200\311n\000\200e\305\000\200nw\000\000~\235\000\000\244\256\000\000z\032\000\000\342\313\000\000\275\r\023<{\303\316;\002\0013\271\273\311;\275\217\260\361\274\031\305\234\274\235\314\202\273M\250\202<9\254\244;\027\215\000\200\025\031\000\000y4\000\000\005\005\000\000\224\006\000\000V\305\000\200WR\000\000\031\212\000\200\342\313\000\200\243\373\034=\232)7<}\273L=\014\277Y\273\232} \275It\251<%\333}<2\303\350<\257\202\340;%\300o\274\026a\2058\037\275m\000\370<\364(5=\353\271]:/\300\221=\226\n\202=i\032:\275.\242 \275~\260\306=\01715\276\314\375 ;\217}\217> \363\335\275\361\274M\275\260\330\022>\224\201\247;\361\023\004;\316+)=\325\266\014\275[hg\274\205\254\357<\207\240\003\275\212\016@\273\034\365j=\007\334\036\275QOS\275](\341\274\252, \275\371+\325\275\231\234\262\275*p;\275\204\367p\275\254N\034\275k\231\247\026\227/\274\364\332\321\275\322\373\302=\240\273\001\275\034dl\275\274\326\217\273\213\217\261\274\3615\200:\346\016\346:\037\337j<.\361\354<\210\006\030<\304\367\'\275\027\240\355;)\251\206\273O\375\351\274\306#~\273\311I\020=\256\227\010\274\274\346\206=\327.\n=\266\023\006\275\341\014*;6\235\000\000V\312\000\200\274\320\000\000B4\000\200\233\270\000\200:$\000\000^C\000\200v\266\000\000\375X\000\000\250y\225=\254@m<\233\252-\275\312\202\035=\375\352\000\273O\235F\275\236\225\232\275\"\270\206;\251p+=vk\007=>\226\321;\330\367\250\274\360\334\237=\334e\013=\314\300K\274\226K\005=\037&\002\274\3508.<\315\255\177\274\241c\216\274\312%\3159\325\260\361\274\nqY\272\340\357\240<{\376\352<\201\376\262\274\023\245\252<\216\266\201<\270k\324<0X\340<\266\215\241=}\\Q\275\253\311S\275\244\212\025=C\007\002<\232o\352\274L\350m\274\354q\205<\t\3230:\2343\303<~\357F=\333Dr<=Y\217;:\031\255\274\230{\313\274\227w\006=L\207!\274\034\356p\274\214_\366<\336M[\275k\246==\023\305$=\374\036\375<\240*\002=\253\341\003\274;\266d\275\325\213\203\273\004\t,;g\271u=\263F\013=\360A\\\272\341\033\322\274\233\203\254<2\371.\273?E4;\330c\225\273{\336\225\274\301\021\266\274d\344\332<\013J8=\277Fc\274\377\nr<\004\326\206<\215\035\273<\346\275g=-k\347\275\337s\317\275\221\207 \2753@\247\273s\016\260<\001o\016=\306\216I<\325=?<\374\266U<\327\322\211=\261\322\017\275\233/#\275g\260\206<\027\270\210<\2531/\274M\316\230\310\005=#%\014\2748\356\352\273B!\006\275\250\024\203;\266\010\332\301\337\275=qT\205\273i\372\362<\310|\000=T\2134<(\004\227\274\307o\213=1^\211\273\347\3705\274\314V\336<-\364\265\274\361\232x\274\030\245\364<\271\326$\273\275Gv\274\221\347\366;K;\367\273\360\177\r\274\314\240\323;\337G\3729\342\355\016\274\361\224\034<\230\032\000\000\021I\000\000\241\231\000\000\000n\000\200So\000\200\032\024\000\200j\212\000\000U\026\000\000\200b\000\000\336\005\033=\252\260\224;\366\227\030\275\000\262\245=\365/_<\205\024E\275\273\t\227=\214\227\213\274j\2745\275\241\317\022=Pc\245\274\351\215\225\274]\360Y:\211\265k<\225\350t=E\376\"\275\263\227\023\275h\346\220=}pB=\275\022%\275Q\255|\274\265\373\355=UYH\274-\036\240\275\251\257\254=O\201\035\275\323\360]\275\367W\332\275/5\302\274\033\212\260=\323$\204<\035\323\222:&\372K\0052\356\274\253\274\n\276\314u\225=\273\t\252;\2207\235\275\375\255\361<6`i\274x9\340\274\036Y\036=Z\005\216<\333\366]\274`\261\030=\331\241*\273\326\001_\274\255\335(\273w\025\345\274\201x\023\274U\0056<\240\306Z<\265/.\343\274\032\352\326\274%h\217;\215\263\241<\ns2=\271\347\274=F\371\204\014\304\376\275D\203\252\275\210N\025>\376\335\033\274\351RN\274\307\016@\274\302b\206\274]\3310\274\351\021\257\273\347\276/#\220\275\216\311\200\275Y\362\317<\014\227\243<\251\265\273\274\253y\376<\225\271P<\276\270\273\274\202\3704\274F\330\232\274\246\221\020\275\333Q;\274\332Q\206\274\036\216\235\274\313\303\247\274\2163\217\274\021q\347;|\321_\275:\216{\272\0239y=B\240_\274ni\004;`\221\320<\226\001;;3\373?<\350\300h<\332\0315\274wf\326\273\366\2202=\016\222J\274\035\270=;\026A\201=O3\304C\275\371\313\017\276\236\203\302>\276\017[\274n\262\234\276\256m~>\242\327b\275\246\301C\276" + } + type: TENSOR + } + } + node { + output: "899" + name: "Constant_25" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 + data_type: 1 + raw_data: "\303\314p\277" + } + type: TENSOR + } + } + node { + output: "900" + name: "Constant_26" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 1 + data_type: 1 + raw_data: ")\353n?" + } + type: TENSOR + } + } + node { + input: "898" + input: "899" + input: "900" + input: "899" + input: "900" + output: "901" + name: "FakeQuantize_27" + op_type: "FakeQuantize" + attribute { + name: "levels" + i: 256 + type: INT + } + domain: "org.openvinotoolkit" + } + node { + input: "897" + input: "901" + output: "902" + name: "Conv_28" + op_type: "Conv" + attribute { + name: "dilations" + ints: 1 + ints: 1 + type: INTS + } + attribute { + name: "group" + i: 1 + type: INT + } + attribute { + name: "kernel_shape" + ints: 3 + ints: 3 + type: INTS + } + attribute { + name: "pads" + ints: 1 + ints: 1 + ints: 1 + ints: 1 + type: INTS + } + attribute { + name: "strides" + ints: 1 + ints: 1 + type: INTS + } + } + name: "graph" + input { + name: "894" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 64 + } + dim { + dim_value: 56 + } + dim { + dim_value: 56 + } + } + } + } + } + output { + name: "902" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 64 + } + dim { + dim_value: 56 + } + dim { + dim_value: 56 + } + } + } + } + } +} +opset_import { + version: 10 +} +opset_import { + domain: "org.openvinotoolkit" + version: 1 +} diff --git a/inference-engine/tests/functional/plugin/shared/models/convolution_qdq.prototxt b/inference-engine/tests/functional/plugin/shared/models/convolution_qdq.prototxt new file mode 100644 index 00000000000000..914c874db64a60 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/models/convolution_qdq.prototxt @@ -0,0 +1,191 @@ +ir_version: 6 +producer_name: "ngraph" +graph { + node { + output: "899" + name: "Constant_25" + op_type: "Constant" + attribute { + name: "value" + t { + data_type: 1 + raw_data: "\210G\372;" + } + type: TENSOR + } + } + node { + output: "900" + name: "Constant_26" + op_type: "Constant" + attribute { + name: "value" + t { + data_type: 2 + raw_data: "\000" + } + type: TENSOR + } + } + node { + input: "898" + input: "899" + input: "900" + output: "901" + name: "QuantizeLinear_27" + op_type: "QuantizeLinear" + } + node { + input: "901" + input: "899" + input: "900" + output: "902" + name: "DequantizeLinear_28" + op_type: "DequantizeLinear" + } + node { + output: "903" + name: "Constant_29" + op_type: "Constant" + attribute { + name: "value" + t { + dims: 64 + dims: 64 + dims: 3 + dims: 3 + data_type: 1 + raw_data: "\017\304/\251\354=1\251\353r\325\250M\202\016\250ry@\250&\006\234\'\004\260\212&\261k\207\247\000?\226\'\251w\204\250\020\336C\250`b(\250\n\3272\250p\345\325\247\230 \331\247\0037\215\247\2043[\247f\253\006\247\017\232\253\250\032\346+\250^\n\253\'\\\354\252\250\031#u\2504\267\370&\263l{\250,\326\t\250\232F\225\246=_\364\247\207\232\207\250\273p\000\250r.3\247\204\261\362\247-A\007\'\023\212O\247{\004S\247g\363\257\247am\246\247\2018F\'\305E\300\247\257\220H\'\2671\004(\226/\243&\322\377^\250F.,\250\303.2\250\0170\002(,\335\'(\250\364\005(4\301e(\215+\203(\232\331>(\201E\345\'\246\036\267\'\'l\003(V\"\035\250\201\252\005\250q\301h\250\343\243\221&\003R\325\'O|\022\246\215\311\232\'\363\022\t\'\277\351\202&\305\206\000\000h\017\000\2001\227\000\000\tX\000\000\"\247\000\000\331\322\000\200Yq\000\000\336\247\000\000\203S\000\000\020\363\317\246\375\313\225%\023\036\n\'\330V!\247U\310\r\246E\203\200\245\326m\213&\273\371\265\'\320\227L(\313\337\037\'\246\017\274\'\334\370@\'\371[\214\'Pv\253\'V!d\'\256\260v\247\213\261\227\246b\334\027\247_\n\216\250M\300E\250\204\314\t\250S\267\302\247\021\013M\247\360\362P\247\034\314\266\247|y\312\247\316\215\353\247\242u\036(\36061\'M\302\245&\002\r\346\'\357\236\273\'\2128\200(\365U\024(N<\226(Ws\341(\034\215y(\337\030A(\302\312\032(\246\253\202(M\254R(v*\221(\361\271D(\236\263P(\237R\207(\306*\303\250]1\242\250\365\352\334\250\320\306\253\250\3776b\247\340\271C\250Y$\223\250\323\007\037\250\356\025\276\247S\327K\250\221\232\357&A\3171(d\031\252\243\005z\360\'\005\236\237(\233-\330\247o%_\247\371,\345\'S0\264\247\215#\231\250\272\334\260\250\025BN\247\263\313\034\250\2004\367\246\341\361\246\247\261\2650\250\244q:\247W\311\270\247\355Ga\250{\007\027\250O$\311&\007<\002\247!d\224\247>\267\214$\314\205\225\246\022\262\031\247#m\322\245\362\274.\245\341c\330&\007\000E\247q!\032\'\337,\022(\315^`&\316\035\037(\211\t\206(N\261\347\'\3149\214\'?V\310\')\353A(\266\317\'(T\265\010(\315\016\024(\213A\373\'\230\367\361&\217\2170\250\242|\005\250[7g\247\247\025_\250\344\343\362\247\247\201\200\247\177\220\274\247\316*\342\247\361\210\240\245@d\270\247\307iW\247\207xG\246(\024\234\'4&\310&\354\350\021(\221\242\274#K\312d&U\231\\\'6\275\245\2502\020\200\250\362\344\250\247N\256O\250\021\227\372\247\372\313\353\247\004\317/\247F\211\"\245\250\005\001\247u\264;\250\371Z\231\247EW\225\246\315GP\247\203\347\247\247Y\366\023&u\313\344\247v\010\371\247R\231p\247V\246\000\000h\310\000\000\233T\000\000\205\215\000\200\014P\000\200\2237\000\000(9\000\200`\307\000\200g4\000\000j\017\233\' \233M(\340\235K(\240\335O({\n\237(\224\007\236(\304\344\333\'\367\031;(C\257\027(0\374\232\250\251\346\216\250\234\244]\250_\343\002\250\270\024\301\247\0328\213\250\024\231R\250\343\200\013\250\226`\003\250\001\014\344\'\276V-\'\204}L\'o\210\227&\020\377C\247-\250\'\200\317\247]\242/\247\323\024\256\'\217!\004(\334\014\035\'\27605(\263%+(\375_\374\246\303Q\301\'\341!\350\'\361dw\250?\253\030\250R\"*\247W\r\352&\236\271\362\'\262\027\005(\030K\214\246\301f\276\'i\214\252\'\235\275y\246\372D\000\247N\035\241\247\212\371\026\246:\213l\'\266\320\344\'\324j*\250@\222K\250_o\036\250b\2550(\030\232\"(IV\304\247\035\341\305\'>\003\314\'\031JW\247Y\261\207\247x-\371\246\313\252.$\320J\037\250\r\321\275\247\234k#\250B\333\227\247Rj5\247FD\217\247Q\3258\250]\305\010\250A\212\245\247\344\305V$;\202\207\247\354\236\234%\220\201K(\020?\t(\253!\237\'I\265\021(x?r\'\0274H\247klq\247\220\347\264\245\274\014\207\246\022\273\030(\370!m(U\321\354\'\361\273 \'\241u\317\'7\215\010\247(\264\236\307\'7\330\367\'\274\230&(U\253\\\'p-\362&,\326M&)\250Y\247\202\301l\'\200\255\310\'[F\211\'\243\220\254\247\370\230\217\247\205\253\205\247\355\323\000\200B\313\000\200%\233\000\200:\215\000\200!\321\000\200B\322\000\000\321l\000\200-\236\000\200Pl\000\200wg\332\247\360\304\017\250\030\tW\247\3534\313&4\301\234&\371<#\'U\216\243\247\213\0325\250Al\r\250\326r\000\000hN\000\200n!\000\200?\311\000\000\2242\000\200\013\243\000\000\242\214\000\200+1\000\200\270\n\000\000\273\016\343\247Y\211\002\250\204\"\245\247\312\213\000\250 \212\202\247}\344\303\'\024\361P&\313\312\001(\213\031\233(_\215P&f\031n%`@\252\247fv}\'\353\313M\'K\2729\246\014\211\207\')\237k\'g\226\001(\242\214\244\'W\243\262\'L\005\020(\207(\025(v\036\026(I\202l(\037\tA(|\254A(\351n^(\016@\225\'e5\250\'8\347\372\246\241\262)(\227\376P(T\373w\'\276\274\317\'\373\007\304\'\360\0260%\356\252\315\247\313\260w\'B\\\026\250\360\346\323\'\261\355\177(\347\274V\'AA\242\250\352)$\250\266\031D\250|\233\302\274\343\030\330:\343Q\325\254\274\'b\000\000w\253\000\200\017\250\000\00065\000\000{\247\000\000G\220\000\000\'&\000\200&-\000\200=\275\000\000|\230\017&\274L\2216\274n\234u;\201\307\001\275\337X\n<\006K\301\273\215>\320\274\234\225\263;\202u\311\273DVW\271F\277\265^P\274\206\r\305\274\334\303\254\274\367Vs\274\332L\310:\017\277\340\273\206],\274-\303\025\273\323\010\327\271\251\376\321\273\323\275\247\271\0322\320<\010,\252;\210\303?\273D\"\244\273\376\010\t\274\343\021\000\274{\305\022\274\007#\210\274\20160;@\310\n\275\316:u\274+$\217\274\332\353\t\275\375+\310\274s\024\314;\231\007\256;\330\2703r\014\274Y\274\002\275\357~\235\274\227\n0\274}9\275\275\t\022-\274Z\237\027;\336\311\310\274io\277\274\342wL\026-\274`\373\016\275%~\260\274Z\023!\275\206\307\357\274\200N\005\275{\222^\274\373M\343;p\346\253\274o\215\233\274\371\251\237\274\207q\016\274\221r\232\274\273fR\274\305B\023\275\362\311\272\274/\255\262\274\362\250><\213\270[\273\0321\026\274e\342\342<\004\211\361;M\007R\273\222\241\212<\302\221\326;S\254\304\273|wX\274\356k\212;\36334<\347\\%<\354M\t<\234\372\223<\364\206\234<\344\367\342<\222\212W;\0311\230;\321\3128\2733\370\033\273\271*y;\344Ir\274\324\360\322\273\242DA\274\021\274\022<\005\244T<:Q\341\274\240\202(:\271\032\326:\333_\236\274\316^\263<\257\216u\274\227\347H\274o_=\274\334\347m\275\376r2<\020G\244<\323\027\335;:\254\242\272\326\210\333<+\2275:,\332\267\273\337g%<\350\'\3509\244[\207<\322\370?<\307\250\006\271\350\3743<`\300\201\273\010r\371\272,6\311:\270P\225\270X\247!;98\032\274\026\030\222\273\322+\177\274\366\225\017\274\022\315\253<\035(\325\274I(P\274\214|K;\026`\005\273,\305\264;\031RB\274\263\342\333\273n\322\372;\310D\\;\273\335n;\251\303w\273k\316\227\272\357\266\252\273\342\312\254\273\005HS\274\024u\277\274I\326U\274++%\275\222\257\200\274\\8\206\274\375\310\245\273\232n\031\274\275\231\354;\247\235l<\177ep<\301d\206\273\037S\217\273\272\221n<\263G\303\273\320!\023\274\310\027\323;%\342\355;\300\30426\226\217\026\274@^\020:m\205\276\274\036\212\317\274}W$\274D\230|<=\336U<\215\275/<\0220\321;\276*^<\323\346I<7\257\r\273)&\346;l\224\013<\242\213\241;\010\373\277:\223\264-\274\271\2603:a/\332<\335v\215<\274\230\273<\376\340\360<\274\244\310<\353y\255<:\365[\273\232%W\273Y\247!\2745aZ\274\010\032\236\273\310\361\201;\340\247\302\272\321YF\273\037\272\263;\245\230\036\273i\3507S;=\014Yq=z\346\022= \247\332;gzX\272K\311\355;\226\240\320;\025;\311;\030\321\254\274\355\364\202;\360\355\007\273\210\235\300<\275X\363Y)\261\274\260~\255\274\247\r\246<\326\361\257\274\313[:=\252\014]\272\310&\372;\371\027\276:&\256J\276\231\237\006\275\377\377+=\317\007\221\273!{}=ZC\261\274\331Rf\274\343F9\274\tZ4;@_\023\275\237\310~<\211\031\217\273\233\377\226\245\2729\021\031\274\027\020M<\177\307\233\274\223\200\027\274\210\345\250;\'\302\272;\037\326\311\273\212\364\261\274+5\216\274C\216\346;2nT;;\254\371:\221d\205\273\372\2735\274h8\006=\366]\'<\265qq\274gB\234\272;#\312;\357\332\227\273\036(H\274\276\260\213\273g\373y;\234H\326;\"\246+<\241\365\347\273\3044\225\273`r\002:\033\005\217=\346p$=<\222\244=f\230\223<\004L,=Y\321\037;\244Q\021\274H\347\217\274\n\371\361\273+\277_<\200\220\251<\005\271\007<\227>\344;`\230\215<\225U\265<.\202\250\273p\202\261;\001\255\373\273\351\301C\273\000E\233\274,4y\274bn)\274x\327\375;`\250\260\274\372%\266;\251:\336\273\364\264\022<\236n\320:n\247R\275\r-t:q\010j\274\024\262\200;;\374\251<\275\246\307\274\032I\231<\361V:<(\375\211=\354{\300=v9h=O\337\t<\202\223|=js/\275\330\351\252<\301\272\352<\273<\237<4k\272;H=\331\273,\277.<\270Y\360<\260\270\330<\325\245\002=\365\310n<\356\346\350;9{\271\273\3023Z<\321\307\234\274\342\236\376:\243q3<\311\246W<\010!)<*U\244\274\036z\331<\205\304\262a\261<\203RL<\221j\246\271\236W\241<\243\313\260\2723\233\200<\004\322\312;\200\211\222<\375i\211<\024P/=&j\034=\026\364\235<\266w\321^\000\200\023|\000\000\330\271\000\000\232{\000\000\257\314\000\200\013\317\000\000\212\236\000\000%|$==\344i\274\274\024\013<\030&\037\273(I\201=\r\025\367\274b\220\352\273\337\332p\273\206\322\021=N%\000\2008\310\000\000\304\315\000\000W\'\000\200\252X\000\200*\304\000\000\237x\000\200\014\261\000\200\232\310\000\000\272\317\350;\302\350\273\274S^w\274\023\004\273\274!xY\275\377\325\256\274\306\336s\2742\'.\275\267\377e\274\316\016\203\273Q<\2709G.n\274}\214\207\274\216\033\033>\2170b\274\020\360Z\274P\247\256\272A\005\222\273k\341+\274\344=\251\2733P\314\273\364\221\224:\307\357\021<\262H%\273\323r\030\2741L\031;)\266*<\322\216\326\272\323\214y<\016\332%P/9=\252\340z<\214c\370<\310xM=~\365s9\341@\202<\270\267y\274\351\277\233<\355\322\253<\271(\207<\200\254\222\274\023\030\306\273\265m\013\275\360\2764<\362q5=2h\325<\273\017\026<\203\'\351;\222\007\232=\316(\331;\n\233q=\217<_=\256\225\377\317\313<\311pB=0\221U=\244\242\"=\r\204x=\241\370\242=\327u\366<)^%=\233\350C=Ym\000\200\260B\000\000\036\220\000\200od\000\000\310\254\000\200\313\321\000\200\247\321\000\200r\213\000\200\330\317\000\200\317\0001\274\211V\213<\266\265]<\025\3745 \314;\245\025\227\274S\346N<\357\267\"\273\251\024\026\274\206\357\212<\360c\335\273d\2101:3\237\010\274\200\267\254\274<\335\r\275^\346\021\234\274\323\301!\275O\037\234\274\270\006\372<\302F\256\273\377]C\273Z\274\000\000\373\203\000\000\322\255\000\000\347$\000\200\250\312\000\200?o\000\200\216j\000\000\226\313\000\200\0045\000\000 \355\240\274\314c\201\274\241\212\342\273\342j\000\275\3351\342;\330\302\315\274\252B\315\273\031H\344; \355n\274 \022w\275\313v+\275\013\004M\274\017\215j\275\275\357\256\275\363\234\264\275\356\233\243\274Ud\245\275\271\213\303\274M\024\333<\322\245#=Ma\275<\n\177\240:\037Ze\273\241#r<\325\230\324<\326\027\243<\374V\235<{\'\000\200\026\211\000\000\2453\000\000\224\231\000\200A\232\000\200\350y\000\200n5\000\000\200\252\000\000v\031\000\000\030k\227\274\004\327\243\274G\371\365;8\355\n\274\001\203\027<\253Jh<\227\356\034\273=\r\251;\301\231S<3W\263<\270\326Q=\265h\006=\007s\375<\354\273\000=\243@\204=\022\253\013=^\324\246=\270\370P=r\247\363;\016\310\304\273-\220\206\274\366\337\316\274G\222\033=\266q\027\275\335F\030\274\317\025$\274\225\260\216\274Zj\336F\264=\267\357\226=+\332~\274&ai=\255\360\247<\030\326Z;\337F\340\273\330S\257<\016A%\274\001\'#\274\332\330\235;CL\264:+\217\242<\3751\342<\330\274\213\006\004<\3150\276\274\347\260\316\2743\344\225<.\202J\273\254(\000\200\373\250\000\000\'\215\000\000X\230\000\000\331\235\000\000\202\213\000\000\223\247\000\200\2143\000\200\340F\000\2006\232\315\273\023\033\245:\301\340\364\273\372qR\274hP\036<\"E\362\273\274\215\327<\303;\304<\323\233w;\231\356\334\273]\276\371;\332\2332<\247N\312;yYO<\036\355U=\254\254\006<=x\020=\340^]=7\346F<\323<\317\274fe\254\274\252u\210\274\232\217\307\273\267\267\242;\236\366\311\273xj\205\273\340M\254\2741\\\250\274\000\005\004\274\260#\316\274\321\364\254\274q%\201<\035\357\362\274Z\263Q;\360>\177\273^\370\020\275\240\352\360\274yt\375\273\003\235\325;6V\004<\\\275\007\275A\234\335;\007\245J<\263\320\224<\320Y[<^\356\024;`\t\313\274\223\213\274\273 x,\273G44;\254s\177\274\375W\001\274\373bg\2746\302\277;k\205\016\273\2760\2718_Z\016\272\210\301\302<\366\346\264\274\322\255\240=\203\036\271\274\234}\321\273M\024\306<\234\033\230<\333!\021\273\247s\240\273\373!\345;\r\360\364;\2719\255<]\237\340\273\210\366Z;\254c09\367\306&<\222\272\356\272G\nq\274\025\277\026\274\354b\217\274\207\003N\275=\202\255<\213\210\315<\316\023\271\274\345\236><_}\000\200\022c\000\200r\257\000\000\311}\000\000\236\013\000\000F\255\000\200c\273\000\200\202f\000\000\025}\000\200\325\262*\274,\343\331;Y\203\321<\324|\353\274\204I\206\274\237\226\004=uJ\r\274P;n\273/\272\370;\313C#\273IeH<\026\347/<\374\263\'\3279\237C\323\272]\214\367\274\251\303\033<\2308*<\031\000_\2753\231\272\273\000p\324<\256b/\274\330\247m<\'\343\321<37\326\273\244!\273\2743\345.;|\316\245\274p~\010=\177\360\257\274\242J \273\343\004\007\2722]\355:\372\277\2779\347R\234\274\241\214p\272\22282\274\376\211p\274\005\236\025\275\225\301(<\263H\353<\247*F\273\n\343\354;\354\270\321<\336]\230;\025\244\375\274\351\035\344:` \003\275\312%\247\272\003\t\242\2727K\014\274\270\231\021:\264\352\004\273\370\255K\275qO\375\273\212\356F;Q\275B<3k?;\261\267\177;\t\325\261:=\365\370\273,t\240;nU\004<\'\0045<\255\006\035<\007\265\034=\236\245p;\031&\270;\226\352h;\214\2413\273\375\224\251;.\352\236<.\027\030<\273y\201\327:\370\234\255\272\202\333B<`\361\305\2731\331\037\275\372\223\205;\254\037\243<_]E<\342\370\262\273yMu;J\221p\271|\3340;\3114U\272\023\363\302\273\3600J\273\010-\210p<\3557\036<\255\327\243\303;p\013\r\273\000\006\201;-\027p=+\375\264<\362\252y\273\247\360\267\273!\351j\274\372<\3358I\202e\274\026\230`\272lP+9m\347=\275\373z#\274H\242\225<\023S\223\273t\034\220\274/\314\000\000\275\303\000\000!a\000\000A#\000\200\275\255\000\000\224\217\000\000Wu\000\200\211(\000\200(\311\000\000\006\313\177<\212\333\033=\335\260\363<\315Xm\274h\356\004=\347C\005:\350\261\275S\273\n\307DY=\325=\244y\214=\336n\374<8r\037>\221\200\236=\257\205%>\255\256\340=\004\2470;c\364PS\030\271%\207*;m\026\264\273\303~\317:\321\"\207\274G\224r;9\333\241\274\314\254]\274u\342T\274\242\231\004\273ke\260\274nB\241\273\277v\021\273\262\347\246;$\211#\274\374\317\354;>\305H<\376/\220;\223\377\206;O\363\227\273\030\035~<\327r\240;\344\210\343\273b\223u;s9\240;_\335\221<\036\036i\274\237\233\324;\357}\231\273\n\362\014\362\314\273_G\302\274\230z\207\274\364\227b\271\201\257\036<\220\237H\274\227\272\307;\177\014\204\221\026\327\274V\210\274\274\206\343\007\275r\254\367\274\r5\226\272\207&!=\017\251\002\275Z9E\275\347\300\"\274\311\010\232\274.\'\003\275*)\026\275PD\025\275O0\200\274\225b\243<3\372\343\274*\323\364\274!\3275\275\372\312\357\274=\325\306<\025\362+=]\312\277\274\360\205\255<0\022+\275\"s\246<*hb\273\301\001g\274\240\232w<$K\355<\212\335\004=\335\257\215<\214\017\252;F\036\036\274M\330\254;\204\223\266\274\327H\265\274\225~\013\274\242\211\311\274R\273\204\274\215\341q<\031\302O\274\240\306\251<\344\325\316;\247\372\374<\346\342G\274,n\264<\222V\345<\270\201\306\271\306G\364: \312R\274\275\023S\275\344O\276<\215y\310=aE<\272&\322\000\000\234\256\000\200\244{\000\200\240\037\000\000\362\312\000\000CY\000\200\307\004\000\000\277\234\000\200s*\000\200\030\352=<\'\256\236\274\373:\231\272\237I\002=\214\323\223\245\351\020\275T~\033\275\r\321 =\266\225\216\274\342\373\031<=u\304;\333\2221\273W\031\365\311\025\275/\254\024\274[\301\003\274\254\200C\275R\351\214\274edB=\222\270\342\274\020\253\260<\234\240@\275ef^=\005\256\221=p-\010\274I\003\t=dH{\275;\246T\274*\302f\274\234y\001;>]\242<\340\267T=\316\236i=I\336\207\274J~\005\275\002N\230\274\265&\000\000\300\325\000\200\210\243\000\200\263\216\000\200\304i\000\200-\325\000\000B \000\000\205\272\000\200gR\000\200K#m=\270\315\271<\247V\001;\325[\223\274\252\331]\275&\363\272\274D\341^\274\002\206S<\304\234y\274\2415J\274\221R)\272^u\331<\3100P<\013<\323\273~g\001=\001\006*\001\274\255\356\206<\276\215\221\274\312\244.\275\352\255G\235\303\275 \262T\274\237(\243\274\203\002\211=\023\330\312<~\210\245\274\001\304\033\272\240\r\255<\265\316\271\273\321 .=\371\344\026\275P\324`\274\305q\210\270\022C\274VR\363\272Q(\201\274\223\376\000\275\345\005\206\274jJ\323<\274\243\220\274\220\264\211<9\032f<1\247\010<\322\3628\274\3149\367;\271B\260\272$\034\335\2730\177\265=j\\\244<\030\325\261;\367\333\330;\330\322\340;\004\254\232;\214`\210<\207z\037<\263\005\352;\t+\376:|\335\207\273\227\377.\272h\245,;\312\002\023\274\217`%\273yG_:zc\027\273C(\377:w\362d\273\247\304\314;]\226\021;U\204\321\272\273$\0272\243\270\253\222\215;\216\220N;\016\031\036<\270zZ;\350\331\350;\0326\312\272\2518\225\274#\0301<\355X[\274\272\227\221\274[\320\215<\255\205\217\274\030\262#\2743\333\026<\t\000\203\274\277\031\034;K\376\333;\344\361n\272\0175=\274\322\303\241\033\273\260\'\362\273\211>>;\274\031\307:\037Mg\273o\254\233<\320\240\345;l\327\003<\271\177\004<\342v\002\274\220!\2249\376:\247;\343\242\302;f\210\355\273yP\337\273\377\313i\273\224:\224\273\211\307\037\272\274\377:\273O\013\002<\201\254W;G\216\306:u\2143=Ew\252=\351\020P=O\351\205;\322\351^;f>\330\272\246\".<\255\014\236\272\242\251?9\263Of<\305~\202;6\213(<\376\0222<\3169\264;d%.<\375_\010=\020\203\365<\021{\331<\367J\226<<\032\013D\273\333_\241\271\034>\263;\222\357`<\305z\000\200\233)\000\0008\312\000\000\240\202\000\000\374\321\000\200\255\324\000\200(\\\000\200\316\306\000\200}h\000\000v\321\347\271K\240D\274J\326\255\273D{\032:io$\275@\224?\274\017V[\272T=\033\274\372\004\213\273\325\333]<\226\035?\036:\237\205\335\270E\254\340:\013y\2769;\363\316;\254\267\316<\321\230D\261;\240\032\262:{DT\274\004>\004\271\274\035\025\273\374\212\203\273\201\355\303:0\307:;\n\337L<\340\002\002;\272\214\261:\224\256\021<\316\204$<\0161p<\257\036\t<\211-P<2xP<\312\325\013<\266\037Y\273UNU;\367?\315\274\005\003\344\273\210\364n\274\212/B\274\223D\331\273l\214j\274\273\323:\2749\026\221\274u\375M\274\252tK\275\024X\214\274\rS4\274\361\020\275\273\025 0\274\331\034]\272C&\213\274\316\024\276\273\204kT\274\320\316\226\273?7\020\275\2677\216\271\253\250\016\275\345!\355\274s\205\337\273@\003\255\273\215\273,<6\313\016\274\307S\3579E7b;Z\202z\274tk\245\273\277\247\366:\366\304\217:\274\314\227\274\220\307\247:\240\271\261\273B\0063\275\365\207H\274H|~\274\333\202\366\272\014k6\273k\371\242\272\206\017\177:\340\360\350;\037\022\310<\253f\232<+\341\026;9\211\274<\032V\030<\177\366\231;B\357\010<\306c\346;\265\234\207\272D\302\367\272\021\207x\274\354$\243\273\323\026b\274\372\301\\\274\023v\224\273\3572\336:\241]\'9\301\253\304:\307MO<,\242\235;q\325\337;\373\024\027;\276\211x;d\264\255;}T\227\327;\253\311\260;\227\351,<\007\223v<\006\'B<\330\271\307;\277g\200<\0246n<\226^g\272rw\246\272E\246\254;Wf\201\274\223\262k\274I\271f\272\r|\215\274\023\375{\273uNM9\024\273\232>\266\273f\233u\272$\3577\274t\2366\274l\310;9!\207\253;\332&%\274\243\373\230\273a\261\340\273uA\357\273\275l\':\271?R:\"\2025;\322\315\272\272\3612v\274\305\342\350\273\215\310\276\272n\325\224\273b\301\344\273\205\221\267;\202\333o\206<\276F\231\274\314I;;\263\345t\000\000\032\326\000\000\0079:\2746\260\242\274\333M\003;v\265\223\274\347\336\246;pDp<\210\260>\272\002\3579\274\242\233n<\330\245g\274u\355i\273*\027-\271\013\036\226\274\246\330$\2755\030\226\274u\r.\274\242\314\207\274z\216\204\273\332Q\360\273\016$\344\273\375\027\221\272#\']\274+\272[\274@Y\277;\344\003\261\273Y\001T\272\261\332\000<6w];\205\266\004\306=*\273(J\224<\225>\315\274\314\305\234<\320\317\224kU\274\366\341\266<\303\347\227=3JE=\204\014\261\274W\271\214\274\236\371\221;8\255\214\275\220\270\242=\355\035\016\275\213)\202\274\362,.\275\rp\007\275_D\023=mC\346=zN\250=\335Z\'>?q\351\276Ye\023>\274q\250=\303\220\002>\367n\336=AH\273\274\370\204\030<\226\337\336\274\001#\322\274\"h\216=\221\225\230\274\350lq\274\335\365*\274T;\201\274\001\376\331\356\315\265=\002\035\307\273\236R-\274\241\201\325;\210\325\233\274A\025\310=\013\306\014<\320\005\005\275\201r\205\274\0176\215\274!\341\236\273y\303\010\275\375\374\206\274o]\035\2758Jh=\r\027\036\274\220\3155\274\303\034\220\273;\2262<\351\340/\211o\000\273\307\030\007\275\266\347(\274\0046\021eI\351\2741C:\274\262U\022\275\233\033\345\274[\303\000\000\214\215\000\200G4\000\200#\217\000\000U\303\000\000@\247\000\200\275\304\000\000\357\255\000\200\367\211\000\200Q^\355;5R\022\275B4\r\275{7\237\274m\215\312=\027\270\340\2742>\352\273MLZ\275\200\326\342\274$?\000\000\365\303\000\000\222\252\000\000\006\276\000\200$\005\000\000\211z\000\200\353d\000\000J\316\000\200\342\'\000\000\rJ\304=j\224*>\376\016\220=\333g\032>n\346\357\276\264BJ>C\032G=p\343M>Ps\031>D m\021<\022\201\320\004\374\275\223\375\274[e\367\273_\375C\274\221\367 \274n&Y<#\300D=\273\026\371;t\363D<\037\245\177\276\016\312\211<\373+\222\272\027K\324\342\325{\275\333U\007\274\"_\027\2759F_\274O/\217\271!\341P\274\212\204\253\274\344[\261;a\233\263<\206\030\335<\227\226U\272\226\312\365;\355C\267;\216%\326<\013\240#\274T\356\'\274(\245\024\274\3516f\274o~\264\274\270\343\222\274\247\365\001\2740\3047<\217A\014\273=\022b<,\022\263\272O\213\260\273\213x\336=X)\003=\254\355\263;lX\227<\217\2167\273\212\232\257\274\355\"\231\274\026\302L\272R\246\365;=\222\266\275\240\301\244\274\037\207\266\273\254\2700\274\0170\271\274C\360\263;O\003I\274|`W\2731\327\232\274$\203vG(\031;#e\004\275\324uf\273\246\234i\272\3468\000\200v6\000\200\340\315\000\000\366/\000\000\337\312\000\000\014\202\000\200\200\266\000\200t4\000\200\027\267\000\200\303\265-;\224\007\365:\243>\365\273=%\317<\367f\034=A\210\270\177\273\340J\302=\"[\023\274B_/\272!\276Z=kS\344<\346\316\000\000\360}\000\000\343n\000\000\321\216\000\000\\\320\000\000\217\271\000\000\032\303\000\200\201\310\000\000\245\202\000\200\225R\340<\334pL=\030\321\324\274\202\251!=G\341\315<\\*\002=\020\324\"=x\362\235<\261\301\341<\257\253\017=@\332\037=\033\t\022=*\235\000\000vh\000\200[\305\000\000$\274\000\000\314u\000\000\316\322\000\000\374k\000\000\202%\000\200\360\214\000\000\227A\223^\'\010=\371M\214\233O$=\030C+<\361\006\021=\373CUC>\377\363\256=\232\033\014=\302\3649=X\256L=\325\213\037=a\204\267\275\245 \332\274\271[\341;eG6\274M\356c\274\304\335\001\274D{\241\332;\343R#<\234\320\350<\341\264y\273\327\354\277;^IG\274\035\244\234\274\324uk\2759)\266<\345|\004=\\\217\277\273\006Z\321<^\272\000\200\"\205\000\200\274\310\000\200\274\321\000\000\342\213\000\000\257&\000\000\317$\000\200:\245\000\0002\312\000\000^\222\223\274\201\357\253<\0214<<\231|\226\274\223\314^=\342p\\=Eo\331\274\\y\r=\363[\211<\364\321\014\275\233\201\022\273\213\320$<\354\255\277<\177GO=\030\213\3027\033\317\215\274\217\201\271\273q\271,=\317\352p\273\206\340\357;6\343\014\273\324\264\276\2743\217)\275\336\242\007<\246\026\021\205\236\246\273\337\027\014<\377\266\023<5\263\335\272\320j\002;N\224\003\273{\316\031\274B\202y\274\343{U<<\305\030<\273r\225\272\370\243`<\305\260\037\272yk+;\207z\032<\177\004)\274\260=Q\274\324\026\024<\222D\022\274*sZ\273\254*\016=\322\305\251\272\275k\306\274s{\234;\264\214\037<_|\027\2745\303\022\272\353\230\030\274V\360M\274\034\033R=\262\210\215\274\237\201\337\27417\352<#\227g\273F\226*\272\273\"\332\271\221\274d<\033\316\315\272\032$M\274\3448J<\315\001\200<\007G\224<\2071\320<\33695\275q\365\211\274\325M\302<\310Y\030\275^\335\215\274\312\264\224=\r~\273<\216\244\214=\237\245\337=\372*P\274{\003\336\274W\364\227\274\250\034q<\272\214-=\342s\330\007=\264^L\362\364;\340}4< \017\"\273>e\001<\254v\234\273\355\325[\274\3454|\273uM\333\273q\250\275\274\211-\250\274\371\3113\274:\313\016<\315\327\256<\320\0222u\274m\343,\274\342\352\037\274\211s@\274\352I\203\273\357\247\r\274\031\307\222\274\257g\036\274(F\007\274U\034\203;\243\224&\273\337\317\245\274\000\032\276<\333s`\274\264\202\354\273*-H<\332iwciV\274x\336\313\274*\327\263\274]d:\274\236\003;\273zD\036\274Z@^\272\2702\261\271n\177\305\272]\246\026\274\251\246\203;\341\2734\274\372\237\324\272\204\355r_\000\274\255\307k\274C$\247\272$\001$;3\334\r\273\014\013q;u\210\014=>\305L:\310\004\351;\310\225\002:\201\262B\273;\316\000\200$\024\000\000q\030\000\000p\320\000\200\202\320\000\200\235\305\000\000\253\203\000\000\032\262\000\000\325u\000\000\331\236\231<9\n\004<\316\013\237;\214\273\206<\232\'\307<\233.\240\271\177\344\315;\231\357!;\014\211E9N\210\000\000B-\000\200\317z\000\200\215\301\000\000\342\234\000\200\305}\000\2009\322\000\200O\312\000\200\244\007\000\000\035\007j;\366\227\220:\244 \253;\221\253\350;\'|\311\274\276A-<\373\224\335\272\371F\177;\315\033\226g=\214\017\032=\016\324\345\274\\\252L\2752\227>\275-o\344\274\230\354\211\274WF\373\274\364\374\'\275_\334\030\275a\354\240\273\021\322\300<\026\355M<\201uk<\017\010\007\274Tg\343\274\"G\204;\306Q\346\274\373\352\230\275\035\250\230\273#\276\376<\332u\3309\357S;;\003\354\305\234\010\273[[p\274\241\310i\275?}\233\274\306\354\222\274u\002\211\273\330\357L\274%Ry\274e`\245\274\355a}\275\026s`\275j2\270\273m\0163\275\303\223\324\274\217/\020<\225\246\030\275\264\367\245\272\362\000E=\026\025\216<\250\335\320<\263\206-;\226UL\2752>I:\210\'\2139\274\227G<\304\202K\274N\303\335\274g\214\210\275\252v\030\275u\311O\274\314\367\230:a.\205;\0213\272\273\032\306\001\274\331\307\213\274\227*\337\274K\334\223=:(\035\274\\\237>\274=\001>\274`\310\214\273\t\n\245\2745h\032=\317\276S=\0105\252\274r\302\220<\361\312\020=\354\034\266=\003>\344\274\364\326|=\336Dd=\374\334.;m\334-<\241\000\274<\207\2267\274\020\022;<(Q\002;\373\343\345\274\357p,=\316B\023<\351\025\000\200v\275\000\200L\006\000\000\033\177\000\000\312\315\000\000\311y\000\200,\223\000\200T6\000\000;9\000\000\'\270H\273\007\222\363\274\262\344\210\274\010#\323\274T@\324\275o7\247\275\327\177K\274\025\272\220\275\370>\037\275\036\347\010\274\032\224\256<\347\r\016;\327\236|\274}`\014<&\310\024\274;\035\033<\204\027\030=\nR\346\274\313U\322\274[\331\300;\363\333\356<\375\363\303\271\216\225\337=YE\236<\037\005G<\270G\016=\253\032I\274\003q\000\2001\317\000\200F)\000\000\317j\000\200\305\227\000\000\320\307\000\200}G\000\000\345\273\000\000\035n\000\200\360*\207<\224\037\"<|!a<#\211\270<\256m\307\273U\240\3169|\362Y\'\263\247=\010P\237<@\263\233=!bP=\014\032\220\274\307V\354\273\304\205.<\177\354\335<\023\302\277\274\'6=\2733\327\334<.\271\267;\307A\232\274\3641\313<7\314\256=\261\337N=\355\243\036=\213\362|>\003G\000>\273\3241=\223\230\373=\345H\316=\374N\214\273K\376X<\004\244\321\273\237]\224\273\337\316n\275\331\305m\274k\303\223\273\210\251\277;M\333\242;\tYC\340`\274\005\231\000\274\234(\202\274N\027\237\274\234\270\265\273\231O-<\247\351\221:\"\021\311\274\216b\270;\265\375D\275\n\245\r\275\333\024\214\275\027\333O\275R\260\263<\341\216\272=\303\265\202=+\277?=\01655>_\337\365=}Rj=\272\016\031>\\\270\257=\343L6;\014z\200<\343\3408<\031\rv<\345Bi\273-js\274\277!\224<\014t>\273n\367R\275n\255\177=\307-u\274\377a\025\275E\341#;w^\377\274\336\351\271\274\\]D\275\033\3417\273\332w\272\274\306<\024<\0269\344\273;Z\366\274\261\216\000\275{F\334\274N\343M\274Z\317\263\2734\364\241;<;>\273\353\241\334\274\311\031=\274o\013}\272%\223\243< \332\221\274\323(\275;?\337\276;\"1\034<+\215\207;\230\220\230\274\375\373\027;\217-\004<\207\303\327\273\2053\037\273y\357p<\217\356\313<\342\342\351<\024\301\245<\343\233\027=.J\265\244;\021\\|\272\273C\000\000AN\000\200%\200\000\000[\t\000\200\244\233\000\000\024q\000\200\t\310\000\200\356\304\000\200\220\305\000\000\\\231\"\274p\235\211\265\376\203=/oK;\177z\254=D*\320<@\375\376;1\352\233\273r\032\206<\326\324\372\274\274\251\251<\201t\030\275\036;m;\217!\232\2741\312\t\2741G\021=\266\001\364<\351Ox;\354q\003=\216\357\316\275\'\350#\275\340O\340;N\037\030\274\300K\001=J\216\373;\201\t0<\334\310\254\274\211!\000\274\005~\002>\016}\253=\036\265;\274\315\\\211=\300;^<\315\271\273F\213\211=\301\223);\315f\245=`z^=\2452 <@\023y<\325\222\304<\014M\265\274\r\376<\275\366\367\202\273\274\023\334\273\251\022<\274\267!E\272a\020\000\000\315\230\000\200:E\000\200*\306\000\200r\275\000\000,\215\000\000\227\217\000\000\000\273\000\2009\322\000\200\035\343k\272g\265G\274e0C;/\266\223<\346\034\021=7\212\000=8D\000=\372\361D<\330r\320<\225?p\366\274\236-\014\274\213y\031\274\271B\251;\314\254\302\272\027w\026\274\361\037\237<\344\\\013;\345\247(\274\022|\347\345}<\201\260\226\275\037\346\204\2744\303\030;\344\333k\273\306\331\025<\374\371n<\24229;\356u\034<\'\223\036\274,\247E\273\243\226m;\177@\343\274\335\020\231\274Y{\354\274\020E\333;\377~\315;\207hp<~M\004\274|(?\271rU\025<\352/\3239D\341I=W{\022;M\365\206y;\302p\217<\375\266Q<\010\265\274\273\204/\t< ,\246<\370\037M<\310:|;\016^\335;x\320D\274@\366\177;\302\032z<\r\255T=qF\310<\3467\031=\245\2249=EM@=\3333\333\225A\247<\347\324\017>\236O#=\224\255\000\000J:\000\000d\247\000\0006\212\000\000Y\274\000\200\215\324\000\000`\305\000\000]\320\000\000U\220\000\000<\377\247\274\\Sa\275\251\005\003<\342$\327\274\234\266]=\313W\230\275\362)\311<\007\307\\\275\211\000\345\274bJ@;\227\266H=Z\346==\306\240\215\273[\343\016<\213\217\277\273T\\\357:\371\336\201<\240\r1<\276\277Q\000\000\367\317\000\200L\216\000\200\217\"\000\200\353\304\000\200\013\233\000\200\307\263\000\000pV\216\274\212\211\376:\010Ud\273\370\373@\274\022,\337<\03135\273D\325\\\274\212\313M<\235S\225\273\310\307\253;\201[\265;o\305\317<\3268\220<\2009D=\026C\031=\331\274\261\273\244\261\007<\313dp\273\371:A;\234\250\347\273\220|\031\273\314\230I<\244\361D;\346\023\327\273@\245\035\273\247\332\023\274\200e\235\273b\004\000\000PY\000\0009\301\000\000[\312\000\200\216\305\000\200\371\032\000\000\272\320\000\200\351k\000\200\010J\000\000\234\315\255:D)W:q\366\264;RSu\2737\001\001\273n4-<\023\372\275\271\200\354I\273\t\306\022;j\2676:\273\257U\2737\302\351\273\272\026\216<\3333\301;a\272G\274\370\365\272;\360A\264;\000\371.\274`\003\202\273\233^j\274\003\254\311\271]\2464\273\372kX\274!\343\332;~\215 <\014\273\317;\227%L[\273\333\2631;xG\024:\201\204\322\273C\251L\273\230\243i;\315\367\276\272+\347B\272\022\362*9\301\346\327\273\020K\205<\031\372p<\303e&<\300\226-\272q\321\365\273\\\324J\273V\370\r\274\016;\373;C\274,\225\013\273\005\327H<\336\275\224<\300\025\266\272\002\267\246;E;\215<\320\021\3358\372\224I:\312d\375;\345\362@\274\013t\255\273\251\233\023;\263\213V\274\322\353L\272\263e2;*\235\355\273\002b \273Q\224\320;\361z\225\270_-\213\273;o\2559\241)\204;u\320_:\024\321#\273X((:\301}\007\273$\223\n<\206\004>:%\271\322\271<\254?\370<\253\336\337<@\264\321;-,@=\t\370\270<\237<\206=\364Uj=\223@\231\274\016\"\3178\335\306\006\274\221\301\267\273\025\212\224\273Z\256\';\014=\'<\217Al;\375kaQo\275\211]\330\273\371\r\255\306\273\375M\311;4\312\205<\022\271W\272\010\333\021\274\375\001\204\273\006\331\221\273\331g\'\275\235\320;\275\205\217\371\274\207\222\236\274b\242\326\274s~`\275\273\246R\275j%\204\275\243\024\234\275\021\233\220\273&\255j<\227y\t<\030p\010;5\307%\275WV\020\274c\306\214;m\222\036<\026\r\352;5|\305:<\017[<\335\255\313;\034\276\202\274M&\n\275>\303\264\273\312N\260:\230\340\202\360\324\247\300B\330\2470\215\215\247GbX\247S\216\003\247\332T\253\250\215\213,\250Mj\253\'l\351\252\250\007\330u\2506=\364&\237\255|\250\266\362\n\250\237\376\232\2462z\365\247\345\020\207\250\022\021\000\250\325\0354\2472\336\361\247`\331\003\'\303\360L\247\3750M\247\r\037\260\247\212\223\244\247\201\274P\'\262\274\271\247\2179A\'J`\003(\221\263\253&^\177a\250\245\005.\250\213\0142\250\251\r\002(\256\307((\330b\007(@.e(\373\240\203(\333\211?(\023\276\342\'\374|\265\'\366\023\003(uK\036\2504\374\006\250\247\341i\2500\323\216&R\370\325\'\234\305\036\246o\006\231\':7\013\'\341\016\203&\307y\000\000\371\325\000\200Oz\000\200\327b\000\000\340\301\000\000s\240\000\200\3076\000\200\033$\000\000l\254\000\200\317\313\346\246\211A\361$\364M\000\'\324\272\'\247n\212#\246\1778\261\245h\021g&D\340\262\'\371VJ(F\312!\'\263\255\274\'\022:G\'C\367\212\'\240\301\252\'\251\334g\'\024\027u\247\341E\225\246\335\210\022\247\300\263\216\250\024[F\250\331\316\n\250\256B\304\247C(L\247\270\244U\247X\261\270\247\031\363\312\247\216\256\354\247Z\362\035(\256$.\'wu\245&\345\337\344\'V\221\272\'[\344\177(\363\243\022(N.\226(\335a\341(k\214x(\'EA(\247\022\033(o\371\202(\250\311S({A\221(Z\nE(\006\317P(Yy\207(\026}\303\250\235\370\241\250\225\030\335\250\312\231\254\2505\200_\247q\346D\250\364\312\222\250&3\036\250\007<\276\247\210\353J\250\307\353\370&\341\'3(+\005\222\244Y\317\356\'s\000\237(\364\347\331\2478\255Z\247D\356\344\'\262\242\262\247\tn\230\250g\266\260\250\004>N\247\216\025\033\250\233\277\354\246f\314\247\247|\3161\250\202/=\247x\177\272\247zXb\250\316&\027\250\314\304\304&J\331\004\247\357R\226\247\330\037\022$\271d\235\246\337v\036\247Q\273\276\245\001\030G\245dZ\332&\314\252E\247\334\253\026\'\202A\021(\224~W&\r^\037(\252\007\206(C\245\345\'U\242\213\'Tf\306\'\031\217A(x\235\'(\335\271\007(\374\365\023(:8\372\'\371K\355&\251\013/\250\362\366\003\250\340\261b\247\\\315^\250\036\335\361\247\272\321\202\247\371\025\276\247Gb\345\247Xp\345\245_\262\273\247[jW\247\262\354N\246\022j\233\'2\322\304&a\235\021(1\313\202\243p\241a& \377]\'\037\177\246\250\0248\200\250bL\253\247\023\237P\250\330\337\372\247\363\340\360\247\334\3624\247<\341\036\245\267g\n\247H]=\250,\215\230\247\003/\213\246\000\314X\247@X\251\247\323\034\034&\302\234\351\247\274\343\375\247\000\347u\247\265\307\000\000\376\320\000\200\222\243\000\000\314\317\000\200q\317\000\2002~\000\200=\317\000\200\344\312\000\200\330.\000\200\374\202\233\'\275\327L(\260AL(\020(O(\"\263\236(\361&\236(\033\352\330\'|]9(h\332\027(\331\254\233\250\312\326\216\250\035$]\250;.\005\250a\017\301\247c`\213\250\335RS\250\210i\014\250\372\311\003\250V\373\345\'\001\236/\'\031\214M\'\243\262\233&\304\006B\247\307\020\313&\221<=\247\201\231\346\247\032m\320%Lg\000\000#8\000\000m\310\000\200\232\307\000\000\243\"\000\200\224\202\000\000\242\271\000\200\347u\000\000+M\000\200\334/\325\'\277P)(\347Q\355\'a5B(\272\324Y(\340AZ(\3364\240&\231\255\204\'\002\025\024(,\341r\250/G\020\250\307\313\313\247\214gX\2505\3107\250Dt\367\246\221Z\252\247\033,B\250\"\235f\247\346f\357&\200R\216\'\376r\257\246\326\215\000\245\276R\371\'\235/\241\'\366\365f\250l\326\252\247\272j>\246\346\034\273\'\330$\252\'\204\356\202\'\216\206\255(/\345\263(\302c^(\362\023\230(UO\242(b\203_(\202\322*(\252\033\240&\324$/\247\013+\261\'p\235\364&\251\261\377\'t)\222\';\200\372\'?f((89\303(\271\252\300(\212\217\202(*\014q(\253,\202(\254sH(\274Q\344\'\204\373\021(.V\024(!$\177\247\020\021\267\247\027\225@\250~\000|\246i\375c\'0\310U&f\266\200\247Ux\301\'\366\205\226\247\225\016\220\'\324\267C\'\274\224\226\'p\025)(\233\374.(\217 +(\214\233\322\'3Z\206&?0l&\256!\232\250\017(\243\250\307cF\250\237\0048\247\236\237\225#4&\327\' \'@\247`\256_&\251\r\216\'\312y\321\250[j\240\250\016o\222\250v\252\201\250\233e\177\250\200\0338&#o \250;\n-\250\206\354\317\247:\0303\247\250\t\254\'\000L\004(\257\371\025\'\30724(\351\246+(\202\332\005\247\260M\276\'\210:\350\'\016\250x\250\360\033\032\250\306G/\247\353\031\331&\317\342\357\'We\003(\0266\231\246j\211\275\'\257\034\251\'\232]r\246\213\320\374\246\346\317\240\247\265\214\014\246C\225q\'is\346\'\323\210)\250O\'J\250\257\374\035\250\322\3011(\256\267#(e\215\304\247aP\304\'\331Y\315\'Y\206X\2473@\211\247\tO\361\246\246\375\236#X\t\036\2501\351\267\247Z\246 \250\317\315\225\247\221\030.\247\267N\212\247o\0239\250N\363\007\250\235\r\243\247\013\3747\244D\231\211\247\365~X%\217\231K(y\034\n(~\264\237\'\356\301\020(~\202r\'2\366E\2477\022s\247U$\221\245\351\245v\246[T\030(\307\373m(\357a\354\'s\035\"\'_\313\322\'\354\032\005\247\276\004\356\246\245\037u\'`R\025\247\324\246-(\244\330v(\340\026\250\'\177\336\236\'\247\350\335\'\236l\252%\312\236\"(\274[3(\320v0(j\322h(\226/\207(\317\013~(R\270D(\324Y\031(_\276\t(Y\235h\251\212\205N\251\374U\362\250d<\264\247\251*\267\247N\010d(\306\250\272\246\275p\206\247\321\214\021\247\250I\246\'\351u_\'\310\'\273&W\305\265\'a\"\003(4~\204\'7\316\017\247\2374\022\247 \220\013\247\226\260\230\247:\375\213\247\302\200\210\246E\374e\245(\377?\246\037\315#\2458\214\334\246\001K\274\247s\374\211\247\316\226C\250B\245\251\247\215\343\231\247CF\200\250Y\365;\250\001\030Q\250\201-\225\250\0231v\250\351W\276\247X\250\323&\314\215\201%\203\204\307&\316\374\332\'\"\372k\'\233}\236\'f\375Q\'>\333\253&B\231~\'\225V\261\247<\002[\250\024\330,\247\235o\330\247\350K\211\250\001\032\000\'\3465\245\247\022AJ\250\217\211\302\'\226\347\234\247\237\264\254\247iQ/\250k\373O\'\356\364\020\'\033Q8\246\315\367\340\246\217\034\277\247\372\200\225\247\376\240\212(]\326W(\355=\343\'\014\343B(<\226=(\212\033\305\'\024c\366\'\371?&(\314\305Y\'\007*\000\'\321\201v&\233\013O\247\211fs\'\300\307\315\'\334W\215\'\236f\251\247\004)\214\247J\307\202\247\300\253\000\200\010\254\000\200\252\013\000\200\255Y\000\000\020\326\000\200K\264\000\000d\310\000\200\224f\000\000\343}\000\200SY\334\247\276\262\020\250\244\322X\247\2145\304&\032\377\231&?\227\"\'\361\253\245\247}\3316\250\343\233\016\250\337b\000\000\313k\000\200d\007\000\200=K\000\000\234\312\000\200\014\215\000\200\363S\000\200]v\000\000\031G\000\000\200A\341\247\036M\003\250\t\215\246\247\0103\000\250\353\t\205\247\271s\276\'\361\225E&C\270\002(\362\255\232(\300\3673&\241\2506%\215\037\252\247ZGw\'\027\tM\'%\333.\246Z9\205\'W\344f\'!?\001(\200\326\244\'\260:\264\'M{\020(\0363\026(\264\352\027(\343\311m(\000\351A(2@C(\266\241_(\252\007\224\'\236\356\250\'\231\345\372\246\307\177)( \214Q(\236\241w\'\201*\321\'\0004\304\'\340\273.%\355R\310\247-&\207\'\213\276\017\250\nM\320\'\211\013\200(4\353`\'%\372\243\250O\000&\250\235\347C\250\256\014\305\275g\020f\276\005w\020\276_s\232\275e\304W\275\032\240\200\275\"\210%>\334\235\261>\025\357N><\250#\342<\324\3073=\2750l=\220I\236\275\372\341\302<\243\"\006>\325\252\251;\356\313#<\312v\373<5\335\254=\270\035\254<\314c\247\275a\320E=\235\204\t=\374\340\024\275\262\2447\275\256\264\214<\013\t\325\274\326^\223\274\026\331\225<\003\335 =f\204\306=G\361K>\315U\031>\367Y\360\274\210\275\230<\217S\356\274W*\270\275\235`\351\275y\177\311\275\216\231\312<\307\266\210;M_|<\351\313\270\274\3167+<\211%\304\274E\354i;g\237\352<\\j\333<&#\242mI\323=\210/\013\275E\302\242\273\2541\377\274\366=\261\275\003\243\344\275\312\374\313\275R\276\022\274\037\2346\274\023\320\231\274E\275;\275!\252\367<\206\030M\275\270W\235<\311\212\331=W\034\013=\232Oc\273/<\317\273\345\274\'\272\035.k\274\256\234&\274\330?\252\274\005;\310<\350\213\362<\004\003\226;T\321p\274\327\026\250\274\243#\031;w\017\376\274\005W\207\274\210\320\203\274t9\335\273&\"\001=/z\230;\035f>\275\203Ih\275D\210*\275p+\236\273{pA<\347\313\336\331>\322\"b>\270FC\274\212\215\222<\344h\274\270[J\010\273\232\374\265<\016 \307\270$\201S\267\252\205\255K>&^/=4\350\230\2754&u=J\204\246\274@@\245<\030\237\022\275\254\026\017\275\317\367+<\302\2420<\366\326e\274eY\033<\257>\234\275\301\020\036\276\225<\335\275\014\200\231=\274\331\204=\341\304\233=\206\3551\251\254\342>\347\007\237>\003\373n\275t{\211\272\367\263Y\275z![\276\374\n\270\276\214yy\276\321qw<\010\005\250=\206r\016=\204\371\240\274\272\247\371\273\323\366\322\274R\300\335\273e\232Y\275cp&\275\217\305\022\274\305;\226\240\325;\227\246\035\274\021\375\233\273\216\275x\273\231.\254;dHD<,\247\204<\025T\347;\253\275\203\274\305\267\177<\311\377\345<\220h\210<\010\344\240\271\207\320E\275\033\231\r\274$\241y\274\tC\"\274\276\302$=@\351\233\274vP\026\275\273\332,\274[\353\n\275\360\203\000\200\3127\000\2006\272\000\000C\234\000\000\223\255\000\0001#\000\200\336\'\000\200\251\316\000\000\225%\000\200h\320\326\274\226]\004\274\032kg\274\337\370\r\275b$G\273\333E_:Rw\026\274\246\'\230;\236\317\204<\217\002b\274\277\010\362\274\007S\233\274j\204\257\274-\205e\2741(\361\2745U\370;\225\241\003=\340y\014\321\205\305=\373\310\316;{7\350\273*O7:b\314\004\275U1<\275%\266\276<\007X0\274\310\362\217\273\307\202\222;\177\021#\275\2618\020=\031\272R\274Q\201\211<)\217\006=\014\200\326\273\310\324\006\274\206x~<\264\007\014\274\241o\237;\277\354\214<\227x\255<\354;m\274\275\257\361<\003_q<\351\300\005\2759\024\313\274\377\264\247\274b\340\362\274\221\320\2278yh\222\273\344%)\275>\335\277\275\230*z\275%\317-\275?w\027\274\210\271\304\274\256\031\351<3s\000>\222Y\205=\030\365\265<\346Y8=\304\331\346=\003\203M=s\014\030\274`\341\200\275\024\032j\274\000hh\273\352\253,\275^\316\344\274*\220\275=\242-\023<\224$\016\275\325p;=\224\376V<2\250\271\272\246Yl;\327\243\202<|\r;=\213\245\004=]\221\370\272\330E-\275R\307X<~\320\240\274@\207\365\274P\203\302:\355\273\000\0007H\000\000\356\211\000\000\n\321\000\000\266%\000\200\237t\000\200\035\265\000\200\305\312\000\000\267{\000\0005\310<<\236@x<\346\355O\274:\241\230\274b\223\023\275gK\020\275\256\372\030\274\371i~\274\2570\\\274\275\246U<\365\326\350<\345\206\355<\243T\302\272\257\035\322<\006z\260\273\333\267Q\274%\364\006:\215(`\275\265\262\354\273\'&\342\272U\354\";\201\2179\273\241p1\275up\002\274\316l:\274U\267P\274\244\232\033\273\006\213\000\000\306t\000\000\243z\000\000\305\211\000\000\355\025\000\200\375\260\000\200h\313\000\200\206\310\000\000\312\217\000\200As\013;1\201\"\3607\275D\3654;\202\021\224:#z\000\275\014\023\203\274\360\344\246<\345-\"\275\334\274\315;?\035\247<\360\252\311\273\241\332\274\274\276\221\315\313<\236\327E<\007#\272\270\3119V;\357\267D;F\262\333\273f\311\265\274\253\315m\274\333\371\t=\2440|=\327pa=\205\273\232\274T\366)\274\302Q\202\2747\236\200;wV\226;\035\265\203\023\305\265=\357\370\375;\350\263J=\225\375\014;y\257\005\275\330\323\232\274\376\014\255\273,J\205;\334c\356\273^(\017<^}\332\273C\255j\274r\372i<\3633\027\275\205g\200\274\372Y\217\273\205\335\275\274\243\364&:]\356l;;\260&<\013 W\274\000U\236\273\337k5=A*\034:\n\361\343\273\275\035\263\273\360\245\327\273\372\335\227\274\034\036\003\274\226=\345\274\013\340\304;\217K0\274]\343e\273\273I\271\274\271\224H;&\334_\274\275\344C\274;\363\320\273U\t\335\274\332\030\327;u\256\374<\251\371^\274%\031&\274\236\307\260\371C;\234\306\217\273\014\227\226\272?\221W\274O|\352\272,~\223\274gX\006\274\337>\261\274aX\203\273\272\345\326:\274I\242\274\303\230t\273\235\272\245\273\272\036D;\325Ii\273\255v@=\023\241q<\244Z\374;\247\212`<\342\002\000<\036\234\000\000\212[\000\000\034\311\000\000-\221\000\2002\322\000\000W\306\000\000\356\210\000\0005\'\000\200gT\000\200A\224\n<\363\311K;\240\2226;,\317H;\027\267\013<\344\006!\272q;$\2749\021/\273\320O}\274\210\344\376\274\313\216\260\274\nR\334\274\232\247\230;\036\213b=\2620\346;\200\354\303\272\026\311\310<\340)\304;wb\256=\365)\243=\320@\257=Y\356\214=\327\276(=\355\347\310=2\214\273=\200\376\355=\177\270\016>Yf\005:\356Cg\273\305(\310\273\325\360u;m\355\230\274\206lZ\273k\267\026:\303vU\274..\202\274\234\344\361;b\346i<\0317\276;\345\313\333:\330\274\371;\303)\272;\266\225\304\273\024h\244\273\241\310\210;\346\246T\322\362\034>2\341\033:T\2345\274\030\000!n\243\273wd\265\273I[A\274z\343Y\274xZ\236\273\037\r\002<\r\271\303\273)\'\313\273\355P`\273\336%W;\022`\325;{y.;\350\363\324<\017-A:\240\252\276\273&\2039<\315h,\273\001\246\036\273!\313\016\274|\014\"\274\353\373\177\272\356\313{\274\037\3742\274j\271\271\274\271)\203\274\206&\t\275\311\344\360;,w\345\273\261\027\363\267\026\244};\203\374^\273\337OI<\013-)\274\315\177\306\273\235F,<\277\354x<\374HF<\rC\330\270nN\204<\234\372\363<\005c9\274\302\210y\274\301I\222\274\313\327*\274\370\260\335\273\"|\035\273\265\263\343\273`\365A<\350wE:\307\362N\274\271\337\212\274\'\342\031\273\375\224\001\275Q\367K\274\200\002\311\274\022\342/\274\202\203\213;xU3\273F,{\2741\247s\274Q\254\255\274\037\304\037\274\021c\304\376-\274\265\372\353\273=\334\231\274^\237\033\274\253\030\006<\305d\005<\212%\276\274\002\260\207\274\273\330(<\003\230.\274\312\244c;\203\222\222=\032\247`\275\033\034&{\003\275\327\037\t\275\222\232r\274\213\320\034\2755\254\302\274\253\257\247\273\336\273\031=\367\260\330<\203\275\274<\274\312c\274\236)\310=\332\324\266<\256\210\300=\210\376\373=\216\345e\274HD\317<\234\376X\274\247+\016\275\345\357\320\274h\336\016\275\225|\016\275\273\376l\326\262\273\261\016\257\273\000k\254;\230w\255\274\306_\243\274\352\321c\2747\334\3549/.\353\274\017j\225:W@\241\274@/\236\2749\315\314\273\337\346\224`\273\266\002\356;\2207\017<%\315\303\241\372\'=\'f:>\\bj>y\313\204<\206k\260\273%pR;jI\031\274\333\262\220\274\033\016\000\274\316#B;\264\014H\273g\210\2059Q\3449\274AL\217\2720^e\274\371\306\303\273\333\333\212\2727\375l\2740/\245\274\020I\221\274m-\313\274\202\005\232\274\252`\005\273\370\365!\274H\333\237\274\346\357\020=\006\342\257\273i=C:d\034\363;\362\255T;\306\233\010\274R\327\225<\010\0141=\311H%=\311\002@<\023a\375=\335\222\013=\242n\367=^\022\355=\371%\272;\352-\206\307f\230=\202\216c>\246\216h>s\200P\372\373<\335w\323<\027\264\312<\017\006\262\273=\2400\2739\316)\275\227\306p\274\245\254=<\'\304x=wz\005=\231\027E\274|\364\301\274\235\300B\274\374\256\304\274\232J\r\274\220w\017\274\305\222\253\274.\226\244\2723\257\236\273m\310\223\274c\333c\271\352\035\242\272\332\221\031\274\253e\231:\241Gd<\030\376\307\274L\263\200\274\364\t\232\273\365r\311<\247\311-;\200}\247<\243\010U\274W\207/\275\3757\023\274\277P\'=\213\374r=e\322\005<\221\211\020;\2010I<\234#\217;u\326T<\005\014\377;\222%\307\272}\370\247<\356\212\t\274m\322\277\272Dn\227<\361bO;\374\266\376\273\303!\376\273pj\223\274\372D\226\273\023\215L;\376I\024\273\304F6\2758\'\311;o\340\322\274r\035.\275]\225+\275I\026\344\274\002Q\305\274\266\211\306\273\017d+=QD(\274\244[\000\274\305y\023\274\230\314\306\274\327g\244\274j\000\030\274\252\246*\274\305\000,\315\273Q\312/:/\260\025:})\">\274\354\014\323\273\353cP\274\304\t\200\274\247\261S;\353 \231\274T\213=\273\253uV<\233\210\206\274\257\300\364\273\270\246\220\273\n\022\231;\324\337\0248x\301\205\273G5H\274pE\027\274\351%\250\273\267\341\327\274\265\036\3509i\013\360\272\230S\312<\270x\206<|\332a\274\345.8;\306\034k<\351\3379;\246se;\274\024\030;o\317\004\217<\226>\236;+\304\217<\372\235\020<\263\356\260\273\006G;\273\230\026J\260E$\276\375/(\276\035\204@>\321\332\335<\025\375\207\275Y\345c<\022\n5;]\007n\272_\362d\274\330\215\220\2749\232g=#\t\253<>+\022=\337L\272<&d^\274D\376d;\027\252\242<\021\002\000\274Dr\252<\273`\204<\360\340\212\272kd\222\274pN\344<\253*\203<\014\206\336:8k\273\273\325\237j<\270\236{<|@\306\274\2303\344;\241\250]<\253\025\026\275\372\345\200;rs\245\274\306\376\013\275\331j\330\274\313=\232<&\352\240\274\263\360.\274U\226\251\274\303B$=\023\202\256;\360Ld<\370\331;\273!\376\243;\r0U=\003\017\025\274\037\237\257\274\005\017\325;\327j\232\2740\"\214=\266;\334\274i\377[\275\32438>Be\354\275\261\355\241\275\220\205\362=3\020\001<\332{)\275\245,\337\272.Lx<\346N\222\274\200\007k\274\312\331k=\026a\202<\001\'6\275*\235.\273\327z\r\274\220s\024\275\203\221\373\273W\'\355<\277\271\037\275\323\336\343<\251\325y=\305\303\002\275\236\001\030\275N%\350<\232\241\216:\273 \207\273\313\2436\273\235\203/:\337X\206<8\211\021\272\221 \217\272r\246\247;l\005 <\220\037\020\273\221\001\210<\034\376\322<\260T\200\273\3537\022\275\252\217H=e\303Q\277\027\326\274-\313\017=\362\251\017\274Q\215\t\275\037\3076\003\275\335/\240<\016\314\230;\023k\013\275\030\325n<\376[\320=\216\2258\275\254~6\275\nd2=\326}p\274\334\312;\275\306\001\211: \333O\274p\342\270;\343\310\361\274\356\204\234\272\r\031\227=c\376\274\274*C`\275\177\252:;+\247b\274\024\260m;\023\320\326\274\301x\317\274\362?\235\275\330\332\024=\345\230==\325\316\003\275\\\341\237\274HY\207\272\231.\321\273\263\231+\270\337\342\362;y\371M=-\320\'\274k\t\024\274u\2403=-\035\371\273\202b\252\274\213\227\271\274\354B\376;\304,\'=\006\341v\2751Tu\273~4\241=\332\303a\275\271\265\031\273\035rz=k\356w\274\362|\322\274;\256\223\273K}\220\2724\027\032\275\371\222\203<8\nx<}\270\006\274Mhy<\211?0<\227\312\222\274\211J\214\274\314\367\244\274\220t\235\274v\010\264\273{\317\243\273k\037\037\274\033\006\212\274\360mQ;7\003.\273^\301\t\274\261\236X<\202\211\260\274\307\272\024\274M3\366<\034-V;\347\327n\273\215\007\347\274\024\002\360:\022V\n\326V1\276GT\264\275\210\316\031>\3559\253\274]a\234\275\335\327HQ=\256\277!:\267\r,\275\217\340\024\273\347\240\235\273:\034\241\2754g{;\255\326\214\273\235&\225\274\237/8$\222;0k\373<\271\020\002=\207\2776=\353\204\245;vz\215\275{\245b\275\242\364\r=\315\002\037=U\313:=x\347\225<\301\270\035\274\215\347\222\273\026&\016<09H\275[\261\363<\324\365\240<\t\'\312;\216\027\231<\376H\300;\231\272\251<;\260s\273\026\322\014=?2C=\266\016\203:\035=\260\274h\007\312\274\324\215\t\275l[\007=\354\035j=\024\343W=\253\343\025=B\216\302\273?\314\177\273N&\223<\246\321B\275\355J\025\275S/\332\270\243\316\363:\306(\202<\213\307\212\274\274\002\022=\367w%\275\271\326$\274q\246\224\2737\322\230\274O\201;\266\240\227\274\270\225|\274ym\221<:\374+\274\247\331x;\242\036\014\274\275\263\210\274\330Pd\275\230\2430\275\032\\k:\330\226\241=W\n\274;\267\017\212\274\367\014\251<~q.\274E\004\226\274\037`\'=D\227\356\273\367\227)\275\241\306\236\274\320\014\307\274Hg\000\275!\245\203\275\301\264(\275\310\272\342\274\222\026\t=\322K\370\272\352\335\356\274\024\001\035=\225\t\327:\364\261/=g\354\322<\362\t\341<\251q\265\273B\305o\274\035\353w\342HoJ<\214\366m;[!(<\367$\r<+\312\254<\231_\243\274C\331,<9\016U=\013\371\007\274\362v%=\177\216\222<>\202\375\274\222\216g<\025a2<\216#\032\275\247\216\203\274\357\332\220\236\273\260\026\215<\026\330\303<\331\343\323M\365*=\351N\023\274\374\351\301\216\204\274\ni\316\273\272(\002\2745\215\367\273\265\265\300\273*\244~\274\377\313\310\274X\237\320=\177\275\227\273\226``<\267\304\341<2\227\375;D\316\335\272*s\274\273\267\370u<1\316J\274;\037`\274\243\346\320\316N\233\274a~\204\274\374\200\205=H\326\323\273\324\221\355\274\301\361B\274k\253\343<=WS=\\\n\177%\275h\203\365\272\025\210\217=\203\340\227=\004\315\250<\226w\377<\3517[\274\201\370\303\274\274\214\236;\350\235\260\274\240Z\000\274\020\301o\273Xq\262\274\325\'\221;\224\315\273;\346\242\213\274\257\357\334\272\377\tt;t\023|\274\345Z\017\274\035Z\330;f\2678\274\t\021\375\272\303V\220;\323\341I<\324O\375<\241\\m<-\346d;\030\337!\273\"a!=j\333\231<\225\265\215\274IV\374<\263$\247;\360u\315\274}\341\366p.\322<^m\333\275E\207\\=\023\206\235\274Ji\222\275\272r\336\273\246\263[<\366[\203;p\003\335<\007\242\202=\213Wi=\002*@\274w0\014=O\324\266<$_\247<\216\201B=N\304\364<>\206\025=\257\005@=^\310q=\250e\272Q\000^\373\272?\022\t<\370V\001\275]e\207\274j\020+\2746A\262\274\332\265r\274v\321B\274\201v\313;G\r\023\274\302\027\021\274\204\235\352<{\026\310;\t\274\320\274\303x\221:\323\236\211\274X\t\301;[\233\003<\344\303\355\273\215$P\274\273j!<\006\344\200\274+\246\304\274x\205@\274\010Q\317\274\3321\027\274\213<\301\273\367\206\333\273y.\013\274\t\345\355\273\327J.\274.E\366\272\225\031\343\272\265\260T:\342\007\320\274i\031C\274\336\016\221;L\250\263;\237O\233\273(\326\240\274\304p&<\326\177\373<\340/_<\365h\320\000\200\321\257\000\000\347\210\000\000%\233\000\200:T\000\000\267\022R\274\035q\276\274(Z\222\274\273-c\273\006F\366\274\242\221\032\275\031\213\306\274V\320\256\274\314\024q\274\2427\001\206^\222\274p\206\031\274ted=*\017\004\275\343eO;\365\352\221;\"\214\032\273\337\273\233\274\353\023\216e;\216\253\253\273\314\312\220:\220N\372\032J\260=\251\356;;\311\277\221\274^_\023\275\202D\265\274\221\257\330;e\321];-\204*\274\340\230\237\273U\261=\274\013\367y\274\226\254\262;L\302\336\273\357q(\272\210\022b\273\310\"\230;X8\022;\275\3425<\r\323><\240\023\016>\3242\037\273N\t\353;\021\202a\274\316\237\026\274\356E\274\274W\216\023\275\215~\227\2730\031%\275\020\035l\275\356.\371\274\020\370\217\274\244\310\363\274\257\360N\274\320\307\"\275\024\345;\275\365 \275*\027\n\275\210\240\355\275\200d\036\275M\243-\275\006\211O\275\212\245\030\275\354?\"<\364!\373\274RE\245\273@[\255;\216\240^=\017\031\201<60\004\274k\331\000\275\004;\007=\210\026\373<\020\262\214\274G\234M\274:\313\022<\233cs<@\253\214<\354\354S\256\321\274\207\244E\274\0060J\273\264\271\374\273\263\231\020>A\346\334\272\r\222\030\273\240\361\357\274\260\307*\273\324\251\353\274C\n\031\27503\003=O\257\030\275iH\"\276\375\266\031\275\227\014\033<\264\002\256\274(y\255\274\2733\000\000\024\220\000\200\324\211\000\2004V\000\000\276\236\000\200\315\320\000\200(\325\000\200\223\275\000\000\356v\000\000_\326*<\244X^<\272`\004=/\306\220=c\360\200=\307i\010=\037\364\031=\203\215c=F&\241<\221\223J;\335\3430\274\331\325]<^\326\213<\271\030\027=\036\034\026<(\025\r<6\210\221\274\033\212\234\273\241\264\021\274\207\322A\274k#\177\274\321!L9\006\226~\2757\345\t\274\300\3755\272\222\322\026\274m\205k\273\303\316\000\000\361\311\000\200.;\000\200.d\000\000\022f\000\000\323\250\000\200`$\000\000U\276\000\200\td\000\000\351\260M\273l6l;o-\250i\271\261C\215<\203\370j<\225\333\273;\214\216\035<\351\004\033\350-\240\237\273$h\213:\263C4;\245#h;\240\256_<\375{A<\212\005\305;\332\273-;\337N\241\273\343Z\215\274\237\261\r\274\263q!\274\355\321\365<\257\276\024<>\271\323<\304j6\271\025\312\272\251\2740\364\005\275\032\376\002\275\0229y\275Z\331\206\274\225=\267\274\301\200\372\274\3628\037\274`P\363;\305\360K\273\241\202\202<\206\275<\274\321X\343\274+7\177<\361\265\005\275tcM\274k\2358\273F\205\372\274n\275\225\273N\315\311\274\243\010\301\274-l\213<\372(\311<\271\025\316<\262[\330\274f\024\246\274v\313\247\273\217\254\244;\277\\@=/kO<\004%v\275\323\026 =\211b8\275\250\212m\373\323\273\273s\246\200\275\220$\227\274\215\327}\274\220\337\234\275V}D\2752\354\002\274\032#_\275\245\346=\275y\350\026\273\035\004\352<\324\035\"<\340\3662=\3450\006>m\351\231=m\306\375\205\'\275.\3634\275\356\264\030\274A\360\177;\207n\244\273\341Y\000\275\032\030Q\274\357\220\367\274\325\006L\274\026+c\274\264\315]\274\377\230M\274\026\211\230\274]*;\274L\350B\275\214\207\311\274\r\303I\275\232\2638\275wdL\274\226H\227\274\274\224\031;\2113\212\274+u\244\274&\"v\274\336\300\026\274-\200\272+Z\277;^\302\252<&\311K<\016\271\017<\265\324E;\331\274\305\273\215\214Q\274\342[\363\274X\373\326\273\262j\207;\306\377R\202\2751\226\004=\224i\213\273f\253\314<\377\002Q;\377\317\302:\344\275\323:$\341\302<\177\376o=\332\361\225=\245=\211=\r\357\010=\026\307\277<\375d\267<\207d\373<\355\373\316<\215\304\300<\025\313\020\274\323\366\362;\360\024\270\275\027\307\213<}Nb<\300\307Q\274\320\277\376\273\220\226\273\274K\206\352\274\337\373\000\274=l\243\275\257\256\256\275;sO\2743\310\'\275\\y\370\274\035-\237\273\224\345O;\327\023\335;\251\204\226;\030\212\300\273\215\241\302\274\270\320\312\273\353\306\234\274\341\007\233\274\300\031-\274w.\210<\016\316\022;\nl\262\273\026\253\221\274\246\325^=`w^\274\220\354F=\3764\034=3`\312;\035\226\376:\243/\236\273\337P\336;`#\275\273\326\313Z\274d\330;\273\372\204\010\274\277M\330\274\024\274\244<=\312\230<\207_\211;\036\306Y=\336P\024>v\364\233\256\342\227=\002\203!<\271k\210=>\254%=\025\212\034<\037W\200M0\275\346t@<\254\376-\274B\t\211\274A*\007<\213\357\n8i\027\\\2748Z\275\274\2130_<\252?\233=\200sl;d\372\277\274#\242\237<\007\325\260<\016\2649\274\r\304\236\274\\\304J\004\216\256=*Z\010=\316\303\310=xt\232=W\240N<8\233\304<+\217\271;\272p\031=T\376J=\3116\271=%\304\337\273SSS=\362\240\262=II\"\274\003~\'\274\222\004\321;\274\220\356;\243\037h\216<\325\337U\274\300X\262<\372\354\202<~\022\254\274\356(j<\224e\300<:u\212<\240\346\267\272\267\233\t8\016\256\007\274B\361\211i\217;=\276SR=\213a\242=r\000,=u#\017;\006\313\275\206L\242\275\240\022\362\275!]J\275\024,\250\331-\231\275\232F\031\275\022\352\254\275\013\035\006\275\331\222\210<\212\300\356\271\035V\276\273\215\306J\275G\251\252\275\214c;\275\372`\305:h\027m\273\022\244\217\274\275\200\036\274IH\310\274\371\036I=\275b\025=\353\331\223\272\206\245\000={\245\303\275\016j\220<\3200\334;\025\027\024=\225\260\010=+\306`\274K\274\027\275\345m\347;\321a\302<\236\361\202\275\337\356\276\274\330\343\207;\264\302\004=W\217\362<\364\321\000\200\245y\000\200?\220\000\000\342\313\000\000\377s\000\000bg\000\200-\257\000\2003\312\000\200]\317\000\000\335\220\245<3\350\315<\247n\224\275B\262\261\274\353JL\274C;\374\273\261\251\027\275\215q\346\273\330\353\345<\2132\365\271A\345\276:\325\361\375\275\222\220#\275\013?\001\000\000\213\310\000\200\222S\000\2006\256\000\200Y\'\000\200P\214\000\000\226$\023<*\022-=LS\216;\231%\374\274F\0319\275\312\262\215<\310\357\200=\001\263\267\273\021\273?=\303o\000\200\003\305\000\200\234$\000\000D\312\000\200\210x\000\000\300>\000\200*4\000\200e\031\000\200\312\n\000\200\307\315\037\275K\246\356\275R\254E\275v\357\320\275K\313\216>\320\017\372\275\021\374\016\275\213\363\007\276d\250\177\275\223\3527<\034\242R\274L\020\266\274\243\213\325\274,f\301\274)\201\201\274\316\025\t\274e\375E\274dM\355\273\346\243\020;\213\364\034<\2706\277<\331\'%\274\364\345\256=h\363\256\274\372\231?<\t\304P\273\000\214=;]=\240\272t\353u<\004\366\n\273\271\021#=\375\251\023\276\264\317\260n\000\200=\307\000\200C\226\000\000\271\236\000\200\266\231><[\364\020\254\202<\254\307t=\347\223\376;\026\"e\274\025=!\272\233\021\252<^\020,<=\r\255\2749\020\025\275\027)b\274\200k\026\275\333\315W\274\022X&<.\314\025\027\000\000\331\314\000\200K\315\000\2006\214\000\200<\311\000\200\341a\000\000\242\320\000\200L>\327;\035\215\207;\033x\214\273q\326,=y\376\025=\344\217,\273\345\252\363<\032\204\002=O\'3\274\022\300\207;\366q\023:R\320s\273\365sV<\227\317\351\274\255\367[\274aZF<\370-P<\251\3432<\225\006\331;r\001p\274\226\373\235\274\n\236v\274_\210\021<\327\370`<\207\275[\272\315\261h\274\235U\224;\242\024\233\274\000\277\311\274\266\210\223\272N\261\014\274\303=\014<\034\023w\2733$Z\274%\t\214\273\311\332/\274\256\301\252\274M\250o\2748\003\252\274>\016\213\274\024r\357:\313\305\262\273\316e\227\273aG\265\274K\201V\273e\035\220\274\220\002*\2743\327\004\274\036\247v;\262\244k;\232\001\315\273!\252\313\272\210\277\036<\326\214\2618\230\311\251;s\267%<\3070+\274*8u\274\311\335\224\274$b\203;\261\364J\274\361\250r\274#hK<\332U\2609[ \272;\231\272\000\200\020\242\000\000||\000\200\214\245\000\000 P\000\200\241\261\000\000,2\000\200\234\302\000\000\317p\000\200\251\036%\274\354\365\230\274\372\3270;\305\350\023\273\t\367\345<\335\240M\224\241\273\237\014\237\274J\220\307\274\265U\301:1@\255<\362\246\255<*\342U<\274\217\023=\265\345u<:U\215\272\275\254^\274k\226\236<\266\362/\272~\027E\274a?\272\312\252\331\273#\211\322\274\345\246N\274cg\321\274|\014\020;*\301l\273\216\311\262<<\205h<\323\310\265;\350\365\023<\316Y\000;(\206H<\243\303B9\266\225\360\273i\354\371\273}\304\022\274\374`\232:\375\357G\273o\254\207<\332\272\326;\357VA<@\014\360<$\322\r\273)\346\321\273(+\360;Y\262\276\273P\027\210\274f\022\220\273t\240\370<\377\311!=,h\206<\367\307?\000=p\021\242<\267.\207<\376\347\021\274\224\037Q<\030\266\032\274\2762-\274>\260D:\006\374\206\274\262C\262\274\333OD9\310\302\215\272+?\253;]\337\371;\203\237#\273\335[F;..\373;5\'\034\273\202\0310;\263p\203;\001\t\035\274\304\242\220\273\252\013\225:\000\004H\274\256\010\003<\016\023\017\2743\023\027\274\360a\262\273P\337\230\273B5\000\2001\307\000\200]r\000\200\375\273\000\000\201\314\000\000UI\000\200Y\311\000\000\024)\000\200*\315\000\000N\325\010<\207/\034\274Q\\\275\273\025\027\307(L2=-:q<\324\257\017=;\030\253;\000\037\253;\321q\020\274\222\212\330<,~\317<\366\3524<_\275;\302\005\3009z\273/<\365\306\274\273\243\212\002<\034\014\035=\210\367\'<\310\'r=U!\030>\265\343\222=n\333\341\273\276\\\021=\301Od<\335;3:\000\377*<\262\036o7 a\220\273\235H\225<\375:\225;\245\202*\274\307\276z:?\241\341:/mX\275?\300P\275dm\367\273_t{;]\221\206\2741[\331<5\232\202\274\0224\202<\373\026*<\240S\356\274q\256B\275s\253\026\275.\245K\274[\374\324\275^\360h\275\372\213\036\275\216Z\237\275\330W8\275\325\273\301;\273\211\212;\361@\"\274\003~\242;\300\253k=\010h.\274\006\014:;<\274\317<\243\006J<\232\334\213\270\0241\233\273KTX[<\2245\002\275\'\270\006\275\204wK\275\2117\333<>I\372<\353E<<\\as<\004t\316\274\323E\316\274\276\213y\274o\251y;\031\313\035\275\270\265\030\275\330Y5\275\354\3134\274\220\274E;J9~<\000qkJ<&\372n;\305\203\026\275\353\222\010=cHN<&g?<\033\316\020\275\201\322\323\274\245\t\225\271\006|\305\273\353\372l\275\316A*<\0239N\275\017\267\t\274pZ\247=\177\230s<\273&\211=p\312\334\275Z\244\327\2726\010J=:\034\024\274\373C\035<\257I[=\344\311.\276\031y\026<\264\022\345<\200P5\275\266P =3\rE<\266H\245\274+\301\230\274\002V\215\275sE->\356dD=c\226\246\274\361\234\202\275\304Q\"\275,\320\217\274\3230\225\274\244\201\323\274\013\376\336\274c6\210=9(\007\275[/f\274>\005`>=\212\352\215\274\221L\236\274\274\270m<\270H\022\274\204\254O<\361J\032<\365\251\370<5?\260<\t\014\266\2755\024&<@>\346<\215\365\343\274(\031\033<+\214\204;j\331\240<\254j\313;\3533\314<\316\2172\274\335#\326<-\022y\325\226\273\024\2210\275\347w%\275\341\257-<^H`\275\232\252\330\274\372\341\225=\306.\211\275e\nn\275\323\226g=C\333\360<\006\327\024=[O\006=\301E\000=\321\274\024=8\365\366<\372\177\026\274!\251\243\2752\206\024<\001;n\274\373d\370<\345\262U<\030n\207<\305\013\'=@\005 =Okt<\3411 =td\231<\262\204l\274\276\246\241\274\327v\355<$\337C=\372\t\010\275\362k\232;#K\324\273hD\276\274\027,\332;$\200\371;r\263<\274o\222\033=\3673\320<\357T=\274\020\217*;\032\261b;\242I\310\274A\2575\275\260\003\034\275x.\2269\356\260\232=\236\341\270\274\311\225\207<\027\360\274\350\271%\275\rh\340\274\266\277?\274p\357\351<\027\337c\274\377`\236<\026\201$=\357\t\273;\356\241\254<\205p\220=\373*\211<\232\010~<\027\202\212\274h,\361<\265\310)\2719\204(\273t\035\330<\222\254L\274\205\331S\274\205\035\370\274O\361\205\274\301?\254<\211\337K\275\003\001\237\275\325gl=\313J\260\274m\023\241\273\330sn=2#\000\200}\005\000\000L\272\000\000\335x\000\200\272\204\000\000\321\232\000\200ViV\2757\372\313\273n\025\r>\214\306\251<\363\220\331\274\252\242\"\274\236m\216=\323z\030<2\216=\275\243\325\343<>\016c\274\362VJ\275\366y\031:x\2529\273\306\303\206\274D\223\326\022K\247\275q\275A\275\026\320\316=\216\246:\342\351j\275\035\226 \275\t\302\217=[\302T;\261\242\206<\330\345\210:\322rm<\022^\332\273\000\256o\274\314\017w<\302\202\232\003x\275\216r\006<\203\357\202;\330Y\245\273\304\274\345w\017\247\275\226 +\275\240\372\322=\343\360\265<0\326<=\236\363\226=\220\255\256\274fjp\275\240%.={\270\003\273\223\".\275n\206\034=\261\000\310\274\006\270\037\275\332`\242=\001\n\r\274\334\'\013\274\342\221M=p\217\257\2734\324\272:\326\246\003>\237\021\247\273\007\222\256\2755l\216>r\233\014=\010dv\276\001\006\036>\345#\017\275\214\255\032\276\244eO=_\tZ\274K+\314\2743\337!={\205\244;\222\334K\275K\'?=m\302\271\274\223b\364\274\206\'Z\274\352\211\274;\2149e\274\332Z\265\274z\260\225\273\330n\305\273\037A\227\274\202=\222\273\241\275\374;{~\324\274a\345\323\274\346\024-\273\014f\215<\375\323~=\370{\027=V5\014\274\241\377\335<\376\236\316\273\315;%\275\206f+\275~9\214=\245\307\237\275\032\225\272\274\202~=>\233i#\275\374t\027\275\177\313\222=HYE\316\033\002>\362%\322\274\216\220\235=o\257\373;\257o\266<\364q\3078\017\330j;\342n\311<\014\371\021\275\270\304y\274%\340\204<\322\2252\274\311\252p;\312\023\304\273Q-\223\311\000\000\314\007\000\200{6\000\200\215\324\000\000\017\271\000\000\033C\000\200\233w\000\200f\332\257\274\333\274\226\274-\331\224<\354GD\275\236\337\322\274\262\336==\027-$\275h\321\311\273[\002v=\235B\367\274\352fZ\273\331\250a=\354\316\220\276=\201\021\223?\301\032\275\252\035\005\274\222\342\356;\0317\r=\270\302\223<\\\334\335\274\325\354\317<\002\334S<\346&$\274\010\016N\275\341\016\250\274C\367(=SZ\277\275PF\024\275\037t\265=\372tL\275)\312?\274\354r\214=\275\321&\274\221?\276\274\006?,=:@\010<\017\243\007\274\034\271P=\356\247\313:\021\033\021\275\\\2024;Cc\326\273\007\243\232\274(p\374;\277\254\r<\335\027\030<|\313\005=\232m\361:\247\322U\274vI|\274M=\034=\357Su\274\274g\r\275\310J\240=\217\300\222;v)z\275\263W{=\304\300B\275\0062\202\275\302U\024<\273X\375\273t>>\274\\\231\256\274\315\214\234\274\330\335B\273\363\311\323\273%\027n\274\257\337\223\273\243\345\367:\204]\254;$\023\007=\264-\266\274n6\202\275tF\265\274D\337\2029\010\202\260\272\203\360\005=\243\236\334:\256<\014\275\271O\002>\036H\322\274:\313\254\275x=\242>]\355\017;y\274m\276\035\256->\025\362S\275\361\360\"\276\313\3260\274\020\303]\275\322=\246\274T\365\177<\326\032\362\271/~\363;\257\334\213\274Y,\333\274\260\374 <\237\223^\274\357\265\2079n\024\342;\341\036\252;k\366\030=\362\333\243\035<\005\"Z\275\331\244\326\274\260\036\205<\325\304\335\273\207\033\271<\351OG\274\346\324\216\274\266\270\316<\327\264\316\273y\344U\274\020t\256\274\005S\244\273\274\314\022X=x\242\000\000\266g\000\000X\266\000\000\247\215\000\200\247\200\000\200\236\205\000\000&{\000\200\210%\000\000\333+\000\200vO\024=\327\261]\274\365\242\023\2744\215\205\236\273\365\263\314\273\217\233\220:\212\013\242\275\003T\244\275ek\004>\212\324-\276\020|\r\275\211#\273>\3050\000\276\303\337\246\275\202\005Q>\207T3=\036\037\313=\246\263\232=%\200\252=\326!\323\274\327\221\032>\344h\310=yg+>\2345\n>\254\347P=|\241r==&c=\246\265e=\326\201q\2741[\273=\243\235P=4\304\271=\362\306\227=\221j3\274\373\266\367\274c\007\312\273\'G\206\274v\200\244\272(Q$=\r\347\372\273\304\260\340\273\027b\242\273lZ\334;\220\304\252\273M\247\226\274\330\263|=2\346d\275\261\226\270\274=\240\317;\255\037Z\275(\r\362\274\255\267P\272#wg\273X70\274\322\307\343\274\242\323\262\274l\272I\275v\334\232\274\004\235@\275\306\310\345\274;\306f\2747\315\251<\253a\271<\362\352\223<\316\221\356\274E\350\001=1\327\306<\2164\333<\010\036\323;\374\261\231<\352\030\203<\271\236Q<\222a\024<\240\355N=\262rk\274\253\'\251\273\337PT=\375\327\247\275\207\351\223\275t\336\022>\306bS\275Z\347/\275\035a\002\275\001s\010\275\034\210I\274\3621\240\274\337k\016\273\365W\216\272X\205\025\274LLj\274\274\264\252<6\215\276\273.\374\320;a\333\321\275j\311\204\274\n\251\231<\241\353H\274\001\267~;TL#;\030\033\\\275&y\r\275~\025q<\365\216\267\237a;\247\034%=\224\304\021<\005l\346\2730;\005\275\372X\013\2751\346\227\274\342\334\216;Wl\021;\203\312\323\274\013\002z;Z\240\000\000\004?\000\200\374\201\000\000\271\312\000\2007\321\000\200\3027\000\000\033\'\000\000r\311\000\000\006\004\000\200\366\347\262;\314\370D\275\206\212l\274d\266\000\000\251\270\000\200\026\244\000\000\307)\000\000j\315\000\000\304\303\000\200\215\236\000\200\300\177\000\200Q4\000\000\330t!\274\337\217\262\274\242\253^<\027p\264\274\020#\246\274\206k\030<{\'s\274\320|\272\273\322\213};\263\365\201<\255Y%=\222\225\311<+\274D<\374\325\025=\331\315\313\273{\0106:\035\177\020\275\n\247\244\274H\244\231:4mm\273\225c\204\272C\247\007\273\t\2727\275\255&g<6\234\'\272{\372O\274\336\236\260;Ro\223\274#L\007\272<\275\264;\235?\026=\312\304\274<)\312\n=S;\304\275v\277m=|H\022\\\256<\311v\326\273\001\362\353\274\275\220 <;\237\032<\033Q\242<\345z\010\275\207TT<\\\004\222\274\311\263\023\275k7\205\273\013\370\213\256\27366\205\272\t:\007<\271\221\210<4)\377<8A\035=\216\255\005=\"\177\277<2\324\031=\033\357\355<\324\3001<\3442\241<\274\324\376;\355-\217\273\353v\"<\245\025\013\274\226\036\271<~\352,\275oT;\274\251\204\262\273\210\340N\274\320\200\240\274Y\274\000\200-9\000\000\307F\000\200Gj\000\200\217%\000\000\370\255\000\200\204~\000\200\276f\000\000\371\311\000\200)\004\227;\030\276\377;pM%<\305\337\000=\016\031c\275yU`\274\377%8\274\237\326\372<\300\032\r\274S\255\000\200\372\212\000\200r\234\000\200?y\000\200QS\000\000\027\243\000\200g\215\000\200\255*\000\200\253\216\000\000d\2141\275\205v3\275\264\202\027\274\260\306\322\274\240\363%>\235!\036;93\213\273d\227\207\274\355\000\023\273\277\303\354\274\362\260m\274w%\027\274R\313B\274\214I\220\275\275\325\273<\001\334\267\273Y\320\034<\317\254\261\273\260\235\366;M\177\244;\347\365\237;\310\253\210;X&F\031\252\274\031\247*\275Z\256\323\274}\223\003\275#RM\275$A\037\275\303\255\343\274Y\334\212\2755=\013>\344j\205>\332\023)>\347\003n<\203\347s=w\342\350\274\251\313\321\275\230\303k\2765\0309\276\311\260\270<\352\202\250<\330\240H=2\237\237\273\252\321<=s\000\264\271\367\273e\274t\336 \275\277\006\360\274\207\334\272=b\314Q=\000\035w\275\353(\333;dG\340\272\024\343\020<\321l\200\275\234\204S\275TI\255=E\271\002\275\347\310Y\271\333n\251<\014\r\020\274\014\376\335;\202\372\301\274u\355\022=\014\013\235=\314)\000\275\230\346B\275\346\262\316\275b\334\262\275\313\256\357\016>-\265\246<\315-\013=\221\371\260<\207_\210\274Oo,:Ne\302;\274\227\t\274\212\316\266\274\230\275\023;\2739\326;\344\323+=A\2022=\327\234\222\274\326L\303<&\0173=\026\205T<\365\364\005N\322\204=\033\244\355\274\222\316\236=\013\273\320\273\3474\347:\276\235\275\274\250\202\257\273?\224\310\274n\265\231\274\347\270\323\274d\266E<\346\241<=8\3767<\230 \207;\321\366e\273\240\"/=\216{\224\274\237\211\371\274\366{\316\273\234\224+=E)\306<.\212\014;`\352D=4\031j=\312\010N\274\002\262\243\274Y\223\331?\271\357\370&;\204\327\235\273l^b\275\345V\355\274\223\250\334\274Lq\317\274\276\3225<\026\246\261<\376\025\220)+1=}Q\371\274\004Zn=\321\0077;\016&\000\200h\217\000\200\313\250\000\200\207\234\000\200\245.\000\000\323*\000\000\311\n\000\200\262#\000\000K\304\000\200\022\203\340\274\222kM\275\022)H\275\347}\246\274\247\373q\274v)\024\274\241\007\002=)\240\212=V+\306=\354\222\030\274^\222E=\320%\027<\372\227s\274\340\000\017>|\357C=I4\221\275C\374\210<;W\244\274\005\254\034\275\005\212\231\275\t\223\227\275v|$\275i_F\275\224\357T\275W2M=7Q\006>_\343\261=\327Ag9\264\202\353;(k\245<\371\361\371;\350\303\312\272u\316%\274\000\035p;\335|\226<\226\024\213<4\203\377\274\235}+<\226\274\t=\017\265\021<\272\343\025\274\303\222\303\272\220\211\336<\260\013\333\274\203\363\315\274\213=\027\275\230\277}\275\313\004%\275F\357\\\274\360\267)\275pM\376\273\253#\025=\312-\220=\240\221\227=Y&<\273\326\257\026\275\311M\320\274\302h\211\272q\226\032\274\013\271P\274U\307\225=\023\370\212=\017x\025=,\367K\274{\361/\272\345\263\331\274\027\216\n\275O<\207\275w\206-\275R\240\023\274h\024\027\273:\037\375\274\377\222+\273,\272H=Y\314\332;\215\204\250\274Y\351-\274\314\205}\274\037\013B;\213\276\226\274j\241\372\273\236\2329\275r\227\035\275\252v\233\274\205\236\246\274B\007_;\320\353\005=\360w\021\274us_=\320[\227;U\370\360\2740{\303\274\261\356\312\273\tn\201\273X\320\031\274\223M\017\275\361\033\020=\321g\n=\031\361\013=\235w\202<\234\005\315<\007\204 \274D=\003<2T\200<\032\337\260\274\311\205X\275\362\036\260\2746\r\263<.6\365\273\372tI<\004!2<\362(S=\306-\272=\277\021\343;7\332O\275(\243\274\275\230\212\220\275\257Q\007\275\270\316\336\272\216\023\361\274\263\020B=\234O\322=\340\271\270=\261\262\016=\276\036}<\334\343\307<\332e\230\272\tY\"\274S\013L<\242SX\274\313/\204\275\261f\346\273\214\353\363\273X\000\307\272\376z\310\273\376\212\313\274\017*\212\273G&\205\274|I1\274\0223A=\025\257\225<\375GF\273\363}\240\273\213E\361\274\356}7\275\267\007\200\274\315\370\230\274\022\376O;\347\232\026<\034o\232\203\312\230>\304\337\036>&=p\2734\3279=\367\3432\275\214\241\002\276\270\002\204\276\007\251?\276\206J\010=wn\025<\324{\\e\267\274\004\315\003%\213\277>\3304}>\247\326\311=\360p>>\006\2266>\274\253\302\275\036\2759\275w\341H=\230B\002\276\244\2355\276X\274?\275\202\236\207<\274\234W=\361\255W=h\3269\274n]\340<%?#=Z\2139\275\336\354P\275\326J\300\274\000V\014=\263\317>\275_k\271\275\3374\247\274\241p\211\274\233\365\007\274\332\331Q\275\330\253]\274R\177\n=\323\270\255:\r\213\030\274>\210\010=\305\256>=\270\013\224\275G \274\274\343\337\321<\226\261B\275\355\227\227\274\027[\235<\037\303\316;\336\353\244;\245f\370:6\221\031<\300Y+\275\333\326\262V\366\207\274\244\241\372\274\354\001\205=\202\313w<\023\351\217\274\020\340W=\322\200*=\035\304v\274j2\324\274\254l=<(\247T\273\315\202\023\274\231\237U<\001\221\017=\n\004\375<\344\222\346\273<\177b\275\006\325\036\275\2071\300;NL-\275\022\345\317;\377b\235\271\350VS\274\036\312\316\274\226\220\274\274E8\010=\301\244\017\274\365\271}:\361\177\333<\245k\347<\355\212\227;\234\307\320{z\274\037\257L\275\214\260\316<\247Z\023\2745e\035\275\001,\221\275\312\3451\275;_\216<\217u\247<\223\326\356\274g\364\303\273SU\217\273\346Ek=\033\276[;\337\301\367\274\202\255V\313<\240\324\021\274\'\3463<\353\227h\274\036mq\271.\325\257\207\275\340\230\233\273!\314<=\342\021\336\274U\016\374\24654>0dY>rn\270\275\t\022\313\275\307\372R=\305\324\357\275\210\223\027\276\215\325;\2745\023\231\274.(\003<`\253u\270gT\364<\361\246\262\273t\322\330\274\201\203\322\274\374\360\217\273Y \014;]\251\225<`\271\323;\223\315R4\247\261;\031\254A\274q\023\007=Z\243\244<\243x\307<\371\232\326\274L^\204=\337\256R<\254-\202=\314\200G=\237\213\231\274\370\025\036;\232\312\005;\315\364\232;\356\260\031\275\356\302\233<\247\t\325\273\224\374\374\226\274\265\251O<\031b$<\370\274\262;4+/\273\300Z\230\273W}\201\272+\r\036\265\274\204\240\001\274\257\023\372:\242\311\333\273\276\250\000\0008\323\000\000\215m\000\000[)\000\200\035\206\000\200\373\234\000\000m\312\000\000\245y\000\200\242\316\000\000\207\302\222<[\273\r\274\256\343\353;\365\371\347;\371\314r\274f\234\344\274\346\251\311;q\225\362\273+|\242\273\344$\347\274\336,\303\274\264\000\203\274\247\217\006\275\234\235\t\275n\217*\275\306\255\314\274\237.\320\274i\241\363\274\364\235\223\273\334!+\274\272\364\026;\020\333\307;{)\230\274\331\206\037\273\335p\223\273\372\310\346\272b\"+<\177D\000\2000\231\000\200m\312\000\000\253\177\000\200O\255\000\200f\213\000\000\005\215\000\200\020\260\000\000\314h\000\000\240\260\344;\nR$;\036Vg<\014\262\013<\257\351\021\274y\014=\273\235\206g;\333\365\036\274+J\276\272\233\350\243\274dl\006\275\021\001\274\274\236\035\2608\356\270w\273\325T\n\275\227s\270\272\3751S;\322\364\206;\220w.=O\252/=\016\304\"=Y\003\000=\004\210#:\272\300\234=~\311\315<\265\232\275=\004\027\327=\360t\030<]\274\206<\300;%<\n\364l\2747\3319\274F\305\213\274\336,\375\272\232\321G\272W\240\201\274%\226\256\273-\230\232\272X\0067<\200\362\227\274\004\270\275<\241\033\241<\272\311\225\272\342\2442\274\240\020\303:\267\001K\274y\331\325\273S\373)\2734\274\224\273\374Z\004\274eS\224;\202\267\306;B\233\344;v\310=9\2110E\274\222\335]\274\272\226y\274b\256~\2747y\212<\205\325\321\273\274B\031\274\332\307\272:\202q/\273f\233\022\274\330%_\273h\242\332;\307V\325;\006YS\272A\016 <\205}P\275\334(9\272\026ut;\307\303\377;\364k\031;M\373\211;\255%\227\272\004H`\273\3179\353;\325\217?\275\302-\022\274q\312\3068X \302;\312o\266\275z\333i\274\225_\231\2752\331d\275\345n\227\275\271[\267\275tp\037\274\201\254\031;\366\221\022;ur\235<\347\261\200<%\263\232<\325\321\265<\201\241\206=\000\275\037=\022\332\271\273o\024\341<)m\357<-\275$\274I\240\303;Ih\262<`\250\204\272\242\254\267<5h\325=M\200\033=\326f!<`\352H=\036\330\236\312\270=\370\006\213\274\0170\354\273;\216\'<)\353\200\274w\321,\275K\340\256\273\032\001m\273\010\241\314\274>\0019=\005nL\273\3714=;\356\320\244<\014(\344\274\333\214g\274H\030~\274\340\235\374\274\005\353\326;?\234\351\274\352\202\002\274\214\'@\274\213j\r\273\332G\270;\275\t9B\237\030\264\005=J#\230;J\035O=\\\332\323<>\347j\274\205\251\210;\216\303u\2722\310\007\275\n\007\301\273\035(\232\274\367Q>\273\205w\311<\365\212(\274Zk\236\274\323.\013=\360\335\342<;Ww\275\342\014r=\351r\037\275\346ND;!\226-=\'`s\275\320>\2379\244ng\273\305s\021<\271\036\331\274\325\336\212=\317\205\227\274\204\216N;\234V\243<\357sz<(-\000\200\254\236\000\200\304\260\000\200\350\001\000\000\036\216\000\200\275G\000\000\013s\000\000\271q\000\000\327\317\000\000\310\350^\246E\006=W\225m\274\263^\265<.\377\262\274\n\242\000\000F(\000\000\2205\000\000\013\307\000\200\300\322\000\200:\310\000\200\355\267\000\200\010\236\000\200\262\256\000\000\214|6<\264\372&\274T\225p\272\n4\353\272\003\345\014;\242a\206;\235%{:\307\250\217\273\261\327\273;\370\r\200;y\333\355\273\240\375\200\274\010\030 <\357\262\273=\331\035\027<\032\030\315;\200\355]\342\276\202=\177\367\t\274\\IE=\304\315\205\272RVx\2745=\311\274\364\005\303\274m:\255\274d\273|\272\255] \274\306K\007\274\272_\217\274z\343\332\273\352\2270\275\374%n\275U\215\352\274^\264\213\273\351\003.>l\245\242<\036\264J\275@2~\275\337\322\204\275\027\217!;\006\004}<\336\200\271\214Q<\211\030\303<\341Q\007\2756\257\215:\346\256K\274\235\355\200\275y\022#>\027\214\'\274\222\3644\275Ky\026=\023\364\036\274K\265\003\274J\366O;\001\330\2669\377]\205\274!\375\235;\262c\013<#\336\315;\312;Z\274\017\225G\274\230\0227\032\026\235<\0100\331\274\023DG=,\307\032\274\323V\323;yv:\274f\327d\234:\217\310\000\200\373\310\000\200\364\005\000\000\320\320\000\000tM\000\200v\233\000\000\0058\000\000\265n\000\200\316\254\000\200\030\006\036=:N\241<\272#\244\021\224<\370z\027<\242FS<,8\255<\252\363\002:y0w<\240j\320<8\322\253;\3271\342\273\275\3579;I\000\304;@\367\216;p\316\347;)Z<\274_\303\022\274\t\217~\273\244%\007\275\204Q\224\274\226\363\027\275\336\277\275\274k\217\001\274.\337\256\273$\024\000\200\270R\000\200\023l\000\000\214\314\000\200\301V\000\000\324q\000\200\202\243\000\000\357\234\000\200\007r\000\200\244\255\236\274|\\h\274V\333\202\274u\335+\272\305\302\233\274J\372;<_]\303<\021\317\334:^\367\226;\244\352T\274\306\256\305;\317\245\3068s\263\360;\260\250k\274\201\302&:\363R\317\273\210\200\225;\340\260\274;,/\241;\316\337#\275\2471\216\274\3179\026\275\033\317\223\274Qk\270\274\023ld<\230\261\217;\314\024k\274\013\206\375;\302\\O\274o\000\216\273`\337\337<\203J\210\275D\313l\273\273\330\200;r\004\274\274\254\264\025\274b*\343\274\372\274[\273\205\217\262\274\033e\003\273bx\013\275\226\\i\274e\036\265\274{\342\276\273\316\350\337\274=}M\266\274\026q\220:\006\"\220;Nr\304;F\033\001<.\306\001:\016}\204\273T\245\223\274+\350\252\273\230C\000=\202-\266\273\025\200\271:c\306\2219\r\254\334\272\334G\214\274\326g\251:\225#?\274\277\336\273\273\365\313\212<\201\316a\274\222\245\343\273\004\256B<\365?\267\274!\303\004<\025}\t=\212\316\263<\256\231\226<\373\007!=\3672\245<\2228\005<[\307\371<@\031\262<;\226\321\273K\007\260\274G\347\023\275u\034\334\273\2505\210<\335\321/<\302\020\003\275\326\332\222\274\027\336\230\274\002\255><\255\252\010>\364\2767=\306o:=\253\355F>\325\356\321=\241\242B=\360\332%>\016Hs=\355(\n;R\315\266;?p-\274\266K\007\275G9\304\274\251\025\2209\354|\230\273T\2510<\\\255\251;T\340\003\275\030\220\214\274i\342\000\275\351\004=\274F[\336V\200\351=\302\365\3170=\354\237\217=f\341{=q\334\331<\202N\306<\2262\343\212\343\273\213\211\266<\035\324\225:\324r\013=Z\272\\<\217gv<\'\274H;Q\377\340<\261\261\024=^n)\274\354z\203\273s\267\200;G\037\234;\311\302\350<\271\232\364\272\267\332|;\354h\363\272\307\014\307\273a\333\276\273K/\370\272h\327A\273\242\035R;*t\000\274_i\256\273\214:\033\273\270\271w\273\316\306Z\273\352\032\000\200\007\313\000\000^X\000\000g\212\000\200%\031\000\000\262>\000\200\354\217\000\200<\273\000\000P\213\000\200\323\340\336<\206x|\274#k\312<\217\212s\274D\310\013\276Q\240\306\275v\336\014\274\212\001\236\275\261r>\274\237\254\000\000/)\000\2006}\000\000Z-\000\000\347\024\000\200^\313\000\200u$\000\2006\2758\361\034\275\227\320?\274\357qi\275\277\004\010\2756\353\230\272\036\351\212\273\023\252A\273\2461w;]G\350\272f\3441;\375\2644\2733\277\277:\227E\311:d\364\026\274\376 >\274\335\0055\274%:\026\273\000\362\250\274cz\314\273\331\340\367\273\'b\224\274\317.\216\272\340\"\224\274\',\213\267;\021%[<\232\376B<\335\214\216\274\257\341 <\351mQ\274\1776\367\273\360\025\"=\263\211\010\275\216\323\322<|\365\302=3\232\222\274P\246>\274I\021W\274\324\\\301\275\241\0230\274\222e);\341\024\367;\270o\233\274|\366\324\274\212l&\273\\\235\376\273\271\244\027\275N\027\022\273\007\346\250;\363G\366\273qX\267\274\027\307\276\274\362\202\224<5\324\325\272#\321\302\274\375J%\2740r\261<\304_\004\274N\251\271:\037\213\300<$\237\220\274\260\rI\274Z4\311\273e\212\n=Eo\276\274\240\231\270\272B\265\254=B\260,\274\001\207\234\274\237\225\236\272-\264\325\275t\313\316\272\363mF\274`\300e\274O.\234<\303\333\236\274\200\020W\273\310uV\273\213\020\036\274\327\225`\274\263#\206\274aDY\274\0237\215\274\300\032#\274:-q\273Gk=:\217\355\203\273\003\307}<9\234\216\273\377\352\017\274Q\032\375;\201\027\262\274\274\033/:\206\244\203\314\274\374\344z\273\345\005\376\274\367\325b=\037\254\256\274\243S\257\274\3533\364<\2271\005=\233R?=m]\006=\375\303!\274\265mL=G[i\362\273SE\374\274l\017H\275\273KC\271\355E\000\200\235|\000\000\222z\000\200(\005\000\200\346E\000\000Q\315\000\000\003\250\000\000\2048\000\200n\314\000\000\203n\010\275\022\360\326\274H\234\216;g\240\017\275\373%\261\273\2024*\274Nd\220\313\236\221<\272\230\n\275K\317\204\272\354,\217<\'\251\\\274_1M=\220\024~=X[>=\263eG\276\215\';=x\000\274=yZt<\227\353\034\275\205Gj;\225\231\215\273\004\300\000\275\260h\2153\237\211\275)+\020\274\202\360\277\275!\324\225\274\357\232\300;\262\273\177\274K\234\214\274Et(\275\225\356\020=\340\2768\275X$\377\274\335\222\234\2753\307\032\275\036J\327\273b\360\253=\305\036\364\273\342\273\017=\354\365G\276\203G\002=\276\016\007=&a8=\225I\212<\330P\276\274\346\232V<\2143F:r\003Q\274ZA.;\377T\211\274\332\336;\274~\010\360;C\250\377;B\266\n\274\244\332Z<\222a\343<\"\340o<~\274\241\275\274\374\216\273\331\267?=r[\271:~\314\365\274\331\337N<\035Q]\273\354\214\004<\177\037\026\272\312\355\361\274\367\264\262\274)+y\273\240mX<\271\341$\004\335\t;\3017\024:\271n\'=\314\"\246($\364\274lD%\273\363\314\332\273^=\362\274\341\3372\256\000\000\256\262\000\200)\212\000\200,6|\273U.\031\274\375\006\207:\330\233\377<%3\261\274\001\n\201\274b\245\t\273~\251\353\272\000\201\305\274\026\014\336<\ts\021\2757\364y\3616\215\274\304\204\311;1\354\376:U\216\0248\334\305T\275\004\266\024\000\204\273m\326\275\274\316=Q\275\020.\022\272\321\277y\275zWb\274\016u\036\275\032\236\324\274\022\214\244\273\364\340\004=W+\225\275\276(c\274\354\323\'=\330v\000<\335[\371\274V.M\2740\322O\274\247\312\263<\354\264\036:L\240\336\273\306\2302=\030\202\310<\365w\246<\261\262\321;HC\005=\"\307\352<\265!\243\273\376\272\r\273\206\251\320\273\005\026\027;\027K\033=v\306\244;\256\301d\274\327\321/\274\236bZ\272\274W\351<9\037\301\273\277\306\306\272\327\271\214\300\305,=\311[\300;q\267:==\344\342<\374\254\371;\377N7\274*\017X<\252]\3109\021\331p=\317\326b\274\366\270\265\274\233PB;\307;\311\274h\014*;<\0255\220<#\277\323;\200n\306;$)\225;\270\244#;t@f\273\261v\001<\252\264];m\0364\273\245\255\203<~\217I<\"\336\036\273l\260\223;\227m-\272\2048\214\271Z\374\t\273\351\253K\274\343\3117\271e\2105\274^\237O\274\325\260\203\274\3335^\274%C\222\274\331\370\220\274j\000,\274\013sy\274\002q\220\274\336-\350;ccL\274\354\023\367\274M\362\357\274\001\263\364\274\302/\025\274h7\216\274Ge\021\274\200\344E\273\307E\210\274\003\034#;0\006\275;\220\234\261\274\336v\r\274\305g\000\000c9\000\200\344\255\000\0007\013\000\200\'\007\000\000\262\320\000\000\325\324\000\000\225\005\000\000.Z\000\200:\330f:\366\321\213\273\212\177%\274\245\243<\273\370\340\026;\r\217\377\273\010S\265\273\261\200u;6\025\353\272\001\303\024\274\241\302\275\273\322^9\273v\013\016\273\337N2\274y\007\214;\212\344\"\274\rT\325:8\023\262;i\356\305:\024\010s<\301Fh<\004\367\274<\3304\365;\370\274Q<\n;\220\353\232\274[\374\315\274\300\216\323:\317\210\026<\375\3654S<\001z\325;\246\202v;H\221\014=\2447 \274I\201L<\027\273\002=\367\0135\275\255JB;\266\\\222\273]\211\253<\263\373\306;\377{\302\274%\357\252\273\2314Z\275\2763\325<\322\322P\275\033Te<\344D\270\271\252\035\010\274\245\253\241\274\264\267a=7D\341\274\366q,\274\311b\203\274\364:\001\275\035\210<=uX-\274\272\226\210<\364\002\261\274\257\340\344:a\257\256\273\026\325\200\275v`\202\274\226\211\325\274Wf\r\275z\374\020\275\020\03469k&=<\320\343\220;\021T\207<\201Y\241<-X\212\275\202\242\r=\332rw<\331\016j<\206\252K\222j;\317\270$=w\260\227\257\275\301\271&\274\005\204\\\275\321\026d\275\314\002\025=\352{\357\274b\277\320\274\201VL\275\215\304=\272\243d\316\274\313\365\016\275\020\t\225:\016>t\275\364F\"\273\014\341\312\274\207\311q<\255h\377<\272:\275<_uC\272\177\017<<\021\261\355<`\211\376;P)\000\000J\246\000\000\022\306\000\000.I\000\000\032\256\000\200\364#\000\000P(\000\200\237i\000\200l~\000\200Ol\337;\003X\236<\336\tl\274Qa[<\212\037i\274G>\321\274\223\010\257:u\236s\274\344B\243\273A\263\327\273\256\356\244\2733\366\324<\255S\006=I\0336=E0\341<\001\"\341<\nSR=\334\314\244<\234\037\240;\230|D<\264\207\036<\337\rB:sl\220;D\267\003\275\315\225-N;CR\205\000\253<\371\306h<\254\2641:g\373w<\244X\346;\032\300\231\274\\\004\302;&5\033\274U9F\2745\267`\275+\232\373\274\207\344\366\273\227Q6\275\304=#\275\214\216W=\003\351;=hJ<=\202oI=\007\213\321;\351\326a=\272\360A=\2631\313<\355?\002=\227\207\303;\027\262S\275\253\236\207\274i\312\272\274\242\2438\274\273\335\206\274\276\201D\000\200\345\031\227I\304\276=\001\213`\274s\345\260\274\246TZ\275\364\366\244\275\262\3308\276]\007\331\275;I\2249\013H\004\274?V\313\2740X\222<\010\032\347\274\217#\237\274\321\343X\274\336a\225i\306o=\375\371\017\273NgO\274+\227$\275\201\3333\275\2664\375\275\035s\230\275\325\241o\275\257h\230\275\320\336\225\275\273\340\r\275\200\304J\275\'P\355\274\235M,=\016\361\232=\360V\177=J\236\023\275&\374+\275h\235\000\275q\352\314\272SX\003<\351\265\226;\244\000\327;E|\0169F\233\377;&Bo\274g\037]\275\344\350/\275 \003m\274|\210O\275\240\355\314\274\017\243\314<6-\244=\3572\210=h\352\257\221)=0\257\000\000\243\252\000\000\231\'\000\000\\\033\000\2004\211\000\200\030\306\000\200c\037\000\000a\315\000\000\233\214\000\200#2\220\274\372gb\274<)\320\272A\331\311\274\332E\261\274\024R\032:7\3323=\231\334\271=\357\315\205=\232n\\\274\005c\025\275R\264\377\274/8f\274\324>\021\274\275l\226\273\225\334\322<\255\206t=\262\031==:h\213\274\3209\020\275y\241\024\275|\261\203\27450\024\274\203q\302\273\204\004k\274mp\277;y\355\365\273~\270\000\000$\276\000\000\213o\000\000?\305\000\000~\203\000\000\343\320\000\000$(\000\200\325\215\000\000\216z\000\000\3054#<\256\243\000\274L\005\204\274\352\267\343;\264c\322\274\223\334\313\274.{^<\270\321\350<\262\024\323\256$;\206\215\257<\345[%<)\217A<\3472S=O\010\260<\004x\332\274q\307X\275:\267$\275c*\355;\375\336\200;<\335\333:\0206?;S\337\037=\212M\345<\214\372\270<{s?\274B\307\230:\rO\245<5\332\277\274qV\302\273+\352\224<_9\032=\301g\320<\305b\351\273%.\351<\370w\274pr\274\010\361e\273^\t\362;\376e\326<\313\264\324<\r\216}\274y]\243\274o\257\340\274\301\274\261\274\231\232\025\274\225\210\n\273\235\262\337<\036\332\3248=\315=\023\373+\274\230\317\006\274\277\366u\275`\347m\275\202)/\276M\203\372\275G\300\310<\337U\316\273U\313\225\272\252_o\274\367a\234\2756\276\340;[\371\240\271\035\032D=\373\356\227<\221\363\"=iSb=cCY=\356\243o<\342\272\235\273z\312$<1<+\274\341\375\006\275\326\205|\274Y\267\212\274-\270y\275\217e\201\275\3433\230\274\n[5\275t\2127\274X<\246<\300\014\311=\237DC=\034+\373\274\013\2231\275\177\000\257\274\210N\031\275=\300e<\032\005!\274\000\324\005=\300\331\265=9O =8k\266<\374\376\313\275 \312\273\275r\302\203=\362\312\243\275\006\020\003\276\304\220\013>\006r\207=_!\021=\235X\230;z\242\006\275\220\201\033\275.\241\373<4Kf=\246\330\270\272~n\277<\333a\t<0\000\365;fJ\"\275q\324\315\274\340-\213\000\000G\237\000\200\200\007\000\200\031<\342\216\340<\006\241\347\272xM\335<\272\225\342<.V\n<\266\232*\346\250=\0343\250\2740\031}<\232\030\3009Z\006\261<\031\000\253=\t\242\355<\024\370\361\273\311\204-=\013\254q\274\345\364N<\202\344\341\273\355\376b\275\335\245\226=\037\330o=\n*\266\2752\224\206\274\244\202\000\200\340\254\000\200\366\324\000\000\310\025\000\200\036\315\000\200\226F\000\000\347R\000\000To\000\200ZW\000\200\010:J=E`\362\274\361\217\017<\351\367\035<\213i\312\275\217\031\214\272\247u<;\376\000\022;\256\347\232<\222\234\326<\023A\010=\335\355\247\274\236\0331\274\351Z\205\272\323\341;\275\311;\223=\357\316C=\315\257f\275\205\r\374\274\021\334\243\274\367+}\337}\231=z\211\262=`^\201\274\3641\t\275\221Jb\274\340\336\353<>\303N=~\326\375;t\006\"<\331\347\005\275\222\337T\274\375%\370\273\023o\265\274\206)T\274\267\216\231\273\216\341\232\274\'\334\037\251\275<\007\273\023<.\266\252\273W)Y\272$W#<~\010\264\273\016rS<\304\261|\371\307;\273\3762<\3715\026=1O\261<\021K\211\273\366\375\257\2745\224\220;\236\n\304\274|\376\216\274\317\032\262\274\263\203\227\274\323Q\245\274T\365?\274\021b\334\274f{\213\274\024\264\356\274\2640\244\274\274v\004=X!\237\273\341!\n\275%=\"\2753\314\302\274\007\025\302<\363\026\013\274\344\017g<=t\225\274\300T\030\275\347\014\343\273\243\025\000;.\371\355\272\022?\260<\035\253\000\200\251\264\000\200\024\270\000\000\246\267\000\000\317{\000\200\330W\000\200\374\213\000\000\230\267\000\000\376u\000\000\311\001\010\273\017g\022\274\306\265\232\271:\n\206\273\366\016\002;^\027k\273\241\336\025\274\356\316\033\274\312\335\203\274\266\237\276\000\000\316S\000\000\'\010r=<\321|=\305\014w=\030>z=d;\300=\036d\255=\266\252,=R\024\204=\331(\255=|\246\257<9\340\021\274\252\302\312\274\311\302\223;\220\206,=\264\020\365\261\275o\233\030\276\314d\312\275\004\362D\275v[\302\275,y-\275\034t5<\221!\235\273p\251a\274\374Y\235\272\231\276,:4\252\007<\016\214\023\2740\013\312<\211V\360;\371\214\361;6\236\002<\250V\n\272\264\'`\2738\204\n<\355\254\210\272\314\245\036<\245T\022<5f\355;:Y<<\2659\251<-S\235<\327\004|<\025\340\235<\363\023\t\340\212\273u\242\341;u\221P\275\361\243\202\275>\256Y\275\277U\203\275\235H\302=\320\223m\275\325\300}\275&\331Y\275[\322\200\275\014U\222\2751\r\261\274\354jO\275\031\357\327\274\027\227\331=\227\252q\274./\202\275\375\265\322\2742Iu\275\216\266\005\275\246Z\353\273\350\221\231;K\3629\275\305\345Q<\024\345,\275\330,\275\273\252\353\260\274\311-\314\274\371\212\007=Y\243\357\274wSa\273c\t\311\274\032\245\227\275\206`+\275iO\207;\031\032\333\274\2561=\274\366\321~<\374\tK<\352\300r<\242\032\202<\223F2\275(b\350:?\346\016<\205\200\246;\236\203\003<\366$\302\274~\317\344\272h\014);\371P\375:\244\224\031=\207\035\230;\206\365\251;\201~\240<\n\r\246;\010t\263;\314R\370\274\004\230\237;\230\227\004\274V\001\346\275\000\202@\275\272\271\245<\034*!\275\274\322\03695\245\000\200$W\000\200\345l\000\200\307\n\000\200\307\322\000\200\345\007\000\200|P\000\000\355\215\000\000A\312\000\000 \316\226:0%\001\275\205\222r\274\326\257\240\274\241\346h;\002\002\300\274\307jq\273]>\375\274Q\345\310\273&\246=<\256:\355\272\243\376P<\333\332=<\277\024\235\275\224\007\220\274u\037\264;K$\020\274\262\333\277<\035_\244<\366a\0269\027i\263:%\2341\274\254Eh:\276\007\263;\002%F;\262\252b;~s\316;\356\255\226\273*\355K=0\253\004=p\303p=\274vO\275\245\250\231=J\204\256<=\215\016=\371#N\274\272E\237;\335\220(\275h\243\370\272\342d\023\274:\251\231\275\266\021=\275a\233\212<\314\3700\274\216\002M<\326\313\037<\363\262\274\266\3732\220\274\352\334\260:s\375\330;\226\274(\274hz\216\274\267\307\223\274\025\374\317<\253\222\032<\204\326\255:\021E\006=\035U\325\274\177X\243\275\317I\002\272\254\355\000<^\270\275\2745\207h<\262\247i\274\226\314c;\365j\230<\037}\205\2748\030\220\2730\334{\274\004\224\317;\201\014\000\274Rn\272\273\001\033]\271\201\353\334\274\037O\231\273>K\327\274Q6\241\275\361i\020\275\010\204\351\273*\324\253\274)R9\274\352\254\345;\236\3020=\330\356\222<\273\000\373?%\270U{#\273s\266\203<\337j\013;J\372H\274l\345\234\273\221h\002<\337\341\t<\202!=\t\274\352\222\022\274\247A\227=\025\000\"=\307ET=I\020\000=\305\201\264\275\377u\021=\202g\007=\257\246\264<\237=l=\256\361\013<\014}>\274\023#\256<\231\366\261\274\201\016\347\2751~\025\275ivy<\337\356\343\274\236\332\333<\2020#j:\300k\260\274\341`\246<\2248n\274\032h\302;J\221(\274%\377\311\273\264\235\377\273\224*\215\274\246\306\300\274\373\227-\274N\355\021\274~u\236\274$-0<)\233\325<_\314=<\3739\303<\037\\\013<\026\327\0009\224+\003;%\343Q\333\353\273M\366\346;\311\272w<\332X\264\273\230J$;\213tZ\233x\275tR\232\274\231\363#;\177\036d\275\222#G\274\327\241D\273N\250\300<\032\363\014<\301\245v\274\001\304\266\274\324\371\331\274D3}\273|\374\305<,\233(\272h\365\273\274\354\210X<\323\350h=`\375\240\274\n\273\271<\n\241L\274Pr@=\\\335\236\274\251\354(=\326q\211\274Xg\215\275\205K\264\274~7\335\2749E\232\274\r\226\264=\'\227a<\272\364\277\274\321\372\256<\265\272p\275\230y\007<\336\202\232;\225}n<3\213h<\310\005\010\275C\211\006=\307\025s<\333\354\337<\232|\000<\277\354#=\177\304\203\274\014\245\2159\302\377\246;\305\361S\275\000\216\204\2743\265\020\274\252\253\312\273_\345\033=\"\000<\274\010\354V\2746\013+\274\366\366n\274\257\200\241;\233\364\332\274;\371\213:\3250\257\274D\021\240\274\355\374\343;\212\256M=\201J\\;\361J\273;\265\016b\272HZ\251\274C\263p\274\263-\031\273\320\3503\275O\366x;\244\000\250<\200\177\362;\013:\230<\301\375\235<\3104\205<4\330\312\273\372\2529;.\016\003\274y\240\023=\230\316\220;W\"\211\273\0009\355<.Y{\273\024\361\260:\276\314\324<\rC\200<<^{\273\312\013\203<\201\220\n\274\177\264q<\224\035B;=\237\252\273\344a\212\274\017\007\013\275\251\311\235<\234_\256;\332h\260:\206\365\234<\216y\240:\037n\307;\177\n\241\273E.+;\333\242G\274\nH\225\272$|#\274\237\246\024=\315\000\365\273\377R\366\274J\255P;d3\235\274 \327\200\273\313\324\034<\017\373\332;\314\370\032<\352&\264\273.\332$\274j\025E;=Q\351\274N\317\0179%\r\233<\246\325v\274\375\270\207;\356\340\353\274\"\235\244\272\223\020;\274\371\331\343\274\025^\355\272$<\233<\371\0312<44J<\336u\002\273\343\264\023\274>\236\212\273\361w\300\273\362\316$\274\177#\313\273\353\210\021<\030D;;f\034\263;D\010P;Z\001\034\274hy\336:\2470\331\272\217f\332;\317u\221;$\2408\274\274\353P\274b\246\315\274\225\256\212\272\326\354\236;\267\322\342\272\300\302:<\361\331B<\252\026i<.\007\370;Nw\233\274\016 \301;\3531\212<8\027\317;\034\320/<\327/\013<,\216\216=\027\031t<[ZB;L\351\264;\362\372#\273\222>z;_G\3459\247\236\333\273*\032 \274\360H\374\273G\3735\274<2}\274\255w\007\273\357\3130;\203\346\r<$I\267;[\236=\273\312\332h;\0325\252\274\022X\027\275\262\357\305\274\013R\306<\361g\251;\247o@<\202\257\232;\335\372\247<\323\226X<\241\274\036\274j*B;,:\260\273\026\233\000\274\230\270\254:i\225\016\274\233\217<\274\365\337K\273}}-:\320\356\320\273\262\327\006;2A\206\273\235\224\357;\016k\375:\006\321\017<\021s\327;&\340\346;p\033\212\272l\326\240\273#\217\345\273\343\304\000\200<\314\000\200\005\311\000\200?|\000\200\323*\000\000\320\004\000\200\301\274\000\200\022\311\000\000z_\000\200\3237\037;%q\001=\367\322\371<\2221O<\226\233\233\274\014(\013<\025\237\252\274{\315\215<\323\374^<\250\226\000\000\354\321\000\200\207\323\000\200~\214\000\200l\262\000\200\237t\000\000\336\271\000\200Vj\000\200\264\206\000\000\001kj\273\313\306t\275\226\3741\274\334\2448\274\240L5\2757}\274\2736\354\332<\226\306\212<\030\251\215\275WA5\274\373\014\215\275\351\205<\275\033v\'\275j\035>\275L\330\376\273O\240\270:\315B\003\275/\247\226;\273LL;\357|p\274\327X\266;\037\2660:\317[\223\273\241\313\273\274\003\372\005\3702\273o\366d\274]\216L\273\310\t\212<\3774:\274g\244l\274\226\236\330\273|:r\273\030\177\377\273\253\024\031\275\326]\r\2743T\226<\345\241\233;\217DF<\000\257I<\352t\307;Q\314}<\000qC\274\350\334\226\274\275\232\205<\t\352\007\274\254\rU\274#\361\262\273L\216\000\274\004\315O\274\243/\227\274\306#\021\275?E\320:<\007\035\275m\303\350\2744\276v=\215U\224\273\304\343x\274P\3152=\'\256\234\274\250e,<\326\242\360;|\253\211<\341\250\211:0\315\263\274\305\2731:\221\025-:\016j8\274\230J\004\273\336\2209\274\t>\211\274B\3061\274\216\262W\2736O/;\370\357\345\273\253l#<\226\335:\274\004\325\236\273V\341g\273=\314\302<\tG\006=\367\030A<\205\350\361\273\356`\023=\361\302I\274\313\304\252\274\362\344><\302\322\265\274\234gr;\240\261L<7zf<\240\267\226\274\233\245\"=\202&\034\2741\322\r\274\177\340T=\266\225\024\274|g\331:\337\311\204\274\314E\023\274.a\241;8\235\013\272;\225\375\274\234\260\223\274\267q\002\275\033\247\361\273\307\377\003<\355\214q<\374\217\263\274X\260\370;\njY\274\321\007.\272\271\366\2779\034\034\250\273Z\216\310;6/W\274\0107\216\274BAd<\346\3628\274c\"\004;\317\006\303\274\255\306\311:\302\nu<\347\014\262\274\315c\335\271\372X\203\272\265\301\005\274\337\261h\304:\313l\201:ibn:\360\231g\273}F:<\332\272\365\273\300\234\246;\231\210\256;\006\002\020;H\001\202<+\311\326<\256m^;\210\335\241<+\303/<\321\350\225\274\252\016\222\273%\316\034;\237\340c\271\347#\253\274\266H{\273\2054\t\274\242\264\253\273\013%\2219\267\200\000\000\247\305\000\000=\323\000\000\304\306\000\000J\n\000\200w4\000\000\025\314\000\200h6\000\200\032\322\000\000{\032\262\274=c\305:6;5\274\324\232S<0,\353;5N\364:t\335\216:\372\306E<\006\257\245\274\307\211\000\200(\216\000\000\353n\000\200\314j\000\200\223l\000\200\307\225\000\200Y\211\000\200\263\314\000\000\376\321\000\000\332W\213\275\360\373\214\274\035>v\275W\275[\275\371\'\242=\263\r\037\242\275L\002\200\275xKZr\000\200\3279\000\200\317\255\000\000\215\275\000\000\264\032\000\000qk\000\000\017\304\n\274{*\322\273bL\016\274\352\217\267\273\263\337R;\274\316\236\273|\334\016<=\017i<\365\001\236;c\254\315;\377\242\362;\214\003\245\272I\021m\273g5\321\273\353b\313;\351\207\310\273\002I-\272\034t\225<\002x\220\273\007\"A\273t)l<\177I\350:\324\347j\274\357\214n\274>\200\202\2748\252\344\273\206\032\266<7\216\205\273\267Q\'\274p3)\274\027\332\273\273\341u\321\273Z3\255\273\202\206r;\272W\n\274\213\347\327\274mn\200;\2212\"\274<4\270;\303\336\222<\334\010\000\200\314\216\000\200x\302\000\000u\317\000\000W7\000\000\313\314\000\000i\237\000\200\3166\000\000\201E\000\000\306e\240<\267\234\370\037\272\032\373\204<\340d\244;#\3371<\327\225`<\177\353\030\274/\375\":Ql@<\031\206E;\361\322\216\2749\214\213<\347NG\355\272\313\000\356;\372\357\014\272R\332d\274-5\205\273\007\247 \274\234\246c\274\331@w\274%\236/\274\356P\253\274\230\351\'\2735c7\274@\233-\274{\032\372<\323\300\233\237\271\274O\231\213\274kJ1;\033\2166\274\024i\375\273%\205\237;\324\233\020:|J\226\274\356\024\322:\270\n\022<\023@G\2711\364I;_A\003\274\222\2444\nF\273\270\256*\274~vS\274\027\247\207\273\321\2610\274\014H\\;\000.\024\271\177]\266\227\204<\324qt<\271\336\022<\2271\360\273\336\316C\272I\030\001\274Q\r\352;\205p\252<\357\004\232<\260#\262;\375O\271<\246\301\336;\336i9\336\231\273\r\210\311\273j\236\n\274o\367\350;U\230\347<\316&\205:\204\323\260\340\274C|T\274<\273r;\352\010Q\274\253ef\274\234\210\014;1\3658\274\374\233\216\274`PO\274a\036\351\274QD\304\274\004(\237\274z\034\375\274\221\310c\272\036\326 ;\373\231\340:.eh:\261\273\350:w\314\3479\252f\231\272\272\273\212;\201\204B;\004\014\207;\037J\375:a\202\231<\376\0204;\207\370\016\000\200\251\307\000\200\301L\000\000\314\240\000\200\337g\000\000r~\000\200\305\200\000\200I\t\000\000\264w\000\000E)\000\000#\304\000\200\262\007\000\000 \212\000\200\314\273\000\200\312r\000\200\321m\000\000\252Y\000\200\241X\000\200\006\031\000\200:\317\000\200KR\000\000\002\273\000\000 \013\000\200\323;\000\000\023\204\000\000\305\273\000\000\263R\000\000\202)\000\000wc\000\200\'\234\000\2002\253\000\000\024\235\000\200\362\271\000\000n\273\000\000\036\264\000\000-U\000\200\341\310\000\200\300<\000\000\273\230\000\000\273!\000\000^\216\000\200\226\277\177\212%\225\326\214n\301\000\000\247X\000\000\017\005\000\200\321\220\000\000(\'\000\200\326q\000\000\305\304+\211\325\250\000\000\357\\\000\000\022q\000\200y\223\000\000\233s\000\200\353\223\000\000\3632\000\000?\214\000\200\013\276\000\200G\035\000\200\246\240\000\200\007z\000\200\3742\000\0000H\000\000\001\303\000\000\256y\000\200 \013\000\000\342\256\000\000\343\023\000\000JK\000\200\312\034\000\000r\035\000\000\312M\000\200WW\316&\253z\000\200$\200\000\200\351!g\203\354\177\000\200\023%\000\000\244\273\000\000(\030\000\200\265\277\r\200\214t\000\200b\250\000\000\372)\000\000\270c\000\200\2550\000\000\002\225\000\200\372\014\000\000\365u\000\200Y\301\000\000\364\353\023\226\371\222\000\000\017V\000\000{\366\215\214\211+\000\200\235\\\000\200x\246\000\000\307\r\000\200\373\027\000\200i\274\000\200V#\000\000\034\030\000\000\202N\204\2171\311\000\2006\247\000\000Or\000\200P\270\000\200\350\221\000\000\204\252\000\000\0173\000\200W\256\000\000`\272\000\200x\264\000\200Aw\000\200\375y\000\200\032\303\000\000\312\302\000\200\026a\000\000\307\246\000\200{\032\000\000\251c\000\200\347M\000\000\331\277\000\0006F\000\200ow\000\000\214\031\000\200\316\225\000\000s\233\000\200{L\000\000\245g\000\0009\300\000\000\323,\000\200\217\262\000\000\256\363\004\003k\231\366\200H\237\000\000\206%B\t7\246\320\rKt\030\206\214\306\000\200w\207\000\000\272u\000\200\177U\000\000\254*\000\200\221\254\000\000\242\017\000\200VF\000\000\232J\000\000\333)\000\000\004\317\000\000\037o\000\000\222l\000\200\203E\000\000H\031\000\200p\026\000\200\306\n\000\200a\211\000\000\221!\000\000\024\377\001\200\213\002\000\200\356\224\000\200\272\220\000\211\003\264\010\035\302d\000\200\222\234\\\013\303\201\247\216a\330\027\014\020\262\000\200\365\016\000\000Cu\000\200\032G\000\200\227\003\000\000\243\211\000\200~K\000\000X\276\000\000\256\304\000\200q\000\000\000?u\000\000\246\032\000\000\372g\000\000,#\000\000\372\247\000\000 \014\000\200\005\271\000\000g|\000\000\270\231\000\000\240\267\000\000\372k\000\200Q\205\000\200\207%\000\200d{\000\000\3365\000\200m\234\000\200Q2\000\200\021j\000\200\372\270\000\200vf\000\000\321\211\000\000\301\306\000\200.\266\000\000`8\000\200h\306\000\000\366\027\000\000[g\000\200\217\006\000\200\207j\000\000h\002\000\200\240\007\000\000\357\036\000\200\366F\000\200\016\274\000\200\253|\000\200\325>\000\200\000\016\000\000*a\000\000Th\000\000\213\037\000\000\370K\000\000\310\256\000\200\231-\000\000\360\262\000\000,\023\000\200\201\t\002\200\301N\000\000\215j\000\200V@\000\2005\224\000\200\034[\000\200\342\233\000\0008\006\000\000\235\235\000\000\2053\000\000nt\000\200\350\004\000\200 D\000\200A\303\000\200~L\000\000\225\375\001\200\355\005\000\200\324Q\000\200\346\227\000\000Y\316\000\200\\-\000\200\242N\000\200\206d\000\200\316Z\000\000\267,\000\200&\205\000\200\264\243\000\200\336\252\000\200\317^\000\200(&\000\000mW\000\000\220\003\000\000J\301\000\000\'Y\000\200\252[\000\200\243\\\000\000x\267\000\000\033\\\000\200\372g\272\000{\267\000\200B\221\000\200\373\274\000\000\322\016\000\200\334k\335\2375\036\000\200a5\000\000\217w\000\000\001f\000\200\217\007\000\000\201`\000\200jf\000\000\324\213\000\200%%\000\000x\230\000\200WL\000\200G\207\000\200E\275\352\205\313\201\000\200k+\000\000\256>\000\200;\220\000\200#\210\000\200)U\000\000;\034\000\200\375?\000\000\353\232\000\000\210\013\000\000JB\000\000;\271\000\000[\256\000\200a7\000\200\357\032\000\000\003\036\000\000z\244\000\2008\236\000\200\267\034\000\000\252\r\000\000\355\223- B\370\301\214\036\277\000\000\201\252\000\200 \216\000\200\375\213\000\000\361i\000\000\370_\000\200\007\"\000\000\265\037\000\200\334\220\000\200*\266\000\200\332#\000\000N=\000\200\274[\000\200\005\203\000\200\224W\000\000u\r\000\200l\320\000\000\026\225\000\000\325g\000\200[\232\000\200i\202\000\000\316\264\000\000Q\306\000\200W+\000\000h$\000\000\311\234\000\200CJ\000\2003\273\000\200\342 \000\200\2109\000\000\337\264\000\200\022\276\000\200!S\000\000\274\036\000\200\322-\000\200Bt\000\200\327\221\000\000\320V\000\000\0200\000\200\\yC\200Q\273\000\200\324\"\000\000\2206\000\200lu\000\000EX\000\200K&\000\000H\232\000\000o\253\000\200FO\000\000\345M\000\000\334u\000\200A\224\000\200\023\207\000\000\252\225\000\000\260_\000\000\364\256\000\200X\224\000\200\351\207\000\000\016\031\000\200\017)\000\200\223i\000\200\230I\000\000=n\000\000]v\267\213\302\275i\237N\201\000\000%\036\000\200F\237\000\200\337I\240&3P\000\0001J\000\000\227q\206\"\2568\000\200+&\000\200\370\272\000\200\320\253\000\000UW\000\000%\265\000\200\217\307\000\000\3778\000\200j\255\000\000\r\213\000\000B5\000\200\275\211\000\200\252\306\000\200I\246\000\000\362u\000\200\"\262\000\200P?\000\200\205\315\000\200Ry\000\000\204t\000\200\033\212\000\000Z\010\000\200\251\202\000\000\036\023\000\000r\253\000\200\031M\000\000\301\214\000\200{\232\000\200\315\275\000\200\335\002\000\000f\301\000\200\031\206\000\000\210\253\000\200\357M\000\200&\276\000\000BV\000\200\354\252\000\200Iy\000\200\245t\000\200j5\000\000\273\275\000\200\023E\000\200\346+\000\200\271J\000\200L\023\000\000\207\027\000\000\275B\000\000.\022\000\000\037L\000\200\303=\000\000~O\000\200\253\022\000\0007!\000\200\001b\000\200\374\207\000\000\340\007\000\000\241\304\000\200\005K\000\000\276h\000\200\\}\000\200t\206\000\200\325#\000\000vx\000\200A\034\000\200\031\267\000\200\233Y\000\000\334\205\000\000\365\303\000\000\213=\000\200rw\000\000\363u\000\200\025r\000\000ty\000\000\351\321\000\000\355S\000\200M\310\000\000|\273\000\000\003T\000\200\024\214\000\000]\'\000\200.\313\000\000\"\261\000\200\202\005\000\0005\255\000\200\363h9\000\330:\000\200L\\\000\200\322\245\000\200\222P\000\200\314D\000\200K\006\000\200\330\307\000\000H?\000\200X\311\000\000\253\305\000\200=\032\000\200\nR\000\000V$\000\200\350Z\000\000\310\362X\200\207Q\001\206rG\000\200$\010\000\200\250$\000\200h\262\000\000k\233\000\000R\204\000\200c@\000\200z\274\233\r\027\265\243\200\365A\000\200\005>r\236rm\376\234\265\343\020\206\300X\363\217&el\021\253\241\203\001\022>\000\200\243\210\000\200\271\250\000\2009B\000\0001\221\000\200\352n\301\216\3717\000\000$\\\000\200\000\263\035\221\"`\000\200\377\303\000\000gu\000\000\356i\000\000T\013\000\200H\211\000\000$\022\000\200$\260\000\200\372b\000\200\256H\000\200\206\261\000\200\204r\000\000u\2736\221\3048\000\000/c\000\200v_\237!\021\205\000\000\013\262\000\200\263\365\302\274\346\362g\273,w\346\273\310VQ;?M\240<\245\200\005=\177\375D\273\312\021\216<\317\243i<\356\275\244;k~s<\246\027(<\332s\231<~\020\201<\2469\016=@u.<\016\204\365<6\355\210<\365\354j\274\341c7\274\226\373\032\274/\2501\274o\2035\274N>z\274V\002\250\274\2712\253\274\205\272\276\274]_\276;\276\236r<\313\373\033<\307O\251\273\034P/<\275}\232\272Y\255\'<(\326\026<\227\251\207\273\361\2738\271\345\253\004\274\206\332\"\274\367\026\203\274\250h\035\274*\227\301\274\272:\031\274G\301\277\273\025\017G\274\337\205(\274|^x\273H\264\307\271\0143:\273\222\2044<\276\0304;7p\245:\301\013\205\273:q|;H\306I\274\245?\210\274\220ye\274\355\255x\274c$\253\274z\000\001\275\366\273\330\272\250\003\230\274+\255\263\274\226|\000\000\310\277\000\000J\236\000\000n9\000\200\373(\000\200\"6\000\200\374&\000\200\325\023\000\200\3165\000\200\363\037\316\273\025h,\274\025a|\274\342K\217\274\302\322s\274\377uT\274-\350g\274K\320\004\274(\306\316\273\362\'\223;\261T2\335\235\274EN5\271T\315 \272:\364\260\274\004\373<\2748\217\331\273S\336\"\275\013\005\320\274\221\211\214\245<\263\023w;d(X<\036U\240<}\311\321\272\242\213\233<\030\250\207`\000\000\230\270\000\000(\230\000\000\217\256\000\000\272\321\000\000\210Z\000\000.\026\000\200\317\275\000\200\265C\000\200s#\'<+\233t<\002\240\237;\200\250k;\340Ve\273\346\343=\273\224\213L;\016D\035;|\322\310;-M:\274^_!\274\272\204\373:\210^\321;\333Q3\272\340\026\323;\321QJ\273C\336\241\274\317/\273\273)\000\372\272@\204\211;L#\276\273\t8\330\272\252U\343:\207o\000\274\300\017\240\274\353\363\020\272\321\323\244\273D;\214;\314\3337<\355\370\r;)Z\022;h\240\223\273l\222\"\274\206\372\237\273\340\2245\274\340\370\217\274q\353\332;C\246\332;\226\207b;LcV;\264\235\223;\3251\035;\213`\330;\2254\244;\254\001];\243\360\016<\325\0059\273>\030\277\273\321uQ\273l9\225\274\336K\007\274\255\222\320\270du3:\254\313\202\273\"\352\246<\361\264\210\024\233\007\033(\246\373\202(\221\320S(\202E\221(g\030E(\n\337P(\003}\207(t\205\303\250\003\000\242\250^\037\335\250U\227\254\250q\277_\247\372\360D\250Q\320\222\250\2159\036\250\302A\276\247\322\365J\250G\226\370&\232\0333(\334\000\225\244O\315\356\'\022\001\237(\350\362\331\247\334\265Z\247}\347\344\'8\270\262\247Gp\230\250\350\273\260\250~2N\247\323\026\033\250O\321\354\246\017\317\247\247\242\3101\250\377\"=\247\200s\272\247/Wb\250\003+\027\250\257\355\304&\254\317\004\247\032C\226\247\216\213\025$HY\235\246\321N\036\247\225\020\301\245\003tI\245\317\322\'\316\027\005\247\021\352\355\246\376\036u\'\365U\025\247\321\255-(\013\335v(\001\033\250\'\257\350\236\',\357\335\'\335\322\252%\242\241\"(\351]3(\211y0(3\325h(\3430\207(z\014~(8\273D(FY\031(2\275\t(T\242h\251\220\216N\251\254b\362\250\331J\264\247$R\267\247\307\375c(\321\221\272\246\022~\206\247}\246\021\247\327L\246\'\207\216_\'?<\273&\320\322\265\'\2225\003(V\204\204\'\251\266\017\247\341,\022\247]{\013\247\212\276\230\247\320\014\214\2475\245\210\246H\003w&\361\001O\247%\262s\'\210\350\315\'\362i\215\')^\251\247i\037\214\247\270\302\202\247yx\000\0005\276\000\000b=\000\200O%\000\200\341\207\000\000\022*\000\200\364\301\000\000\360\213\000\200\250\303\000\200\212G\334\247k\260\020\250\211\333X\247\264\037\304&\0006\232&\235\221\"\'\271\241\245\247\373\3246\250/\241\016\250\220\306\000\2008\215\000\200hH\000\000\r\275\000\200=\320\000\200\2058\000\200\372\303\000\200A\237\000\200y\320\000\000\264L\341\247wM\003\250=\217\246\247\036F\000\250Aj\205\247i\217\276\'\376\252E&\267\250\002(^\263\232(\241\2354&=W9%:\024\252\247llw\'E\036M\'\372\270.\246\301H\205\'\344\364f\'\005?\001(\027\264\244\'\326\374\263\'\371Z\020(\203\004\026(\307\225\027(7\215m(\245\306A(]\014C(\007v_(N\027\224\'q\370\250\'m\312\372\246\356\205)(\212\226Q(\036\300w\'[1\321\'\355B\304\'CW3%}U\310\247u\001\207\'\326\264\017\250\343\230\320\'\232\024\200(\203}a\'w\340\243\250\"\354%\250\005\263C\250\3551\246=x\221l=\234\022\026=!I\n=\014\nZ\274\374\360\363\274\002\352,<\300\325\031\2750\034N\275\366x\355\273Z\237\351\272\311\367\\\273\2604X<\254Tz\001=\361\370\243<\373\311\226<\361\021o\273C5{<\364[0\274\376>)\275_O(\273\005\343\335\271!\0165\274`T><\355\201\207\272\377\307Q<\242\002\023\274o8Q\274\367\334\215<\205\227`\274\211\213\205\274\372wb<\374=\";>\323{<49L<[\372\037:\252\256s;%\276\205\273\277\344|\274\223<(\273uG\343\274\355xw\274\376\321 <\203\342\245\272\372\277Z\274\332j*\274DB\206<\335r\275;\251<,\177\334\272\325\302e\274\001\346\277< \362p<\340\222\311\274OZ\206\274+\211\025\274\0035\227\274g\327\354\273X\2760\273,Tc\273\030\021\377;:\366(<\177\"h\274RF\306\273\004\037\206\270\302/\224\274\340,\311<\023\374\017<\201\"N:\031\025\333<\2729\224<\020\265\000\000o{\000\200\311n\000\200e\305\000\200nw\000\000~\235\000\000\244\256\000\000z\032\000\000\342\313\000\000\275\r\023<{\303\316;\002\0013\271\273\311;\275\217\260\361\274\031\305\234\274\235\314\202\273M\250\202<9\254\244;\027\215\000\200\025\031\000\000y4\000\000\005\005\000\000\224\006\000\000V\305\000\200WR\000\000\031\212\000\200\342\313\000\200\243\373\034=\232)7<}\273L=\014\277Y\273\232} \275It\251<%\333}<2\303\350<\257\202\340;%\300o\274\026a\2058\037\275m\000\370<\364(5=\353\271]:/\300\221=\226\n\202=i\032:\275.\242 \275~\260\306=\01715\276\314\375 ;\217}\217> \363\335\275\361\274M\275\260\330\022>\224\201\247;\361\023\004;\316+)=\325\266\014\275[hg\274\205\254\357<\207\240\003\275\212\016@\273\034\365j=\007\334\036\275QOS\275](\341\274\252, \275\371+\325\275\231\234\262\275*p;\275\204\367p\275\254N\034\275k\231\247\026\227/\274\364\332\321\275\322\373\302=\240\273\001\275\034dl\275\274\326\217\273\213\217\261\274\3615\200:\346\016\346:\037\337j<.\361\354<\210\006\030<\304\367\'\275\027\240\355;)\251\206\273O\375\351\274\306#~\273\311I\020=\256\227\010\274\274\346\206=\327.\n=\266\023\006\275\341\014*;6\235\000\000V\312\000\200\274\320\000\000B4\000\200\233\270\000\200:$\000\000^C\000\200v\266\000\000\375X\000\000\250y\225=\254@m<\233\252-\275\312\202\035=\375\352\000\273O\235F\275\236\225\232\275\"\270\206;\251p+=vk\007=>\226\321;\330\367\250\274\360\334\237=\334e\013=\314\300K\274\226K\005=\037&\002\274\3508.<\315\255\177\274\241c\216\274\312%\3159\325\260\361\274\nqY\272\340\357\240<{\376\352<\201\376\262\274\023\245\252<\216\266\201<\270k\324<0X\340<\266\215\241=}\\Q\275\253\311S\275\244\212\025=C\007\002<\232o\352\274L\350m\274\354q\205<\t\3230:\2343\303<~\357F=\333Dr<=Y\217;:\031\255\274\230{\313\274\227w\006=L\207!\274\034\356p\274\214_\366<\336M[\275k\246==\023\305$=\374\036\375<\240*\002=\253\341\003\274;\266d\275\325\213\203\273\004\t,;g\271u=\263F\013=\360A\\\272\341\033\322\274\233\203\254<2\371.\273?E4;\330c\225\273{\336\225\274\301\021\266\274d\344\332<\013J8=\277Fc\274\377\nr<\004\326\206<\215\035\273<\346\275g=-k\347\275\337s\317\275\221\207 \2753@\247\273s\016\260<\001o\016=\306\216I<\325=?<\374\266U<\327\322\211=\261\322\017\275\233/#\275g\260\206<\027\270\210<\2531/\274M\316\230\310\005=#%\014\2748\356\352\273B!\006\275\250\024\203;\266\010\332\301\337\275=qT\205\273i\372\362<\310|\000=T\2134<(\004\227\274\307o\213=1^\211\273\347\3705\274\314V\336<-\364\265\274\361\232x\274\030\245\364<\271\326$\273\275Gv\274\221\347\366;K;\367\273\360\177\r\274\314\240\323;\337G\3729\342\355\016\274\361\224\034<\230\032\000\000\021I\000\000\241\231\000\000\000n\000\200So\000\200\032\024\000\200j\212\000\000U\026\000\000\200b\000\000\336\005\033=\252\260\224;\366\227\030\275\000\262\245=\365/_<\205\024E\275\273\t\227=\214\227\213\274j\2745\275\241\317\022=Pc\245\274\351\215\225\274]\360Y:\211\265k<\225\350t=E\376\"\275\263\227\023\275h\346\220=}pB=\275\022%\275Q\255|\274\265\373\355=UYH\274-\036\240\275\251\257\254=O\201\035\275\323\360]\275\367W\332\275/5\302\274\033\212\260=\323$\204<\035\323\222:&\372K\0052\356\274\253\274\n\276\314u\225=\273\t\252;\2207\235\275\375\255\361<6`i\274x9\340\274\036Y\036=Z\005\216<\333\366]\274`\261\030=\331\241*\273\326\001_\274\255\335(\273w\025\345\274\201x\023\274U\0056<\240\306Z<\265/.\343\274\032\352\326\274%h\217;\215\263\241<\ns2=\271\347\274=F\371\204\014\304\376\275D\203\252\275\210N\025>\376\335\033\274\351RN\274\307\016@\274\302b\206\274]\3310\274\351\021\257\273\347\276/#\220\275\216\311\200\275Y\362\317<\014\227\243<\251\265\273\274\253y\376<\225\271P<\276\270\273\274\202\3704\274F\330\232\274\246\221\020\275\333Q;\274\332Q\206\274\036\216\235\274\313\303\247\274\2163\217\274\021q\347;|\321_\275:\216{\272\0239y=B\240_\274ni\004;`\221\320<\226\001;;3\373?<\350\300h<\332\0315\274wf\326\273\366\2202=\016\222J\274\035\270=;\026A\201=O3\304C\275\371\313\017\276\236\203\302>\276\017[\274n\262\234\276\256m~>\242\327b\275\246\301C\276" + } + type: TENSOR + } + } + node { + output: "904" + name: "Constant_30" + op_type: "Constant" + attribute { + name: "value" + t { + data_type: 1 + raw_data: "\303\314\360;" + } + type: TENSOR + } + } + node { + output: "905" + name: "Constant_31" + op_type: "Constant" + attribute { + name: "value" + t { + data_type: 3 + raw_data: "\000" + } + type: TENSOR + } + } + node { + input: "903" + input: "904" + input: "905" + output: "906" + name: "QuantizeLinear_32" + op_type: "QuantizeLinear" + } + node { + input: "906" + input: "904" + input: "905" + output: "907" + name: "DequantizeLinear_33" + op_type: "DequantizeLinear" + } + node { + input: "902" + input: "907" + output: "908" + name: "Conv_34" + op_type: "Conv" + attribute { + name: "dilations" + ints: 1 + ints: 1 + type: INTS + } + attribute { + name: "group" + i: 1 + type: INT + } + attribute { + name: "kernel_shape" + ints: 3 + ints: 3 + type: INTS + } + attribute { + name: "pads" + ints: 1 + ints: 1 + ints: 1 + ints: 1 + type: INTS + } + attribute { + name: "strides" + ints: 1 + ints: 1 + type: INTS + } + } + name: "graph" + input { + name: "898" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 64 + } + dim { + dim_value: 56 + } + dim { + dim_value: 56 + } + } + } + } + } + output { + name: "908" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 64 + } + dim { + dim_value: 56 + } + dim { + dim_value: 56 + } + } + } + } + } +} +opset_import { + version: 10 +} diff --git a/inference-engine/tests/functional/plugin/shared/models/custom_abs_op.prototxt b/inference-engine/tests/functional/plugin/shared/models/custom_abs_op.prototxt new file mode 100644 index 00000000000000..4b42d612bee234 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/models/custom_abs_op.prototxt @@ -0,0 +1,42 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "A" + output: "Y" + name: "customrelu" + op_type: "CustomAbs" + domain: "custom_domain" + } + name: "test_graph" + input { + name: "A" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 10 + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 10 + } + } + } + } + } +} +opset_import { + version: 1 + domain: "custom_domain" +} diff --git a/inference-engine/tests/functional/plugin/shared/models/custom_template_op.prototxt b/inference-engine/tests/functional/plugin/shared/models/custom_template_op.prototxt new file mode 100644 index 00000000000000..38e0fec48b6dd1 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/models/custom_template_op.prototxt @@ -0,0 +1,65 @@ +ir_version: 7 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "A" + output: "Y" + name: "operation" + op_type: "Template" + domain: "custom_domain" + attribute { + name: "add" + type: INT + i: 11 + } + } + name: "test_graph" + input { + name: "A" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 1 + } + } + } + } + } +} +opset_import { + version: 1 + domain: "com.example" +} diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/caching/caching_tests.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/caching/caching_tests.cpp index 8b3e37ee501942..8a6918a51d1d84 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/caching/caching_tests.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/caching/caching_tests.cpp @@ -109,6 +109,9 @@ std::vector LoadNetworkCacheTestBase::getStandardFunctio res.push_back(nGraphFunctionWithName { inputShapeWrapper(ngraph::builder::subgraph::makeReadConcatSplitAssign, {1, 1, 2, 4}), "ReadConcatSplitAssign"}); + res.push_back(nGraphFunctionWithName{ + inputShapeWrapper(ngraph::builder::subgraph::makeMatMulBias, {1, 3, 24, 24}), + "MatMulBias" }); return res; } diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/memory_states.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/memory_states.cpp index 107a68d1b74856..83328034f7c1fa 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/memory_states.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/infer_request/memory_states.cpp @@ -31,98 +31,6 @@ InferenceEngine::ExecutableNetwork InferRequestVariableStateTest::PrepareNetwork return ie->LoadNetwork(net, deviceName); } -TEST_P(InferRequestVariableStateTest, smoke_VariableState_QueryState) { - IE_SUPPRESS_DEPRECATED_START - auto executableNet = PrepareNetwork(); - - auto states = executableNet.QueryState(); - ASSERT_TRUE(states.size() == 2) << "Incorrect number of VariableStates"; - - for (auto &&state : states) { - auto name = state.GetName(); - ASSERT_TRUE(std::find(statesToQuery.begin(), statesToQuery.end(), name) != statesToQuery.end()) - << "State " << name << "expected to be in memory states but it is not!"; - } - IE_SUPPRESS_DEPRECATED_END -} - -TEST_P(InferRequestVariableStateTest, smoke_VariableState_SetState) { - IE_SUPPRESS_DEPRECATED_START - auto executableNet = PrepareNetwork(); - const float new_state_val = 13.0f; - for (auto &&state : executableNet.QueryState()) { - state.Reset(); - auto state_val = state.GetState(); - auto element_count = state_val->size(); - - float *new_state_data = new float[element_count]; - for (int i = 0; i < element_count; i++) { - new_state_data[i] = new_state_val; - } - auto stateBlob = make_blob_with_precision(state_val->getTensorDesc()); - stateBlob->allocate(); - std::memcpy(stateBlob->buffer(), new_state_data, element_count * sizeof(float)); - delete[]new_state_data; - state.SetState(stateBlob); - } - - for (auto &&state : executableNet.QueryState()) { - auto lastState = state.GetState(); - auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); - ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; - - for (int i = 0; i < last_state_size; i++) { - EXPECT_NEAR(new_state_val, last_state_data[i], 1e-5); - } - } - IE_SUPPRESS_DEPRECATED_END -} - -TEST_P(InferRequestVariableStateTest, smoke_VariableState_Reset) { - IE_SUPPRESS_DEPRECATED_START - auto executableNet = PrepareNetwork(); - const float new_state_val = 13.0f; - for (auto &&state : executableNet.QueryState()) { - state.Reset(); - auto state_val = state.GetState(); - auto element_count = state_val->size(); - - float *new_state_data = new float[element_count]; - for (int i = 0; i < element_count; i++) { - new_state_data[i] = new_state_val; - } - auto stateBlob = make_blob_with_precision(state_val->getTensorDesc()); - stateBlob->allocate(); - std::memcpy(stateBlob->buffer(), new_state_data, element_count * sizeof(float)); - delete[]new_state_data; - - state.SetState(stateBlob); - } - - executableNet.QueryState().front().Reset(); - - auto states = executableNet.QueryState(); - for (int i = 0; i < states.size(); ++i) { - auto lastState = states[i].GetState(); - auto last_state_size = lastState->size(); - auto last_state_data = lastState->cbuffer().as(); - - ASSERT_TRUE(last_state_size != 0) << "State size should not be 0"; - - if (i == 0) { - for (int j = 0; j < last_state_size; ++j) { - EXPECT_NEAR(0, last_state_data[j], 1e-5); - } - } else { - for (int j = 0; j < last_state_size; ++j) { - EXPECT_NEAR(new_state_val, last_state_data[j], 1e-5); - } - } - } - IE_SUPPRESS_DEPRECATED_END -} - TEST_P(InferRequestVariableStateTest, inferreq_smoke_VariableState_QueryState) { auto executableNet = PrepareNetwork(); auto inferReq = executableNet.CreateInferRequest(); diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/io_tensor.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/io_tensor.cpp index 1f3f255ec6be54..b078389aa8ac06 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/io_tensor.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/io_tensor.cpp @@ -18,6 +18,8 @@ std::string OVInferRequestIOTensorTest::getTestCaseName(const testing::TestParam } void OVInferRequestIOTensorTest::SetUp() { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() OVInferRequestTests::SetUp(); req = execNet.create_infer_request(); input = execNet.input(); diff --git a/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/wait.cpp b/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/wait.cpp index 7764b0fbf76a21..8d73e9f749473d 100644 --- a/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/wait.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/behavior/ov_infer_request/wait.cpp @@ -14,6 +14,8 @@ std::string OVInferRequestWaitTests::getTestCaseName(const testing::TestParamInf } void OVInferRequestWaitTests::SetUp() { + // Skip test according to plugin specific disabledTestPatterns() (if any) + SKIP_IF_CURRENT_TEST_IS_DISABLED() OVInferRequestTests::SetUp(); req = execNet.create_infer_request(); input = execNet.input(); diff --git a/inference-engine/tests/functional/plugin/shared/src/blob_tests/detect_network_batch_test.cpp b/inference-engine/tests/functional/plugin/shared/src/blob_tests/detect_network_batch_test.cpp index f598a02792254e..097d1e6fb53b24 100644 --- a/inference-engine/tests/functional/plugin/shared/src/blob_tests/detect_network_batch_test.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/blob_tests/detect_network_batch_test.cpp @@ -57,6 +57,7 @@ void DetectNetworkBatch::LoadNetwork() { functionRefs = ngraph::clone_function(*cnnNetwork.getFunction()); ConfigureNetwork(); executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } TEST_P(DetectNetworkBatch, InferWithOneInput) { diff --git a/inference-engine/tests/functional/plugin/shared/src/blob_tests/dynamic_batch.cpp b/inference-engine/tests/functional/plugin/shared/src/blob_tests/dynamic_batch.cpp index 4eee1d3b6b20fb..17ff2e2506098c 100644 --- a/inference-engine/tests/functional/plugin/shared/src/blob_tests/dynamic_batch.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/blob_tests/dynamic_batch.cpp @@ -54,10 +54,10 @@ namespace ConfigurationTestsDefinitions { ConfigureNetwork(); cnnNetwork.setBatchSize(max_batch_size); executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } void DynamicBatchTest::Infer() { - inferRequest = executableNetwork.CreateInferRequest(); inputs.clear(); for (int i = 0; i < batch_sizes.size(); i++) { diff --git a/inference-engine/tests/functional/plugin/shared/src/onnx/quantized_models_tests.cpp b/inference-engine/tests/functional/plugin/shared/src/onnx/quantized_models_tests.cpp index c33709ecce1cbe..4285b952f8540b 100644 --- a/inference-engine/tests/functional/plugin/shared/src/onnx/quantized_models_tests.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/onnx/quantized_models_tests.cpp @@ -22,7 +22,8 @@ static std::string getModelFullPath(const char* path) { return FileUtils::makePath(TEST_MODELS, path); } -void QuantizedModelsTests::runModel(const char* model, const std::unordered_map& expected_layer_types) { +void QuantizedModelsTests::runModel(const char* model, const LayerInputTypes& expected_layer_input_types, float thr) { + threshold = thr; auto ie = getCore(); auto network = ie->ReadNetwork(getModelFullPath(model)); function = network.getFunction(); @@ -31,19 +32,34 @@ void QuantizedModelsTests::runModel(const char* model, const std::unordered_map< int ops_found = 0; for (const auto& node : runtime_function->get_ordered_ops()) { const auto& name = node->get_friendly_name(); - if (expected_layer_types.count(name)) { + if (expected_layer_input_types.count(name)) { ops_found++; - ASSERT_EQ(expected_layer_types.at(name), node->get_element_type()); + const auto& expected_input_types = expected_layer_input_types.at(name); + auto inputs = node->input_values(); + ASSERT_EQ(inputs.size(), expected_input_types.size()); + for (size_t i = 0; i < inputs.size(); i++) + ASSERT_EQ(expected_input_types[i], inputs[i].get_element_type()); } } ASSERT_GT(ops_found, 0); } TEST_P(QuantizedModelsTests, MaxPoolQDQ) { - runModel("max_pool_qdq.onnx", {{"890_original", ngraph::element::u8}}); + runModel("max_pool_qdq.onnx", {{"890_original", {ngraph::element::u8}}}, 1e-5); } TEST_P(QuantizedModelsTests, MaxPoolFQ) { - runModel("max_pool_fq.onnx", {{"887_original", ngraph::element::u8}}); + runModel("max_pool_fq.onnx", {{"887_original", {ngraph::element::u8}}}, 1e-5); } + +TEST_P(QuantizedModelsTests, ConvolutionQDQ) { + // activations have type uint8 and weights int8 + runModel("convolution_qdq.onnx", {{"908_original", {ngraph::element::u8, ngraph::element::i8}}}, 1.5e-2); +} + +TEST_P(QuantizedModelsTests, ConvolutionFQ) { + // activations have type uint8 and weights int8 + runModel("convolution_fq.onnx", {{"902_original", {ngraph::element::u8, ngraph::element::i8}}}, 1.5e-2); +} + } // namespace ONNXTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/ov_subgraph.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/ov_subgraph.hpp index de8870c21257c7..df0412f3a5d7ae 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/ov_subgraph.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/base/ov_subgraph.hpp @@ -31,8 +31,8 @@ class SubgraphBaseTest : public CommonTestUtils::TestsCommon { } protected: - void compare(const std::vector &expected, - const std::vector &actual); + virtual void compare(const std::vector &expected, + const std::vector &actual); virtual void configure_model(); virtual void compile_model(); diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/experimental_detectron_roifeatureextractor.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/experimental_detectron_roifeatureextractor.hpp new file mode 100644 index 00000000000000..f068e038f8fb95 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/experimental_detectron_roifeatureextractor.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ngraph_functions/utils/ngraph_helpers.hpp" +#include "common_test_utils/common_utils.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" + +namespace ov { +namespace test { +namespace subgraph { + +using Attrs = ov::op::v6::ExperimentalDetectronROIFeatureExtractor::Attributes; +using ExperimentalROI = ov::op::v6::ExperimentalDetectronROIFeatureExtractor; + +typedef std::tuple< + std::vector, // Input shapes + int64_t, // Output size + int64_t, // Sampling ratio + std::vector, // Pyramid scales + bool, // Aligned + ElementType, // Network precision + std::string // Device name>; +> ExperimentalDetectronROIFeatureExtractorTestParams; + +class ExperimentalDetectronROIFeatureExtractorLayerTest : public testing::WithParamInterface, + virtual public SubgraphBaseTest { +protected: + void SetUp() override; + +public: + static std::string getTestCaseName(const testing::TestParamInfo& obj); +}; +} // namespace subgraph +} // namespace test +} // namespace ov diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather_nd.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather_nd.hpp index 73d15a9ffb0a3c..53b2742d4ecd1e 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather_nd.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/gather_nd.hpp @@ -36,4 +36,13 @@ class GatherNDLayerTest : public testing::WithParamInterface, void SetUp() override; }; +class GatherND8LayerTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(const testing::TestParamInfo &obj); + +protected: + void SetUp() override; +}; + } // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/slice.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/slice.hpp new file mode 100644 index 00000000000000..946cc4e0ad7346 --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/slice.hpp @@ -0,0 +1,43 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +#include "shared_test_classes/base/layer_test_utils.hpp" + +namespace LayerTestsDefinitions { + +struct SliceSpecificParams { + InferenceEngine::SizeVector inputShape; + std::vector start; + std::vector stop; + std::vector step; + std::vector axes; +}; + +using SliceParams = std::tuple< + SliceSpecificParams, + InferenceEngine::Precision, // Net precision + InferenceEngine::Precision, // Input precision + InferenceEngine::Precision, // Output precision + InferenceEngine::Layout, // Input layout + InferenceEngine::Layout, // Output layout + std::string, // Device name + std::map // Additional network configuration +>; + +class SliceLayerTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(const testing::TestParamInfo &obj); + +protected: + void SetUp() override; +}; +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp b/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp index 95fc622a18f4b1..7a0300971211fc 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/base/layer_test_utils.cpp @@ -344,6 +344,7 @@ void LayerTestsCommon::LoadNetwork() { CoreConfiguration(this); ConfigureNetwork(); executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } void LayerTestsCommon::GenerateInputs() { @@ -361,8 +362,6 @@ void LayerTestsCommon::GenerateInputs() { } void LayerTestsCommon::Infer() { - inferRequest = executableNetwork.CreateInferRequest(); - const auto& inputsInfo = executableNetwork.GetInputsInfo(); const auto& functionParams = function->get_parameters(); for (int i = 0; i < functionParams.size(); ++i) { diff --git a/inference-engine/tests/functional/shared_test_classes/src/base/ov_subgraph.cpp b/inference-engine/tests/functional/shared_test_classes/src/base/ov_subgraph.cpp index 699d35f66bb8c8..6ae46c547936d1 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/base/ov_subgraph.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/base/ov_subgraph.cpp @@ -2,14 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include #include #ifdef _WIN32 #include #endif +#include "openvino/core/preprocess/pre_post_process.hpp" #include "openvino/pass/serialize.hpp" #include "graph_comparator.hpp" @@ -27,16 +28,16 @@ namespace test { void SubgraphBaseTest::run() { auto crashHandler = [](int errCode) { - auto &s = LayerTestsUtils::Summary::getInstance(); + auto& s = LayerTestsUtils::Summary::getInstance(); s.saveReport(); std::cerr << "Unexpected application crash with code: " << errCode << std::endl; std::abort(); }; signal(SIGSEGV, crashHandler); - LayerTestsUtils::PassRate::Statuses status = - FuncTestUtils::SkipTestsConfig::currentTestIsDisabled() ? - LayerTestsUtils::PassRate::Statuses::SKIPPED : LayerTestsUtils::PassRate::Statuses::CRASHED; + LayerTestsUtils::PassRate::Statuses status = FuncTestUtils::SkipTestsConfig::currentTestIsDisabled() + ? LayerTestsUtils::PassRate::Statuses::SKIPPED + : LayerTestsUtils::PassRate::Statuses::CRASHED; summary.setDeviceName(targetDevice); summary.updateOPsStats(function, status); SKIP_IF_CURRENT_TEST_IS_DISABLED(); @@ -54,12 +55,13 @@ void SubgraphBaseTest::run() { generate_inputs(targetStaticShapeVec); infer(); validate(); - } catch (const std::exception &ex) { - throw std::runtime_error("Incorrect target static shape: " + CommonTestUtils::vec2str(targetStaticShapeVec) + " " + ex.what()); + } catch (const std::exception& ex) { + throw std::runtime_error("Incorrect target static shape: " + + CommonTestUtils::vec2str(targetStaticShapeVec) + " " + ex.what()); } } status = LayerTestsUtils::PassRate::Statuses::PASSED; - } catch (const std::exception &ex) { + } catch (const std::exception& ex) { status = LayerTestsUtils::PassRate::Statuses::FAILED; errorMessage = ex.what(); } catch (...) { @@ -89,10 +91,13 @@ void SubgraphBaseTest::serialize() { bool success; std::string message; - std::tie(success, message) = - compare_functions(result, function, false, false, false, - true, // precision - true); // attributes + std::tie(success, message) = compare_functions(result, + function, + false, + false, + false, + true, // precision + true); // attributes EXPECT_TRUE(success) << message; @@ -115,8 +120,8 @@ void SubgraphBaseTest::query_model() { ASSERT_EQ(expected, actual); } -void SubgraphBaseTest::compare(const std::vector &expected, - const std::vector &actual) { +void SubgraphBaseTest::compare(const std::vector& expected, + const std::vector& actual) { ASSERT_EQ(expected.size(), actual.size()); for (size_t i = 0; i < expected.size(); i++) { ov::test::utils::compare(expected[i], actual[i], abs_threshold, rel_threshold); @@ -125,11 +130,13 @@ void SubgraphBaseTest::compare(const std::vector &expected, void SubgraphBaseTest::configure_model() { // configure input precision + ov::preprocess::PrePostProcessor p(function); { - auto params = function->get_parameters(); - for (auto& param : params) { + auto& params = function->get_parameters(); + for (size_t i = 0; i < params.size(); i++) { if (inType != ov::element::Type_t::undefined) { - param->get_output_tensor(0).set_element_type(inType); + p.input(ov::preprocess::InputInfo(i) + .tensor(ov::preprocess::InputTensorInfo().set_element_type(inType))); } } } @@ -137,12 +144,14 @@ void SubgraphBaseTest::configure_model() { // configure output precision { auto results = function->get_results(); - for (auto& result : results) { + for (size_t i = 0; i < results.size(); i++) { if (outType != ov::element::Type_t::undefined) { - result->get_output_tensor(0).set_element_type(outType); + p.output(ov::preprocess::OutputInfo(i) + .tensor(ov::preprocess::OutputTensorInfo().set_element_type(outType))); } } } + function = p.build(); } void SubgraphBaseTest::compile_model() { @@ -160,7 +169,8 @@ void SubgraphBaseTest::generate_inputs(const std::vector& targetInput const auto& funcInput = funcInputs[i]; ov::runtime::Tensor tensor; if (funcInput.get_element_type().is_real()) { - tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(), targetInputStaticShapes[i], 10, 0, 1000); + tensor = ov::test::utils::create_and_fill_tensor( + funcInput.get_element_type(), targetInputStaticShapes[i], 10, 0, 1000); } else { tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(), targetInputStaticShapes[i]); } @@ -197,8 +207,8 @@ void SubgraphBaseTest::validate() { return; } - ASSERT_EQ(actualOutputs.size(), expectedOutputs.size()) << "nGraph interpreter has " - << expectedOutputs.size() << " outputs, while IE " << actualOutputs.size(); + ASSERT_EQ(actualOutputs.size(), expectedOutputs.size()) + << "nGraph interpreter has " << expectedOutputs.size() << " outputs, while IE " << actualOutputs.size(); compare(expectedOutputs, actualOutputs); } @@ -213,11 +223,12 @@ void SubgraphBaseTest::init_input_shapes(const std::vector& shapes) dynShape = shape.second.front(); } inputDynamicShapes.push_back(dynShape); - ASSERT_EQ(shape.second.size(), targetStaticShapeSize) << "Target static count shapes should be the same for all inputs"; + ASSERT_EQ(shape.second.size(), targetStaticShapeSize) + << "Target static count shapes should be the same for all inputs"; for (size_t i = 0; i < shape.second.size(); ++i) { targetStaticShapes[i].push_back(shape.second.at(i)); } } } } // namespace test -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/activation.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/activation.cpp index 6ac2acea0316d7..ccc6d54df761d7 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/activation.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/activation.cpp @@ -137,17 +137,7 @@ InferenceEngine::Blob::Ptr ActivationLayerTest::GenerateInput(const InferenceEng data_range = 15; data_start_from = 0; } - if (activationType == ngraph::helpers::ActivationTypes::Exp && targetDevice == CommonTestUtils::DEVICE_GNA) { - const double max_result_on_GNA = 15.9; - const double exp_inverse = std::round(std::log(max_result_on_GNA)); - if (inPrcSigned) { - data_range = exp_inverse * 2.0; - data_start_from = -exp_inverse; - } else { - data_range = exp_inverse; - data_start_from = 0; - } - } + return FuncTestUtils::createAndFillBlob(info.getTensorDesc(), data_range, data_start_from, resolution); diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/eltwise.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/eltwise.cpp index 140f5dfb11ad38..c84364cc8d52a8 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/eltwise.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/eltwise.cpp @@ -40,6 +40,9 @@ std::string EltwiseLayerTest::getTestCaseName(const testing::TestParamInfo& obj) { + std::vector inputShapes; + int64_t outputSize, samplingRatio; + std::vector pyramidScales; + bool aligned; + ElementType netPrecision; + std::string targetName; + std::tie(inputShapes, outputSize, samplingRatio, pyramidScales, aligned, netPrecision, targetName) = obj.param; + + std::ostringstream result; + if (inputShapes.front().first.size() != 0) { + result << "IS=("; + for (const auto &shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result.seekp(-1, result.cur); + result << ")_"; + } + result << "TS="; + for (const auto& shape : inputShapes) { + for (const auto& item : shape.second) { + result << CommonTestUtils::vec2str(item) << "_"; + } + } + result << "outputSize=" << outputSize << "_"; + result << "samplingRatio=" << samplingRatio << "_"; + result << "pyramidScales=" << CommonTestUtils::vec2str(pyramidScales) << "_"; + std::string alig = aligned ? "true" : "false"; + result << "aligned=" << alig << "_"; + result << "netPRC=" << netPrecision << "_"; + result << "trgDev=" << targetName; + return result.str(); +} + +void ExperimentalDetectronROIFeatureExtractorLayerTest::SetUp() { + std::vector inputShapes; + int64_t outputSize, samplingRatio; + std::vector pyramidScales; + bool aligned; + ElementType netPrecision; + std::string targetName; + std::tie(inputShapes, outputSize, samplingRatio, pyramidScales, aligned, netPrecision, targetName) = this->GetParam(); + + inType = outType = netPrecision; + targetDevice = targetName; + + init_input_shapes(inputShapes); + + Attrs attrs; + attrs.aligned = aligned; + attrs.output_size = outputSize; + attrs.sampling_ratio = samplingRatio; + attrs.pyramid_scales = pyramidScales; + + auto params = ngraph::builder::makeDynamicParams(netPrecision, {inputDynamicShapes}); + auto paramsOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); + auto experimentalDetectronROIFeatureExtractor = std::make_shared(paramsOuts, attrs); + function = std::make_shared(ov::OutputVector{experimentalDetectronROIFeatureExtractor->output(0), + experimentalDetectronROIFeatureExtractor->output(1)}, + "ExperimentalDetectronROIFeatureExtractor"); +} +} // namespace subgraph +} // namespace test +} // namespace ov diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gather_nd.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gather_nd.cpp index 7ceca5670ff1ef..6e8806ec8a1fbc 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gather_nd.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gather_nd.cpp @@ -54,4 +54,30 @@ void GatherNDLayerTest::SetUp() { ngraph::ResultVector results{std::make_shared(gather)}; function = std::make_shared(results, params, "gatherND"); } + +std::string GatherND8LayerTest::getTestCaseName(const testing::TestParamInfo& obj) { + return GatherNDLayerTest::getTestCaseName(obj); +} + +void GatherND8LayerTest::SetUp() { + InferenceEngine::SizeVector dataShape, indicesShape; + InferenceEngine::Precision dPrecision, iPrecision; + int batchDims; + GatherNDParamsSubset gatherArgsSubset; + std::tie(gatherArgsSubset, dPrecision, iPrecision, targetDevice, configuration) = this->GetParam(); + std::tie(dataShape, indicesShape, batchDims) = gatherArgsSubset; + + auto ngDPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(dPrecision); + auto ngIPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(iPrecision); + + auto params = ngraph::builder::makeParams(ngDPrc, {dataShape}); + auto paramOuts = ngraph::helpers::convert2OutputVector( + ngraph::helpers::castOps2Nodes(params)); + auto dataNode = paramOuts[0]; + auto gather = std::dynamic_pointer_cast( + ngraph::builder::makeGatherND(dataNode, indicesShape, ngIPrc, batchDims)); + ngraph::ResultVector results{std::make_shared(gather)}; + function = std::make_shared(results, params, "gatherND"); +} + } // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp index d3da4c2c4cfd4b..bf8e79a8e30416 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/memory.cpp @@ -81,6 +81,7 @@ namespace LayerTestsDefinitions { CoreConfiguration(this); ConfigureNetwork(); executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } GenerateInputs(); for (int64_t i = 0; i < iteration_count; ++i) { diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp index 2a8d8f8497ec38..8c477178a257d4 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/non_max_suppression.cpp @@ -91,12 +91,12 @@ void NmsLayerTest::CompareBuffer(const std::vector(expectedBuffer), - reinterpret_cast(actualBuffer), size, 0); + reinterpret_cast(actualBuffer), size, threshold); break; case ngraph::element::Type_t::f64: LayerTestsUtils::LayerTestsCommon::Compare( reinterpret_cast(expectedBuffer), - reinterpret_cast(actualBuffer), size, 0); + reinterpret_cast(actualBuffer), size, threshold); break; default: break; diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/slice.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/slice.cpp new file mode 100644 index 00000000000000..60130e82480cfd --- /dev/null +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/slice.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ngraph_functions/builders.hpp" +#include "ngraph/ngraph.hpp" + +#include "shared_test_classes/single_layer/slice.hpp" + +using namespace ngraph; + +namespace LayerTestsDefinitions { + +std::string SliceLayerTest::getTestCaseName(const testing::TestParamInfo &obj) { + SliceSpecificParams params; + InferenceEngine::Precision netPrc; + InferenceEngine::Precision inPrc, outPrc; + InferenceEngine::Layout inLayout, outLayout; + std::string targetName; + std::map additionalConfig; + std::tie(params, netPrc, inPrc, outPrc, inLayout, outLayout, targetName, additionalConfig) = obj.param; + std::ostringstream result; + result << "inShape=" << CommonTestUtils::vec2str(params.inputShape) << "_"; + result << "netPRC=" << netPrc.name() << "_"; + result << "start=" << CommonTestUtils::vec2str(params.start) << "_"; + result << "stop=" << CommonTestUtils::vec2str(params.stop) << "_"; + result << "step=" << CommonTestUtils::vec2str(params.step) << "_"; + result << "axes=" << CommonTestUtils::vec2str(params.axes) << "_"; + result << "trgDev=" << targetName; + return result.str(); +} + +void SliceLayerTest::SetUp() { + SliceSpecificParams sliceParams; + InferenceEngine::Precision netPrecision; + std::map additionalConfig; + std::tie(sliceParams, netPrecision, inPrc, outPrc, inLayout, outLayout, targetDevice, additionalConfig) = this->GetParam(); + configuration.insert(additionalConfig.begin(), additionalConfig.end()); + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + + element::Type_t et = element::i32; + + const auto data = std::make_shared(ngPrc, Shape(sliceParams.inputShape)); + const auto start = std::make_shared(et, Shape{sliceParams.start.size()}, sliceParams.start); + const auto stop = std::make_shared(et, Shape{sliceParams.stop.size()}, sliceParams.stop); + const auto step = std::make_shared(et, Shape{sliceParams.step.size()}, sliceParams.step); + + Output slice; + if (sliceParams.axes.empty()) { + slice = std::make_shared(data, start, stop, step); + } else { + const auto axes = std::make_shared(et, Shape{sliceParams.axes.size()}, sliceParams.axes); + slice = std::make_shared(data, start, stop, step, axes); + } + + ResultVector results{std::make_shared(slice)}; + function = std::make_shared(results, ov::ParameterVector{data}, "Slice"); +} + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_quantization_during_memory_requantization.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_quantization_during_memory_requantization.cpp index 729dfdb4e508ef..c17b5267471e18 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_quantization_during_memory_requantization.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/concat_quantization_during_memory_requantization.cpp @@ -10,13 +10,17 @@ namespace SubgraphTestsDefinitions { std::string targetName; size_t inputSize; size_t hiddenSize; - std::tie(netPrecision, targetName, inputSize, hiddenSize, std::ignore) = obj.param; + std::map config; + std::tie(netPrecision, targetName, inputSize, hiddenSize, config) = obj.param; std::ostringstream results; results << "netPRC=" << netPrecision.name() << "_"; results << "IS=" << inputSize << "_"; results << "HS=" << hiddenSize << "_"; results << "targetDevice=" << targetName; + for (auto const& configItem : config) { + results << "_configItem=" << configItem.second; + } return results.str(); } @@ -99,8 +103,8 @@ namespace SubgraphTestsDefinitions { SKIP_IF_CURRENT_TEST_IS_DISABLED() LoadNetwork(); - IE_SUPPRESS_DEPRECATED_START - auto states = executableNetwork.QueryState(); + + auto states = inferRequest.QueryState(); for (auto& state : states) { auto name = state.GetName(); if (name == "memory_1") { @@ -115,7 +119,6 @@ namespace SubgraphTestsDefinitions { GTEST_FAIL() << "unknown memory state"; } } - IE_SUPPRESS_DEPRECATED_END GenerateInputs(); Infer(); switchToNgraphFriendlyModel(); diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/delayed_copy_layer.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/delayed_copy_layer.cpp index f8b094bc278c0c..885d24b6f2ba0e 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/delayed_copy_layer.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/delayed_copy_layer.cpp @@ -6,8 +6,7 @@ namespace SubgraphTestsDefinitions { void DelayedCopyTestBase::InitMemory() { - IE_SUPPRESS_DEPRECATED_START - auto states = executableNetwork.QueryState(); + auto states = inferRequest.QueryState(); for (auto& state : states) { auto name = state.GetName(); if (name.find("id") != std::string::npos) { @@ -18,7 +17,6 @@ namespace SubgraphTestsDefinitions { GTEST_FAIL() << "unknown memory state"; } } - IE_SUPPRESS_DEPRECATED_END } void DelayedCopyTestBase::Run() { diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/first_connect_input_concat.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/first_connect_input_concat.cpp index 9a92a5936dba70..f2999ab75294a7 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/first_connect_input_concat.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/first_connect_input_concat.cpp @@ -18,7 +18,9 @@ std::string ConcatFirstInputTest::getTestCaseName(const testing::TestParamInfoLoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } else if (transformation == ngraph::helpers::MemoryTransformation::LOW_LATENCY_V2_REGULAR_API) { cnnNetwork = InferenceEngine::CNNNetwork{function}; InferenceEngine::lowLatency2(cnnNetwork); @@ -339,6 +338,7 @@ namespace SubgraphTestsDefinitions { ConfigureNetwork(); executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } } } // namespace SubgraphTestsDefinitions diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp index 3c4d39558ac917..56e82d8dbb511d 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/memory_eltwise_reshape_concat.cpp @@ -122,7 +122,7 @@ void MemoryEltwiseReshapeConcatTest::Run() { InferenceEngine::Layout::NC); IE_SUPPRESS_DEPRECATED_START - auto states = executableNetwork.QueryState(); + auto states = inferRequest.QueryState(); auto state_values_blob = FuncTestUtils::createAndFillBlobWithFloatArray(state_description, memory_init.data(), memory_init.size()); states[0].SetState(state_values_blob); diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp index a3a131eb5b2345..29ea5c09798736 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_LSTMCell.cpp @@ -397,8 +397,7 @@ void MultipleLSTMCellTest::InitMemory() { InferenceEngine::TensorDesc state_description(InferenceEngine::Precision::FP32, InferenceEngine::SizeVector({1, hiddenSize}), InferenceEngine::Layout::NC); - IE_SUPPRESS_DEPRECATED_START - auto states = executableNetwork.QueryState(); + auto states = inferRequest.QueryState(); for (auto& state : states) { auto name = state.GetName(); if (name.find("cell_state_1") != std::string::npos) { @@ -421,7 +420,6 @@ void MultipleLSTMCellTest::InitMemory() { GTEST_FAIL() << "unknown memory state"; } } - IE_SUPPRESS_DEPRECATED_END } void MultipleLSTMCellTest::ApplyLowLatency() { @@ -459,6 +457,7 @@ void MultipleLSTMCellTest::ApplyLowLatency() { ConfigureNetwork(); executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } else if (transformation == ngraph::helpers::MemoryTransformation::LOW_LATENCY_V2_REGULAR_API) { cnnNetwork = InferenceEngine::CNNNetwork{function}; InferenceEngine::lowLatency2(cnnNetwork); @@ -468,6 +467,7 @@ void MultipleLSTMCellTest::ApplyLowLatency() { ConfigureNetwork(); executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice, configuration); + inferRequest = executableNetwork.CreateInferRequest(); } } diff --git a/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_concat.cpp b/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_concat.cpp index 60a16462320449..1aae54a8343b05 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_concat.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/subgraph/multiple_concat.cpp @@ -20,6 +20,9 @@ std::string MultipleConcatTest::getTestCaseName(const testing::TestParamInfo(void)); MOCK_METHOD0(GetExecGraphInfo, std::shared_ptr(void)); MOCK_METHOD1(SetConfig, void(const std::map &config)); diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_function.hpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_function.hpp index 325b981ec16e2e..1a93cc8a2b0220 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_function.hpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/include/lpt_ngraph_functions/convolution_function.hpp @@ -22,9 +22,15 @@ class ConvolutionFunction { const ngraph::element::Type netPrecision, const ngraph::element::Type inputPrecision, const ngraph::PartialShape& inputShape, - const ngraph::builder::subgraph::DequantizationOperations& dequantizationBefore, + const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnActivations, std::shared_ptr weights, - const ngraph::builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights); + const ngraph::builder::subgraph::FakeQuantizeOnWeights fqOnWeights, + const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnWeights = DequantizationOperations(), + const bool fqOnWeightsTransposeOnData = false, + const bool fqOnWeightsTransposeOnInputLow = false, + const bool fqOnWeightsTransposeOnInputHigh = false, + const bool fqOnWeightsTransposeOnOutputLow = false, + const bool fqOnWeightsTransposeOnOutputHigh = false); static std::shared_ptr getOriginalWithIncorrectWeights( const ngraph::Shape& inputShape, diff --git a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp index 1d2dc22bb860df..e5606d9647b8c8 100644 --- a/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp +++ b/inference-engine/tests/ngraph_helpers/lpt_ngraph_functions/src/convolution_function.cpp @@ -25,11 +25,17 @@ std::shared_ptr ConvolutionFunction::getOriginal( const ngraph::element::Type netPrecision, const ngraph::element::Type inputPrecision, const ngraph::PartialShape& inputShape, - const ngraph::builder::subgraph::DequantizationOperations& dequantizationBefore, + const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnActivations, std::shared_ptr weights, - const ngraph::builder::subgraph::FakeQuantizeOnWeights fakeQuantizeOnWeights) { + const ngraph::builder::subgraph::FakeQuantizeOnWeights fqOnWeights, + const ngraph::builder::subgraph::DequantizationOperations& dequantizationOnWeights, + const bool transposeOnData, + const bool transposeOnInputLow, + const bool transposeOnInputHigh, + const bool transposeOnOutputLow, + const bool transposeOnOutputHigh) { const auto input = std::make_shared(inputPrecision, inputShape); - auto dequantizationStructure = dequantizationBefore; + auto dequantizationStructure = dequantizationOnActivations; dequantizationStructure.multiply.outPrecision = netPrecision; const auto dequantization = makeDequantization(input, dequantizationStructure); @@ -48,20 +54,45 @@ std::shared_ptr ConvolutionFunction::getOriginal( weights, op::Constant::create(ngraph::element::i64, Shape{ targetShape.size() }, targetShape))); } - const auto convertOnWeights = std::make_shared(weights, netPrecision); - OutputVector convertedOutput(1); - convertOnWeights->constant_fold(convertedOutput, convertOnWeights->input_values()); - const auto convertedWeights = convertedOutput[0].get_node_shared_ptr(); + std::shared_ptr convertedWeights; + if (dequantizationOnWeights.empty()) { + const auto convertOnWeights = std::make_shared(weights, netPrecision); + OutputVector convertedOutput(1); + convertOnWeights->constant_fold(convertedOutput, convertOnWeights->input_values()); + convertedWeights = convertedOutput[0].get_node_shared_ptr(); + } else { + convertedWeights = weights; + } - const auto onWeights = fakeQuantizeOnWeights.empty() ? convertedWeights : - ngraph::builder::makeFakeQuantize( - convertedWeights, netPrecision, - fakeQuantizeOnWeights.quantizationLevel, - fakeQuantizeOnWeights.constantShape, - fakeQuantizeOnWeights.inputLowValues, - fakeQuantizeOnWeights.inputHighValues, - fakeQuantizeOnWeights.outputLowValues, - fakeQuantizeOnWeights.outputHighValues); + const std::shared_ptr constant = ngraph::opset1::Constant::create(ngraph::element::u64, ngraph::Shape{4}, {0, 1, 2, 3}); + std::shared_ptr onWeights; + if (fqOnWeights.empty()) { + onWeights = dequantizationOnWeights.empty() ? convertedWeights : makeDequantization(convertedWeights, dequantizationOnWeights); + } else { + onWeights = std::make_shared( + transposeOnData ? std::make_shared(convertedWeights, constant) : convertedWeights, + transposeOnInputLow ? + std::make_shared( + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.inputLowValues, fqOnWeights.inputLowValues.empty()), + constant->clone_with_new_inputs({})) : + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.inputLowValues, fqOnWeights.inputLowValues.empty()), + transposeOnInputHigh ? + std::make_shared( + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.inputHighValues, fqOnWeights.inputHighValues.empty()), + constant->clone_with_new_inputs({})) : + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.inputHighValues, fqOnWeights.inputHighValues.empty()), + transposeOnOutputLow ? + std::make_shared( + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.outputLowValues, fqOnWeights.outputLowValues.empty()), + constant->clone_with_new_inputs({})) : + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.outputLowValues, fqOnWeights.outputLowValues.empty()), + transposeOnOutputHigh ? + std::make_shared( + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.outputHighValues, fqOnWeights.outputHighValues.empty()), + constant->clone_with_new_inputs({})) : + makeConstant(netPrecision, fqOnWeights.constantShape, fqOnWeights.outputHighValues, fqOnWeights.outputHighValues.empty()), + fqOnWeights.quantizationLevel); + } auto convolutionOriginal = ngraph::opset1::Convolution( ngraph::op::TemporaryReplaceOutputType(dequantization, netPrecision).get(), diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/preprocess/preprocess_builders.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/preprocess/preprocess_builders.hpp index 381317bcb2fca1..ed9fdc34c9ebc8 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/preprocess/preprocess_builders.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/preprocess/preprocess_builders.hpp @@ -81,90 +81,90 @@ inline std::shared_ptr create_preprocess_2inputs_trivial() { inline std::shared_ptr mean_only() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, Shape{1, 3, 24, 24}); - function = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().mean(1.1f))).build(function); + function = PrePostProcessor(function).input(InputInfo().preprocess(PreProcessSteps().mean(1.1f))).build(); return function; } inline std::shared_ptr scale_only() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, Shape{1, 3, 24, 24}); - function = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().scale(2.1f))).build(function); + function = PrePostProcessor(function).input(InputInfo().preprocess(PreProcessSteps().scale(2.1f))).build(); return function; } inline std::shared_ptr mean_scale() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, Shape{1, 3, 24, 24}); - function = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().mean(1.1f).scale(2.1f))).build(function); + function = PrePostProcessor(function).input(InputInfo().preprocess(PreProcessSteps().mean(1.1f).scale(2.1f))).build(); return function; } inline std::shared_ptr scale_mean() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, Shape{1, 3, 24, 24}); - function = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().scale(2.1f).mean(1.1f))).build(function); + function = PrePostProcessor(function).input(InputInfo().preprocess(PreProcessSteps().scale(2.1f).mean(1.1f))).build(); return function; } inline std::shared_ptr mean_vector() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, Shape{1, 3, 24, 24}); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW")) - .preprocess(PreProcessSteps().mean({2.2f, 3.3f, 4.4f}))).build(function); + .preprocess(PreProcessSteps().mean({2.2f, 3.3f, 4.4f}))).build(); return function; } inline std::shared_ptr scale_vector() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, Shape{1, 3, 24, 24}); - function = PrePostProcessor().input(InputInfo() + function = PrePostProcessor(function).input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW")) - .preprocess(PreProcessSteps().scale({2.2f, 3.3f, 4.4f}))).build(function); + .preprocess(PreProcessSteps().scale({2.2f, 3.3f, 4.4f}))).build(); return function; } inline std::shared_ptr convert_element_type_and_mean() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::u8, Shape{1, 3, 24, 24}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .preprocess(PreProcessSteps() .convert_element_type(element::f32) .mean(0.2f) .convert_element_type(element::u8))) - .build(function); + .build(); return function; } inline std::shared_ptr tensor_element_type_and_mean() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::u8, Shape{1, 3, 12, 12}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::f32)) .preprocess(PreProcessSteps().mean(0.1f).convert_element_type(element::u8))) - .build(function); + .build(); return function; } inline std::shared_ptr custom_preprocessing() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::i32, Shape{3, 4, 10, 20}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo().preprocess(PreProcessSteps().custom([](const Output& node) { auto abs = std::make_shared(node); abs->set_friendly_name(node.get_node_shared_ptr()->get_friendly_name() + "/abs"); return abs; }))) - .build(function); + .build(); return function; } inline std::shared_ptr lvalues_multiple_ops() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::u8, Shape{1, 3, 3, 3}); - auto p = PrePostProcessor(); + auto p = PrePostProcessor(function); auto p1 = std::move(p); p = std::move(p1); auto inputInfo = InputInfo(); @@ -195,21 +195,21 @@ inline std::shared_ptr lvalues_multiple_ops() { inputInfo.preprocess(std::move(same)); } p.input(std::move(inputInfo)); - function = p.build(function); + function = p.build(); return function; } inline std::shared_ptr two_inputs_basic() { using namespace ov::preprocess; auto function = create_preprocess_2inputs(element::f32, Shape{1, 3, 1, 1}); - function = PrePostProcessor().input(InputInfo(1).preprocess(PreProcessSteps().mean(1.f).scale(2.0f))).build(function); + function = PrePostProcessor(function).input(InputInfo(1).preprocess(PreProcessSteps().mean(1.f).scale(2.0f))).build(); return function; } inline std::shared_ptr two_inputs_trivial() { using namespace ov::preprocess; auto function = create_preprocess_2inputs_trivial(); - function = PrePostProcessor().input(InputInfo(1).preprocess(PreProcessSteps().mean(1.f).scale(2.0f))).build(function); + function = PrePostProcessor(function).input(InputInfo(1).preprocess(PreProcessSteps().mean(1.f).scale(2.0f))).build(); return function; } @@ -217,9 +217,9 @@ inline std::shared_ptr reuse_network_layout() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{4, 3, 2, 1}); function->get_parameters().front()->set_layout("NC??"); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo().preprocess(PreProcessSteps().mean({1.1f, 2.2f, 3.3f}).scale({2.f, 3.f, 4.f}))) - .build(function); + .build(); return function; } @@ -227,66 +227,66 @@ inline std::shared_ptr tensor_layout() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{4, 3, 2, 1}); function->get_parameters().front()->set_layout("NC??"); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NC??")) .preprocess(PreProcessSteps().mean({1.1f, 2.2f, 3.3f}).scale({2.f, 3.f, 4.f}))) - .build(function); + .build(); return function; } inline std::shared_ptr resize_linear() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 3, 10, 10}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(20, 20)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); return function; } inline std::shared_ptr resize_nearest() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 3, 10, 10}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(20, 20)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_NEAREST)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); return function; } inline std::shared_ptr resize_linear_nhwc() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 10, 10, 3}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(20, 20)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NHWC"))) - .build(function); + .build(); return function; } inline std::shared_ptr resize_cubic() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 3, 20, 20}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(10, 10)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_CUBIC)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); return function; } inline std::shared_ptr resize_and_convert_layout() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 30, 20, 3}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo() .set_layout("NHWC") @@ -295,25 +295,25 @@ inline std::shared_ptr resize_and_convert_layout() { .convert_layout() .resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); return function; } inline std::shared_ptr convert_layout_by_dims() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 30, 20, 3}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .preprocess(PreProcessSteps() .convert_layout({0, 3, 1, 2}))) - .build(function); + .build(); return function; } inline std::shared_ptr resize_and_convert_layout_i8() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::i8, PartialShape{1, 30, 20, 3}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo() .set_layout("NHWC") @@ -322,36 +322,36 @@ inline std::shared_ptr resize_and_convert_layout_i8() { .convert_layout() .resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); return function; } inline std::shared_ptr cvt_color_nv12_to_rgb_single_plane() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 20, 20, 3}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))) - .build(function); + .build(); return function; } inline std::shared_ptr cvt_color_nv12_to_bgr_two_planes() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 20, 20, 3}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR))) - .build(function); + .build(); return function; } inline std::shared_ptr cvt_color_nv12_cvt_layout_resize() { using namespace ov::preprocess; auto function = create_preprocess_1input(element::f32, PartialShape{1, 3, 10, 10}); - function = PrePostProcessor() + function = PrePostProcessor(function) .input(InputInfo() .tensor(InputTensorInfo() .set_color_format(ColorFormat::NV12_TWO_PLANES) @@ -363,7 +363,7 @@ inline std::shared_ptr cvt_color_nv12_cvt_layout_resize() { .convert_element_type(element::f32) .resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(function); + .build(); return function; } diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp index d8bb4a027165d2..a518b080af3f0e 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/subgraph_builders.hpp @@ -550,6 +550,23 @@ inline std::shared_ptr makeReadConcatSplitAssign(std::vectorset_friendly_name("ReadConcatSplitAssign"); return fn_ptr; } + +inline std::shared_ptr makeMatMulBias(std::vector inputShape = { 1, 3, 24, 24 }, + ngraph::element::Type type = ngraph::element::Type_t::f32) { + auto parameter = ngraph::builder::makeParams(type, { inputShape }); + parameter[0]->set_friendly_name("parameter"); + auto weights = ngraph::opset1::Constant::create(type, ngraph::Shape{ 24, 24 }, { 1 }); + auto biases = ngraph::opset1::Constant::create(type, ngraph::Shape{ 1, 24 }, { 1 }); + auto matmul = std::make_shared(parameter[0], weights); + matmul->set_friendly_name("matmul"); + auto add = std::make_shared(matmul, biases); + add->set_friendly_name("add"); + auto result = std::make_shared(add); + result->set_friendly_name("result"); + std::shared_ptr fn_ptr = std::make_shared(ngraph::ResultVector{ result }, ngraph::ParameterVector{ parameter }); + fn_ptr->set_friendly_name("MatMulBias"); + return fn_ptr; +} } // namespace subgraph } // namespace builder } // namespace ngraph diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_to_space.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_to_space.cpp index 59f23e654b9dcf..a60a708afa5293 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_to_space.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/batch_to_space.cpp @@ -12,7 +12,7 @@ std::shared_ptr makeBatchToSpace(const ngraph::Output &in, const std::vector &blockShape, const std::vector &cropsBegin, const std::vector &cropsEnd) { - ngraph::Shape constShape = {in.get_shape().size()}; + ngraph::Shape constShape = {in.get_partial_shape().size()}; auto blockShapeNode = std::make_shared(ngraph::element::i64, constShape, blockShape.data()); auto cropsBeginNode = std::make_shared(ngraph::element::i64, constShape, diff --git a/inference-engine/tests/unit/cpu/CMakeLists.txt b/inference-engine/tests/unit/cpu/CMakeLists.txt index a66c27aa5c2a29..d44d258421261a 100644 --- a/inference-engine/tests/unit/cpu/CMakeLists.txt +++ b/inference-engine/tests/unit/cpu/CMakeLists.txt @@ -8,8 +8,8 @@ addIeTargetTest( NAME ${TARGET_NAME} ROOT ${CMAKE_CURRENT_SOURCE_DIR} INCLUDES - ${IE_MAIN_SOURCE_DIR}/src/mkldnn_plugin - ${IE_MAIN_SOURCE_DIR}/src/mkldnn_plugin/nodes + $ + $/nodes $ OBJECT_FILES $ diff --git a/inference-engine/tests/unit/gna/CMakeLists.txt b/inference-engine/tests/unit/gna/CMakeLists.txt index 76a2a1ac94fb76..cff4aa3d20e995 100644 --- a/inference-engine/tests/unit/gna/CMakeLists.txt +++ b/inference-engine/tests/unit/gna/CMakeLists.txt @@ -4,15 +4,22 @@ set(TARGET_NAME gnaUnitTests) +# TODO: fix CVS-71010 and remove BUILD_SHARED_LIBS +if(NOT BUILD_SHARED_LIBS) + set(exclude_path EXCLUDED_SOURCE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/(gna_api_stub|gna_wait_test).cpp") +endif() + addIeTargetTest( NAME ${TARGET_NAME} ROOT ${CMAKE_CURRENT_SOURCE_DIR} + ${exclude_path} LINK_LIBRARIES PRIVATE ngraphFunctions gmock commonTestUtils_s GNAPlugin_test_static + engines_test_util ADD_CPPLINT LABELS GNA diff --git a/inference-engine/tests/unit/gna/ngraph/op_eval/softsign.cpp b/inference-engine/tests/unit/gna/ngraph/op_eval/softsign.cpp new file mode 100644 index 00000000000000..4df575cbb3414a --- /dev/null +++ b/inference-engine/tests/unit/gna/ngraph/op_eval/softsign.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ops/softsign.hpp" + +#include +#include + +#include "execute_tools.hpp" +#include "gtest/gtest.h" +#include "ngraph/runtime/host_tensor.hpp" +#include "ngraph/validation_util.hpp" +#include "ngraph/opsets/opset8.hpp" + +using namespace GNAPluginNS; + +TEST(op_eval, softsign) { + auto p = std::make_shared(ngraph::element::f32, ngraph::Shape{4}); + auto softsign = std::make_shared(p); + auto fun = std::make_shared(ngraph::OutputVector{softsign}, ngraph::ParameterVector{p}); + + float inputs[] = {-1.0, 0.0, 1.0, 20.0}; + std::vector expected_result{0.5, 1.0, 0.5, 0.047619}; + + ov::runtime::TensorVector result(1); + ov::runtime::Tensor input{ov::element::f32, ov::Shape{4}, inputs}; + + ASSERT_TRUE(fun->evaluate(result, ov::runtime::TensorVector{input})); + + EXPECT_EQ(result.size(), 1); + EXPECT_EQ(result[0].get_element_type(), ngraph::element::f32); + EXPECT_EQ(result[0].get_shape(), ngraph::Shape{4}); + EXPECT_EQ(result[0].get_size(), 4); + + const float * result_data = result[0].data(); + for (size_t i = 0; i < result[0].get_size(); ++i) + EXPECT_NEAR(result_data[i], expected_result[i], 0.000001); +} + diff --git a/inference-engine/tests/unit/gna/ngraph/transformations/gna_substitute_softsign.cpp b/inference-engine/tests/unit/gna/ngraph/transformations/gna_substitute_softsign.cpp new file mode 100644 index 00000000000000..8df3db75000113 --- /dev/null +++ b/inference-engine/tests/unit/gna/ngraph/transformations/gna_substitute_softsign.cpp @@ -0,0 +1,167 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "transformations/substitute_softsign.hpp" + +#include "common_test_utils/ngraph_test_utils.hpp" +#include +#include +#include +#include +#include + +namespace testing { + +namespace { + +std::shared_ptr createSoftSignFunction() { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto softsign = std::make_shared(input_params); + + ngraph::ResultVector results{ std::make_shared(softsign) }; + + return std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); +} + +} // namespace + +TEST(TransformationTests, SubstituteSoftSignMulPower) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1}); + auto const_neg_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1}); + + auto add = std::make_shared(abs, const_1); + auto power = std::make_shared(add, const_neg_1); + + auto mul = std::make_shared(power, input_params); + ngraph::ResultVector results{ std::make_shared(mul) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = createSoftSignFunction(); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +TEST(TransformationTests, SubstituteSoftSignDivide) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1}); + auto add = std::make_shared(abs, const_1); + + auto divide = std::make_shared(input_params, add); + ngraph::ResultVector results{ std::make_shared(divide) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = createSoftSignFunction(); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +TEST(TransformationTests, SubstituteSoftSignMulPowerInvalidAddConst) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.1}); + auto const_neg_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1}); + + auto add = std::make_shared(abs, const_1); + auto power = std::make_shared(add, const_neg_1); + + auto mul = std::make_shared(power, input_params); + ngraph::ResultVector results{ std::make_shared(mul) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = ngraph::clone_function(*func); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +TEST(TransformationTests, SubstituteSoftSignMulPowerInvalidPowerConst) { + std::shared_ptr func(nullptr), reference_func(nullptr); + + { + auto input_params = std::make_shared(ngraph::element::f32, + ngraph::Shape{ 1, 1, 1, 64 }); + + auto abs = std::make_shared(input_params); + + auto const_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1}); + auto const_neg_1 = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-1.1}); + + auto add = std::make_shared(abs, const_1); + auto power = std::make_shared(add, const_neg_1); + + auto mul = std::make_shared(power, input_params); + ngraph::ResultVector results{ std::make_shared(mul) }; + + func = std::make_shared(ngraph::ResultVector{results}, + ngraph::ParameterVector{input_params}); + ngraph::pass::Manager m; + m.register_pass(); + m.register_pass(); + m.run_passes(func); + ASSERT_NO_THROW(check_rt_info(func)); + } + + reference_func = ngraph::clone_function(*func); + + const FunctionsComparator func_comparator = FunctionsComparator::with_default().enable(FunctionsComparator::ATTRIBUTES); + const FunctionsComparator::Result result = func_comparator(func, reference_func); + ASSERT_TRUE(result.valid); +} + +} // namespace testing diff --git a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp index c4f0395023e360..8d7d39b92a3d4f 100644 --- a/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp +++ b/inference-engine/tests/unit/inference_engine/cpp_interfaces/ie_memory_state_internal_test.cpp @@ -43,162 +43,6 @@ class InferRequestVariableStateTests : public ::testing::Test { } }; -TEST_F(InferRequestVariableStateTests, ExecutableNetworkCanConvertOneVariableStateFromCppToAPI) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn(1); - toReturn[0] = mockVariableStateInternal; - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - - auto state = net->QueryState(); - ASSERT_EQ(state.size(), 1); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, ExecutableNetworkCanConvertZeroVariableStateFromCppToAPI) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).WillOnce(Return(toReturn)); - - auto state = net->QueryState(); - ASSERT_EQ(state.size(), 0); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, ExecutableNetworkCanConvert2VariableStatesFromCPPtoAPI) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - - auto state = net->QueryState(); - ASSERT_EQ(state.size(), 2); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, VariableStatePropagatesReset) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), Reset()).Times(1); - - auto state = net->QueryState(); - state.front()->Reset(); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, VariableStatePropagatesExceptionsFromReset) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), Reset()).WillOnce(Throw(std::logic_error("some error"))); - - auto state = net->QueryState(); - EXPECT_ANY_THROW(state.front()->Reset()); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetName) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), GetName()).WillOnce(Return("someName")); - - auto state = net->QueryState(); - EXPECT_STREQ(state.front()->GetName().c_str(), "someName"); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetNameWithZeroLen) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), GetName()).WillOnce(Return("someName")); - - auto pState = net->QueryState().front(); - EXPECT_NO_THROW(pState->GetName()); - IE_SUPPRESS_DEPRECATED_END -} - - -TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetNameWithLenOfOne) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), GetName()).WillOnce(Return("someName")); - - auto pState = net->QueryState().front(); - std::string name; - EXPECT_NO_THROW(name = pState->GetName()); - EXPECT_EQ(name, "someName"); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, VariableStatePropagatesGetNameWithLenOfTwo) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).Times(1).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), GetName()).WillOnce(Return("someName")); - - auto pState = net->QueryState().front(); - std::string name; - EXPECT_NO_THROW(name = pState->GetName()); - EXPECT_EQ(name, "someName"); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, VariableStateCanPropagateSetState) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - Blob::Ptr saver; - toReturn.push_back(mockVariableStateInternal); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), SetState(_)).WillOnce(SaveArg<0>(&saver)); - - float data[] = {123, 124, 125}; - auto stateBlob = make_shared_blob({ Precision::FP32, {3}, C }, data, sizeof(data) / sizeof(*data)); - - EXPECT_NO_THROW(net->QueryState().front()->SetState(stateBlob)); - ASSERT_FLOAT_EQ(saver->buffer().as()[0], 123); - ASSERT_FLOAT_EQ(saver->buffer().as()[1], 124); - ASSERT_FLOAT_EQ(saver->buffer().as()[2], 125); - IE_SUPPRESS_DEPRECATED_END -} - -TEST_F(InferRequestVariableStateTests, VariableStateCanPropagateGetLastState) { - IE_SUPPRESS_DEPRECATED_START - std::vector toReturn; - toReturn.push_back(mockVariableStateInternal); - - float data[] = {123, 124, 125}; - auto stateBlob = make_shared_blob({ Precision::FP32, {3}, C }, data, sizeof(data) / sizeof(*data)); - - EXPECT_CALL(*mockExeNetworkInternal.get(), QueryState()).WillRepeatedly(Return(toReturn)); - EXPECT_CALL(*mockVariableStateInternal.get(), GetState()).WillOnce(Return(stateBlob)); - - auto saver = net->QueryState().front()->GetState(); - ASSERT_NE(saver, nullptr); - ASSERT_FLOAT_EQ(saver->cbuffer().as()[0], 123); - ASSERT_FLOAT_EQ(saver->cbuffer().as()[1], 124); - ASSERT_FLOAT_EQ(saver->cbuffer().as()[2], 125); - IE_SUPPRESS_DEPRECATED_END -} class VariableStateInternalMockImpl : public IVariableStateInternal { public: VariableStateInternalMockImpl(const char* name) : IVariableStateInternal(name) {} diff --git a/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp b/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp index 7c9a41fb5d2f99..8b5021093943e7 100644 --- a/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp +++ b/inference-engine/tests/unit/inference_engine/ie_executable_network_test.cpp @@ -88,26 +88,6 @@ TEST_F(ExecutableNetworkTests, GetInputsInfo) { ASSERT_EQ(info, InferenceEngine::ConstInputsDataMap{}); } -IE_SUPPRESS_DEPRECATED_START - -TEST_F(ExecutableNetworkTests, QueryStateThrowsIfReturnErr) { - EXPECT_CALL(*mockIExeNet.get(), QueryState()) - .Times(1) - .WillOnce(Throw(InferenceEngine::GeneralError{""})); - EXPECT_THROW(exeNetwork->QueryState(), InferenceEngine::Exception); -} - -TEST_F(ExecutableNetworkTests, QueryState) { - auto mockIMemState_p = std::make_shared(); - EXPECT_CALL(*mockIExeNet.get(), QueryState()) - .Times(1) - .WillOnce(Return(std::vector>(1, mockIMemState_p))); - std::vector MemState_v; - EXPECT_NO_THROW(MemState_v = exeNetwork->QueryState()); - EXPECT_EQ(MemState_v.size(), 1); -} - -IE_SUPPRESS_DEPRECATED_END class ExecutableNetworkWithIInferReqTests : public ExecutableNetworkTests { protected: @@ -135,6 +115,29 @@ TEST_F(ExecutableNetworkWithIInferReqTests, CreateInferRequestThrowsIfReturnNotO ASSERT_THROW(exeNetwork->CreateInferRequest(), InferenceEngine::Exception); } +TEST_F(ExecutableNetworkWithIInferReqTests, QueryStateThrowsIfReturnErr) { + EXPECT_CALL(*mockIExeNet.get(), CreateInferRequest()).WillOnce(Return(mockIInferReq_p)); + IInferRequestInternal::Ptr actualInferReq; + ASSERT_NO_THROW(actualInferReq = exeNetwork->CreateInferRequest()); + EXPECT_CALL(*mockIInferReq_p.get(), QueryState()) + .Times(1) + .WillOnce(Throw(InferenceEngine::GeneralError{""})); + EXPECT_THROW(actualInferReq->QueryState(), InferenceEngine::Exception); +} + +TEST_F(ExecutableNetworkWithIInferReqTests, QueryState) { + EXPECT_CALL(*mockIExeNet.get(), CreateInferRequest()).WillOnce(Return(mockIInferReq_p)); + IInferRequestInternal::Ptr actualInferReq; + ASSERT_NO_THROW(actualInferReq = exeNetwork->CreateInferRequest()); + auto mockIMemState_p = std::make_shared(); + EXPECT_CALL(*mockIInferReq_p.get(), QueryState()) + .Times(1) + .WillOnce(Return(std::vector>(1, mockIMemState_p))); + std::vector MemState_v; + EXPECT_NO_THROW(MemState_v = actualInferReq->QueryState()); + EXPECT_EQ(MemState_v.size(), 1); +} + IE_SUPPRESS_DEPRECATED_START class ExecutableNetworkBaseTests : public ::testing::Test { diff --git a/inference-engine/tests/unit/vpu/base/graph_transformer_tests.cpp b/inference-engine/tests/unit/vpu/base/graph_transformer_tests.cpp index 15cfffd0343a34..8f89c28a8e50f3 100644 --- a/inference-engine/tests/unit/vpu/base/graph_transformer_tests.cpp +++ b/inference-engine/tests/unit/vpu/base/graph_transformer_tests.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -414,7 +414,7 @@ PluginConfiguration createConfiguration() { configuration.registerOption(); configuration.registerOption(); configuration.registerOption(); - configuration.registerOption(); + configuration.registerOption(); configuration.registerOption(); configuration.registerOption(); configuration.registerOption(); diff --git a/inference-engine/tests/unit/vpu/middleend_tests/passes_tests/vpu_scale_tests.cpp b/inference-engine/tests/unit/vpu/middleend_tests/passes_tests/vpu_scale_tests.cpp new file mode 100644 index 00000000000000..5d3e42e5286086 --- /dev/null +++ b/inference-engine/tests/unit/vpu/middleend_tests/passes_tests/vpu_scale_tests.cpp @@ -0,0 +1,162 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "graph_transformer_tests.hpp" +#include +#include +#include "ngraph_functions/subgraph_builders.hpp" +#include "vpu/private_plugin_config.hpp" +#include "common_test_utils/common_utils.hpp" + +#if defined(__GNUC__) && (__GNUC__ <= 4) && (__GNUC_MINOR__ < 9) && !defined(__clang__) && !defined(IE_GCC_4_8) +#define IE_GCC_4_8 +#endif + +using namespace vpu; +IE_SUPPRESS_DEPRECATED_START +namespace LayerTestsDefinitions { +typedef std::tuple< + std::string +> VpuScaleParams; + +class VpuScaleTest : public testing::WithParamInterface, + public GraphTransformerTest { +protected: + void SetUp() override; + void Compile() { + m_pipeline.run(m_testModel); + } + +protected: + std::string configValue = {}; + Model m_testModel; + +private: + void InitModel() { + int kernelx = 16; + int kernely = 1; + int kernelStrideX = 1; + int kernelStrideY = 1; + int dilationX = 1; + int dilationY = 1; + int padx_begin = 7; + int pady_begin = 0; + int padx_end = 8; + int pady_end = 0; + m_testModel = CreateModel(); + int inputX = 32; + int inputY = 32; + + auto input = m_testModel->addInputData( + "Input", + DataDesc(DataType::FP16, DimsOrder::NCHW, {inputX, inputY, 8, 1})); + m_testModel->attrs().set("numInputs", 1); + + Data output; + + output = m_testModel->addOutputData( + "Output", + DataDesc( + DataType::FP16, DimsOrder::NCHW, + {(inputX + padx_begin + padx_end - kernelx) / kernelStrideX + 1, + (inputY + pady_begin + pady_end - kernely) / kernelStrideY + 1, + 8, 1})); + + auto conv = std::make_shared(ie::LayerParams{"conv1", "Convolution", ie::Precision::FP16}); + conv->_kernel_x = kernelx; + conv->_kernel_y = kernely; + conv->_stride_x = kernelStrideX; + conv->_stride_y = kernelStrideY; + conv->_dilation_x = dilationX; + conv->_dilation_x = dilationY; + + conv->_padding.insert(0, padx_begin); + conv->_padding.insert(1, pady_begin); + conv->_pads_end.insert(0, padx_end); + conv->_pads_end.insert(1, pady_end); + conv->_auto_pad = "same_upper"; + + conv->_weights = ie::make_shared_blob({ ie::Precision::FP16, {static_cast(kernelx * kernely * 8 * 8)}, ie::Layout::C }); + conv->_weights->allocate(); + + frontEnd->parseConvolution(m_testModel, conv, {input}, {output}); + Data output2; + + output2 = m_testModel->addOutputData( + "Output", + DataDesc( + DataType::FP16, DimsOrder::NCHW, + {(inputX + padx_begin + padx_end - kernelx) / kernelStrideX + 1, + (inputY + pady_begin + pady_end - kernely) / kernelStrideY + 1, + 8, 1})); + auto conv2 = std::make_shared(ie::LayerParams{"conv2", "Convolution", ie::Precision::FP16}); + conv2->_kernel_x = kernelx; + conv2->_kernel_y = kernely; + conv2->_stride_x = kernelStrideX; + conv2->_stride_y = kernelStrideY; + conv2->_dilation_x = dilationX; + conv2->_dilation_x = dilationY; + + conv2->_padding.insert(0, padx_begin); + conv2->_padding.insert(1, pady_begin); + conv2->_pads_end.insert(0, padx_end); + conv2->_pads_end.insert(1, pady_end); + conv2->_auto_pad = "same_upper"; + + conv2->_weights = ie::make_shared_blob({ ie::Precision::FP16, {static_cast(kernelx * kernely * 8 * 8)}, ie::Layout::C }); + conv2->_weights->allocate(); + + frontEnd->parseConvolution(m_testModel, conv2, {output}, {output2}); + } + + void InitPipeline() { + m_pipeline = PassSet(); + m_pipeline.addPass(passManager->analyzeWeightableLayers()); + } + PassSet m_pipeline; +}; + +void VpuScaleTest::SetUp() { + ASSERT_NO_FATAL_FAILURE(GraphTransformerTest::SetUp()); + config.set(InferenceEngine::MYRIAD_SCALES_PATTERN, configValue); + ASSERT_NO_FATAL_FAILURE(InitCompileEnv()); + ASSERT_NO_FATAL_FAILURE(InitPipeline()); + ASSERT_NO_FATAL_FAILURE(InitModel()); +} + +TEST_F(VpuScaleTest, IsScaleWorkCorrectly) { + #ifdef IE_GCC_4_8 + GTEST_SKIP(); + #endif + configValue = "conv1:0.2; conv2:1.4"; + SetUp(); + ASSERT_NO_THROW(Compile()); + for (const auto& stage : m_testModel->getStages()) { + auto scale = stage->attrs().getOrDefault("scaleFactor"); + if (stage->name() == "conv1") { + ASSERT_FLOAT_EQ(scale, 0.2); + continue; + } + if (stage->name() == "conv2") { + ASSERT_FLOAT_EQ(scale, 1.4); + } + } +} + +TEST_F(VpuScaleTest, IsRegexInScaleWorksCorrectly) { + #ifdef IE_GCC_4_8 + GTEST_SKIP(); + #endif + configValue = "conv1:0.2"; + SetUp(); + ASSERT_NO_THROW(Compile()); + for (const auto& stage : m_testModel->getStages()) { + auto scale = stage->attrs().getOrDefault("scaleFactor"); + if (stage->name() == "conv1") { + ASSERT_FLOAT_EQ(scale, 0.2); + continue; + } + } +} +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests_deprecated/behavior/shared_tests/CMakeLists.txt b/inference-engine/tests_deprecated/behavior/shared_tests/CMakeLists.txt index e48b259815533c..b66da71d4bdab8 100644 --- a/inference-engine/tests_deprecated/behavior/shared_tests/CMakeLists.txt +++ b/inference-engine/tests_deprecated/behavior/shared_tests/CMakeLists.txt @@ -18,6 +18,7 @@ target_include_directories(${TARGET_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/pl target_link_libraries(${TARGET_NAME} PUBLIC funcTestUtils + inference_engine_legacy ieTestHelpers ) diff --git a/inference-engine/tests_deprecated/behavior/vpu/CMakeLists.txt b/inference-engine/tests_deprecated/behavior/vpu/CMakeLists.txt index a2956a887dd220..72c1b13436bdf6 100644 --- a/inference-engine/tests_deprecated/behavior/vpu/CMakeLists.txt +++ b/inference-engine/tests_deprecated/behavior/vpu/CMakeLists.txt @@ -57,7 +57,7 @@ function(enable_vpu TARGET_NAME FLAG_NAME PLUGIN_NAME) target_include_directories(${TARGET_NAME} PRIVATE $ ${CMAKE_CURRENT_SOURCE_DIR}/myriad_tests - ${IE_MAIN_SOURCE_DIR}/src/inference_engine/src + $/src ${XLINK_INCLUDE} ${XLINK_PLATFORM_INCLUDE}) target_link_libraries(${TARGET_NAME} PRIVATE mvnc) diff --git a/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt b/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt index fcda30314227c1..d8a66f328305a9 100644 --- a/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/gna/CMakeLists.txt @@ -20,8 +20,7 @@ if(ENABLE_HETERO) endif() if(ENABLE_MKL_DNN) - list(APPEND DEPENDENCIES - MKLDNNPlugin) + list(APPEND DEPENDENCIES MKLDNNPlugin) endif() add_executable(${TARGET_NAME} ${TEST_SRC} ${TEST_INCLUDE}) diff --git a/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt b/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt index 50f53518083b50..c6fa691c53d3ae 100644 --- a/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt +++ b/inference-engine/tests_deprecated/functional/vpu/CMakeLists.txt @@ -75,3 +75,7 @@ addIeTargetTest( VPU MYRIAD ) +# because vpu_graph_transformer is compiled with LTO +if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.0) + set_target_properties(VPUCommonTests PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) +endif() diff --git a/inference-engine/tests_deprecated/functional/vpu/graph_transformer/gt_functional_tests.cpp b/inference-engine/tests_deprecated/functional/vpu/graph_transformer/gt_functional_tests.cpp index b6b82f72eb25fa..84029dcd48868e 100644 --- a/inference-engine/tests_deprecated/functional/vpu/graph_transformer/gt_functional_tests.cpp +++ b/inference-engine/tests_deprecated/functional/vpu/graph_transformer/gt_functional_tests.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -108,7 +108,7 @@ void graphTransformerFunctionalTests::PrepareGraphCompilation() { _configuration.registerOption(); _configuration.registerOption(); _configuration.registerOption(); - _configuration.registerOption(); + _configuration.registerOption(); _configuration.registerOption(); _configuration.registerOption(); _configuration.registerOption(); diff --git a/inference-engine/tests_deprecated/unit/CMakeLists.txt b/inference-engine/tests_deprecated/unit/CMakeLists.txt index 5f109be495a110..415563ed2d8568 100644 --- a/inference-engine/tests_deprecated/unit/CMakeLists.txt +++ b/inference-engine/tests_deprecated/unit/CMakeLists.txt @@ -18,7 +18,8 @@ file(GLOB inference_engine_tests/*.cpp ) -if (ENABLE_GNA) +# TODO: fix CVS-71010 and remove BUILD_SHARED_LIBS +if (ENABLE_GNA AND BUILD_SHARED_LIBS) file(GLOB GNA_TESTS engines/gna/*cpp @@ -82,7 +83,7 @@ if (ENABLE_MYRIAD) ) include_directories( engines/vpu/myriad_tests/helpers - ${IE_MAIN_SOURCE_DIR}/src/vpu/myriad_plugin + $ ${XLINK_INCLUDE} ${XLINK_PLATFORM_INCLUDE}) @@ -142,4 +143,11 @@ install(TARGETS ${TARGET_NAME} COMPONENT tests EXCLUDE_FROM_ALL) +if(TARGET libGNAStubs) + install(TARGETS libGNAStubs + RUNTIME DESTINATION tests + COMPONENT tests + EXCLUDE_FROM_ALL) +endif() + add_dependencies(${TARGET_NAME} mock_engine) diff --git a/inference-engine/tests_deprecated/unit/engines/gna/fp32_non_quantized_tests.cpp b/inference-engine/tests_deprecated/unit/engines/gna/fp32_non_quantized_tests.cpp index 3570511851511d..8166d0be1e5802 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/fp32_non_quantized_tests.cpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/fp32_non_quantized_tests.cpp @@ -41,22 +41,6 @@ static std::string getTestName(testing::TestParamInfo obj) { return "channels_" + std::to_string(obj.param.nChannels) + "_" + (obj.param.eltwise_type == FP32TestParams::eSumm ? "summ" : "mull"); } - -TEST_P(GNAFP32ParametricTest, SplitFollowedByEltwiseMulOnAllignedCPU) { - auto c = GetParam().nChannels; - auto isMull = GetParam().eltwise_type == FP32TestParams::eMul; - std::vector input_data1(c, 3.0); - std::vector input_data2(c, 2.0); - std::vector input_data; - input_data.insert(input_data.end(), input_data1.begin(), input_data1.end()); - input_data.insert(input_data.end(), input_data2.begin(), input_data2.end()); - - std::vector expected_result(c, isMull ? 6.0 : 5.0); - assert_that().onInferModel(EltwiseAfterSplitModel(c, isMull)) - .inNotCompactMode().gna().propagate_forward().onCPU() - .called_with().input("input_1", input_data).equals_to(expected_result); -} - FP32TestParams gna_fp32_test_params[] = { {7, FP32TestParams::eMul}, {7, FP32TestParams::eSumm}, @@ -106,49 +90,6 @@ TEST_F(FP32NonQuantizedTest, SliceFollowedBy2FCsAnd2EltwisesOnCPU) { .called_with_input_and_expected_output(input_data, expected_result); } -TEST_F(FP32NonQuantizedTest, SplitAfterFCFollowedByFCAndEltwiseOnCPU) { - std::vector input_data = {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, 1.0, 1.0, 1.0, 1.0}; - std::vector expected_result = {232.0, 232.0, 232.0, 232.0, 232.0, - 232.0, 232.0, 232.0, 232.0, 232.0}; - assert_that().onInferModel(FCBeforeSplitModel()) - .inNotCompactMode().gna().propagate_forward().onCPU() - .called_with_input_and_expected_output(input_data, expected_result); -} - - -TEST_F(FP32NonQuantizedTest, ConcatPropagateForwardWithSuccessOnCPU) { - std::vector input_data = {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, 1.0, 1.0, 1.0, 1.0}; - std::vector expected_result = {121.0, 121.0, 121.0, 121.0, 121.0, - 121.0, 121.0, 121.0, 121.0, 121.0, - 121.0, 121.0, 121.0, 121.0, 121.0, - 121.0, 121.0, 121.0, 121.0, 121.0}; - - assert_that().onInferModel(concatModel()) - .inNotCompactMode().gna().propagate_forward().onCPU() - .called_with_input_and_expected_output(input_data, expected_result); -} - -TEST_F(FP32NonQuantizedTest, DoubleConcatPropagateForwardWithSuccessOnCPU) { - std::vector input_data = {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, 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, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - std::vector expected_result = {141.0, 141.0, 141.0, 141.0, 141.0, - 141.0, 141.0, 141.0, 141.0, 141.0, - 141.0, 141.0, 141.0, 141.0, 141.0, - 141.0, 141.0, 141.0, 141.0, 141.0, - 141.0, 141.0, 141.0, 141.0, 141.0, - 141.0, 141.0, 141.0, 141.0, 141.0, - 141.0, 141.0, 141.0, 141.0, 141.0, - 141.0, 141.0, 141.0, 141.0, 141.0}; - - assert_that().onInferModel(doubleConcatModel()) - .inNotCompactMode().gna().propagate_forward().onCPU() - .called_with_input_and_expected_output(input_data, expected_result); -} - TEST_F(FP32NonQuantizedTest, multiple_inputs_correct_results) { std::vector input_data = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; std::vector input2_data = {2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0}; @@ -301,19 +242,6 @@ TEST_F(FP32NonQuantizedTest, ScaleShiftWithBroadcastSupported) { .called_with_input_and_expected_output(input_data, expected_result); } -TEST_F(FP32NonQuantizedTest, ConcatWithConstInputPropagatedForward) { - std::vector input_data = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - - std::vector expected_result = {121.0, 121.0, 121.0, 121.0, 121.0, - 121.0, 121.0, 121.0, 121.0, 121.0, - 121.0, 121.0, 121.0, 121.0, 121.0, - 121.0, 121.0, 121.0, 121.0, 121.0}; - - assert_that().onInferModel(concatModelWithConstLayer()) - .inNotCompactMode().gna().propagate_forward().onCPU() - .called_with_input(input_data).equals_to(expected_result); -} - TEST_F(FP32NonQuantizedTest, InputSplitConcatPropagateForward) { std::vector input_data(64, 1.0f); std::vector expected_result(10, 64.f); @@ -411,33 +339,6 @@ TEST_F(FP32NonQuantizedTest, TI2PropagateForward) { .called_with_input(input_data).equals_to(expected_result1).equals_to(expected_result2); } -TEST_F(FP32NonQuantizedTest, EltwiseWithConstInputPropagatedForward) { - std::vector input_data = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - std::vector expected_result = {2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0}; - - assert_that().onInferModel(eltwiseSumModelWithConstLayer()) - .inNotCompactMode().gna().propagate_forward().onCPU() - .called_with_input(input_data).equals_to(expected_result); -} - -TEST_F(FP32NonQuantizedTest, EltwiseWithConstInputReorderPropagatedForward) { - std::vector input_data = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; - std::vector expected_result = {2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0}; - - assert_that().onInferModel(eltwiseSumModelWithConstLayer2()) - .inNotCompactMode().gna().propagate_forward().onCPU() - .called_with_input(input_data).equals_to(expected_result); -} - -TEST_F(FP32NonQuantizedTest, EltwiseMulWithConstInputReorderPropagatedForward) { - std::vector input_data = {3.0, 1.0, 3.0, 1.0, 3.0, 1.0, 3.0, 1.0, 3.0, 1.0}; - std::vector expected_result = {6.0, 2.0, 6.0, 2.0, 6.0, 2.0, 6.0, 2.0, 6.0, 2.0}; - - assert_that().onInferModel(eltwiseMulModelWithConstLayer()) - .inNotCompactMode().withWeigthsPattern({2}).gna().propagate_forward().onCPU() - .called_with_input(input_data).equals_to(expected_result); -} - TEST_F(FP32NonQuantizedTest, PowerWithScaleFactorPropagateForward) { std::vector input_data(10, 2.f); std::vector expected_result(12, 21.f); @@ -723,4 +624,3 @@ TEST_F(FP32NonQuantizedTest, ReshapeConvolutionLessThan48Filters) { .called_with_input(input_data) .equals_to(expected_result); } - diff --git a/inference-engine/tests_deprecated/unit/engines/gna/gna_matcher.cpp b/inference-engine/tests_deprecated/unit/engines/gna/gna_matcher.cpp index c0a5719783dda6..15cf4951c586a0 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/gna_matcher.cpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/gna_matcher.cpp @@ -798,30 +798,6 @@ void GNAQueryStateMatcher :: match() { EXPECT_CALL(mockApi, Gna2InstrumentationConfigAssignToRequestConfig(_,_)).Times(AtLeast(1)).WillRepeatedly(Return(Gna2StatusSuccess)); #endif - IE_SUPPRESS_DEPRECATED_START - try { - loadNetwork(); - if (GnaPluginTestEnvironment::kAnyNotNull == _env.numberOfStates) { - auto states = executer->QueryState(); - ASSERT_NE(states.size(), 0); - // usually states are callable - for (auto & state : states) { - state->Reset(); - } - } else if (_env.numberOfStates >= 0) { - ASSERT_EQ(executer->QueryState().size(), _env.numberOfStates); - } else { - FAIL() << "number of memory states expectation not set"; - } - - } - catch(std::exception &ex) { - FAIL() << ex.what(); - } - catch(...) { - FAIL() << "unknown exception thrown"; - } - IE_SUPPRESS_DEPRECATED_END } diff --git a/inference-engine/tests_deprecated/unit/engines/gna/gna_query_state_tests.cpp b/inference-engine/tests_deprecated/unit/engines/gna/gna_query_state_tests.cpp deleted file mode 100644 index 7ead4aa815336d..00000000000000 --- a/inference-engine/tests_deprecated/unit/engines/gna/gna_query_state_tests.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include "gna_matcher.hpp" - -class QueryStateTest : public GNATest<> { - protected: - void SetUp() override { - } -}; -using namespace GNATestIRs; - -// Recursive Algorithm -// Precision Threshold - -TEST_F(QueryStateTest, returnEmptyCollectionOfStatesIfNoMemoryInIR) { - assert_that().afterLoadingModel(TanhActivationModel()).withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f).queryState().isEmpty(); -} - -TEST_F(QueryStateTest, returnNonEmptyCollectionOfStatesForMemoryIR) { - assert_that().afterLoadingModel(affineToMemoryModel()).withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f).queryState().isNotEmpty(); -} diff --git a/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp b/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp index 36c201d60f9eae..b8f32671fe943d 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/i16_quantisation_test.cpp @@ -218,12 +218,6 @@ TEST_F(I16QuantisationTest, canDetectLeakyRelu) { .gna().propagate_forward().called_with().pwl_inserted_into_nnet(); } -TEST_F(I16QuantisationTest, canDetectSoftWSignSubgraph) { - assert_that().onInferModel(TFSoftsignUnfoldedModel()) - .inNotCompactMode().withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f) - .gna().propagate_forward().called_with().pwls_inserted_into_nnet({kActSigmoid}); -} - TEST_F(I16QuantisationTest, MaxPool_followedAfterActivation) { assert_that().onInferModel(maxpoolAfterRelu()) .inNotCompactMode().withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f) diff --git a/inference-engine/tests_deprecated/unit/engines/gna/layers/activation_test.cpp b/inference-engine/tests_deprecated/unit/engines/gna/layers/activation_test.cpp deleted file mode 100644 index 0d768f823a1c1c..00000000000000 --- a/inference-engine/tests_deprecated/unit/engines/gna/layers/activation_test.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../gna_matcher.hpp" - -typedef struct { - std::string activationType; - size_t input_shape; - std::pair range; -} ActivationCaseParam; - -using ActivationCaseParam2 = std::tuple; - -class GNAActivationTest : public GNATest<>, - public testing::WithParamInterface { - public: - - static std::string getTestName(const testing::TestParamInfo& params) { - std::string test_name = std::string(std::get<0>(params.param).name()) + "_"; - test_name += std::get<1>(params.param).activationType + "_"; - test_name += std::to_string(std::get<1>(params.param).input_shape) + "_"; - test_name += std::to_string(std::get<1>(params.param).range.first) + "_"; - test_name += std::to_string(std::get<1>(params.param).range.second); - return test_name; - } - - std::shared_ptr buildNgraphFunction(const ActivationCaseParam& param) { - - auto shape = ngraph::Shape{1, param.input_shape}; - auto inputN = std::make_shared(ngraph::element::f32, shape); - - auto absN = std::make_shared(inputN); - - auto powerN = std::make_shared(absN, -1, 1, 1.0); - - auto eltwiseN = std::make_shared(powerN, inputN); - - auto function = std::make_shared(ngraph::NodeVector{eltwiseN}, ngraph::ParameterVector{inputN}); - return function; - } -}; - -TEST_P(GNAActivationTest, ActivationTest) { - const auto precision = std::get<0>(GetParam()); - const auto param = std::get<1>(GetParam()); - - if (precision == InferenceEngine::Precision::FP32) { - auto input_data = generate_random_1d(param.input_shape, param.range.first, param.range.second); - std::vector expected_result(param.input_shape); - - - for (std::size_t i = 0; i < expected_result.size(); i++) { - auto & x = input_data[i]; - if (param.activationType == "softsign") { - expected_result[i] = x / (1 + fabs(x)); - } else { - FAIL() << "Unsupported activation type: " << param.activationType; - } - } - - assert_that().onInferNgraphModel(buildNgraphFunction(param)) - .inNotCompactMode() - .gna() - .propagate_forward() - .onCPU() - .called_with_input(input_data) - .equals_to(expected_result); - } else { - assert_that().onInferNgraphModel(buildNgraphFunction(param)) - .inNotCompactMode() - .gna() - .withGNAConfig(GNA_CONFIG_KEY(SCALE_FACTOR), 1.0f) - .withGNAConfig(GNA_CONFIG_KEY(PRECISION), precision.name()) - .propagate_forward() - .called_with().pwls_inserted_into_nnet({kActSigmoid}); - } -} - -static const ActivationCaseParam gna_activation_test_params[] = { - {"softsign", 200, {-10, 10}}, -}; - -INSTANTIATE_TEST_SUITE_P( - GNALayerTests, GNAActivationTest, - ::testing::Combine( - ::testing::Values(InferenceEngine::Precision::FP32, InferenceEngine::Precision::I16, InferenceEngine::Precision::I8), - ::testing::ValuesIn(gna_activation_test_params)), - GNAActivationTest::getTestName); diff --git a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp index bd41ec0118b4c6..8d20b04311f794 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.cpp @@ -2164,146 +2164,6 @@ std::string TFLeakyReluModel() { )V0G0N"; } -std::string TFSoftsignUnfoldedModel() { - return R"V0G0N( - - - - - - - 1 - 64 - - - - - - - 1 - - - - - - - - - - 1 - 64 - - - 1 - - - - - 1 - 1 - 64 - - - - - - - 1 - 1 - 64 - - - - - 1 - 1 - 64 - - - - - - - - 1 - 1 - 64 - - - - - 1 - 1 - 64 - - - - - - - - 1 - 1 - 64 - - - 1 - 1 - 64 - - - - - 1 - 1 - 64 - - - - - - - 1 - - - - - - - - - - 1 - 1 - 64 - - - 1 - - - - - 1 - 64 - - - - - - - - - - - - - - - - - )V0G0N"; -} - std::string maxpoolAfterRelu() { return R"V0G0N( diff --git a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp index 929cc644fc4198..745c4dd426200b 100644 --- a/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp +++ b/inference-engine/tests_deprecated/unit/engines/gna/test_irs.hpp @@ -39,7 +39,6 @@ std::string ClampActivationModel(); std::string IdentityActivationModel(); std::string maxpoolAfterRelu(); std::string TFLeakyReluModel(); -std::string TFSoftsignUnfoldedModel(); std::string cropWithoutOffsetModel(); std::string cropWithAlignedOffsetModel(); std::string cropWithOffsetModel(); diff --git a/inference-engine/tests_deprecated/unit/engines/vpu/get_vpu_scale_from_ir_tests.cpp b/inference-engine/tests_deprecated/unit/engines/vpu/get_vpu_scale_from_ir_tests.cpp deleted file mode 100644 index 66f8493b563f47..00000000000000 --- a/inference-engine/tests_deprecated/unit/engines/vpu/get_vpu_scale_from_ir_tests.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "graph_transformer_tests.hpp" -#include "tests_vpu_common.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace vpu; -using namespace InferenceEngine; - -using VPU_AddVpuScaleTest = GraphTransformerTest; - -TEST_F(VPU_AddVpuScaleTest, CanAddVpuScaleToNetwork) { - InitCompileEnv(); - - auto& env = CompileEnv::get(); - auto config = createConfiguration(); - config.set(InferenceEngine::MYRIAD_IR_WITH_SCALES_DIRECTORY, "/"); - env.updateConfig(config); - - std::shared_ptr function; - - { - auto input = std::make_shared(ngraph::element::f16, ngraph::Shape{4, 2, 2}); - input->set_friendly_name("input"); - auto weights = ngraph::opset1::Constant::create(ngraph::element::f16, ngraph::Shape{2, 2}, {1}); - auto bias = ngraph::opset1::Constant::create(ngraph::element::f16, ngraph::Shape{2}, {1}); - auto fc = std::make_shared(input, weights, bias, ngraph::Shape{4, 2, 2}); - fc->set_friendly_name("FullyConnected"); - auto result = std::make_shared(fc); - ngraph::ResultVector results { result }; - ngraph::ParameterVector params {input }; - function = std::make_shared(results, params); - } - - auto network = InferenceEngine::CNNNetwork(function); - auto model = frontEnd->buildInitialModel(network); - - const auto getFullyConnectedStage = [model]() -> Stage { - const auto isFullyConnected = [](const Stage& stage) { - const auto& layer = stage->origLayer(); - return layer && layer->type == "FullyConnected"; - }; - const auto stages = model->getStages(); - const auto stageIt = std::find_if(begin(stages), end(stages), isFullyConnected); - return *stageIt; - }; - - const auto fcStage = getFullyConnectedStage(); - EXPECT_EQ(fcStage->origLayer()->params.find("vpu_scale"), fcStage->origLayer()->params.end()); - - auto middleEnd = passManager->buildMiddleEnd(); - middleEnd->run(model); - - const auto fcStageAfterMiddleEnd = getFullyConnectedStage(); - EXPECT_NE(fcStageAfterMiddleEnd->origLayer()->params.find("vpu_scale"), fcStageAfterMiddleEnd->origLayer()->params.end()); -} - -TEST_F(VPU_AddVpuScaleTest, VpuScaleFromIrChangesWeights) { - InitCompileEnv(); - const auto& env = CompileEnv::get(); - auto config = createConfiguration(); - config.set(InferenceEngine::MYRIAD_IR_WITH_SCALES_DIRECTORY, "/"); - env.updateConfig(config); - - std::shared_ptr function; - { - ngraph::element::Type elementType = ngraph::element::Type_t::f16; - ngraph::Shape shape { 1, 1, 4, 5 }; - auto input = std::make_shared(elementType, shape); - input->set_friendly_name("input"); - - auto weights = std::make_shared( - elementType, ngraph::Shape{1, 1, 1, 1}, std::vector(1, 1.0f)); - auto conv = std::make_shared( - input, weights, ngraph::Strides {1, 1}, - ngraph::CoordinateDiff{0, 0}, ngraph::CoordinateDiff{0, 0}, ngraph::Strides{1, 1}); - conv->set_friendly_name("Convolution"); - auto result = std::make_shared(conv); - - ngraph::ResultVector results { result }; - ngraph::ParameterVector params { input }; - function = std::make_shared(results, params); - } - - auto network = InferenceEngine::CNNNetwork(function); - auto model = frontEnd->buildInitialModel(network); - - auto middleEnd = passManager->buildMiddleEnd(); - auto checkWeightWasChanged = [this, &network](const float scale) { - auto model = frontEnd->buildInitialModel(network); - for (const auto& stage : model->getStages()) { - if (stage->name() == "Convolution") { - stage->origLayer()->params["vpu_scale"] = toString(scale); - } - } - - auto middleEnd = passManager->buildMiddleEnd(); - middleEnd->run(model); - for (const auto& stage : model->getStages()) { - if (stage->name() == "Convolution") { - auto content = stage->input(1)->content()->get(); - if (scale < 0) { - EXPECT_EQ(scale, PrecisionUtils::f16tof32(content[0])); - } else { - EXPECT_EQ(scale, fabs(PrecisionUtils::f16tof32(content[0]))); - } - } - } - }; - - const auto maxVal = std::numeric_limits::infinity(); - - checkWeightWasChanged(32); - checkWeightWasChanged(64); - checkWeightWasChanged(maxVal); - -} diff --git a/inference-engine/tests_deprecated/unit/engines/vpu/graph_transformer_tests.cpp b/inference-engine/tests_deprecated/unit/engines/vpu/graph_transformer_tests.cpp index a75d0ba76217a7..4e46ccbb1b5b8d 100644 --- a/inference-engine/tests_deprecated/unit/engines/vpu/graph_transformer_tests.cpp +++ b/inference-engine/tests_deprecated/unit/engines/vpu/graph_transformer_tests.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -226,7 +226,7 @@ PluginConfiguration createConfiguration() { configuration.registerOption(); configuration.registerOption(); configuration.registerOption(); - configuration.registerOption(); + configuration.registerOption(); configuration.registerOption(); configuration.registerOption(); configuration.registerOption(); diff --git a/inference-engine/thirdparty/CMakeLists.txt b/inference-engine/thirdparty/CMakeLists.txt index 4aea987153459d..10d9e495254c97 100644 --- a/inference-engine/thirdparty/CMakeLists.txt +++ b/inference-engine/thirdparty/CMakeLists.txt @@ -24,9 +24,12 @@ if (ENABLE_CLDNN) set(CLDNN__INCLUDE_TESTS OFF CACHE BOOL "" FORCE) endif() add_subdirectory(clDNN) + ov_install_static_lib(clDNN_lib gpu) endif() function(ie_add_mkldnn) + set(DNNL_ENABLE_JIT_PROFILING ${BUILD_SHARED_LIBS} CACHE BOOL "" FORCE) + set(DNNL_ENABLE_ITT_TASKS ${BUILD_SHARED_LIBS} CACHE BOOL "" FORCE) set(DNNL_ENABLE_CONCURRENT_EXEC ON CACHE BOOL "" FORCE) set(DNNL_ENABLE_PRIMITIVE_CACHE OFF CACHE BOOL "" FORCE) ## TODO: try it later set(DNNL_ENABLE_MAX_CPU_ISA OFF CACHE BOOL "" FORCE) ## TODO: try it later @@ -53,6 +56,7 @@ function(ie_add_mkldnn) add_subdirectory(mkl-dnn EXCLUDE_FROM_ALL) add_library(mkldnn ALIAS dnnl) + ov_install_static_lib(dnnl cpu) endfunction() if(ENABLE_MKL_DNN) diff --git a/inference-engine/thirdparty/clDNN/CMakeLists.txt b/inference-engine/thirdparty/clDNN/CMakeLists.txt index 37b824c0698d95..18270b771a5fcb 100644 --- a/inference-engine/thirdparty/clDNN/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/CMakeLists.txt @@ -12,14 +12,6 @@ project("${CLDNN__PROJ_NAME}") # ====================================== HELPER CONSTANT VARIABLES ===================================== # ====================================================================================================== # ====================================================================================================== -if (ENABLE_ONEDNN_FOR_GPU) - ExternalProject_Get_property(onednn_gpu_build SOURCE_DIR) - ExternalProject_Get_property(onednn_gpu_build BINARY_DIR) - - set(ONEDNN_TARGET_NAME onednn_gpu) - set(ONEDNN_INCLUDE_DIRS "${BINARY_DIR}/include/" "${SOURCE_DIR}/include/") - set(ONEDNN_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_STATIC_LIBRARY_PREFIX}onednn_gpu${CMAKE_STATIC_LIBRARY_SUFFIX}") -endif() if(ENABLE_GPU_DEBUG_CAPS) add_definitions(-DGPU_DEBUG_CONFIG=1) diff --git a/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device.hpp b/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device.hpp index 7f5e1f13d7d1e7..d552b74ce61dd3 100644 --- a/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device.hpp +++ b/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device.hpp @@ -18,6 +18,8 @@ struct device { virtual device_info get_info() const = 0; virtual memory_capabilities get_mem_caps() const = 0; + virtual bool is_same(const device::ptr other) = 0; + virtual ~device() = default; }; diff --git a/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device_query.hpp b/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device_query.hpp index 4ff170b5ae242c..fc3df799a3cf92 100644 --- a/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device_query.hpp +++ b/inference-engine/thirdparty/clDNN/api/cldnn/runtime/device_query.hpp @@ -20,6 +20,7 @@ struct device_query { runtime_types runtime_type, void* user_context = nullptr, void* user_device = nullptr, + int ctx_device_id = 0, int target_tile_id = -1); std::map get_available_devices() const { diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/CMakeLists.txt b/inference-engine/thirdparty/clDNN/kernel_selector/CMakeLists.txt index 6c47bcec69d0a5..eeebbe2d9c7b02 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/kernel_selector/CMakeLists.txt @@ -168,5 +168,6 @@ add_custom_command( TARGET "${CLDNN_BUILD__PROJ}" POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${__CLDNN_Directory__core}/cache/cache.json ${CLDNN_CACHE_PATH}/cache.json) +ov_install_static_lib("${CLDNN_BUILD__PROJ}" gpu) # ====================================================================================================== diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/border/border_kernel_ref.cpp b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/border/border_kernel_ref.cpp index 2bed9a76962a74..bed25eb288a72b 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/border/border_kernel_ref.cpp +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/actual_kernels/border/border_kernel_ref.cpp @@ -23,12 +23,16 @@ ParamsKey BorderKernelRef::GetSupportedKey() const { k.EnableInputLayout(DataLayout::byxf); k.EnableInputLayout(DataLayout::bfzyx); k.EnableInputLayout(DataLayout::bfwzyx); + k.EnableInputLayout(DataLayout::b_fs_yx_fsv16); + k.EnableInputLayout(DataLayout::b_fs_zyx_fsv16); k.EnableOutputLayout(DataLayout::bfyx); k.EnableOutputLayout(DataLayout::yxfb); k.EnableOutputLayout(DataLayout::byxf); k.EnableOutputLayout(DataLayout::bfzyx); k.EnableOutputLayout(DataLayout::bfwzyx); + k.EnableOutputLayout(DataLayout::b_fs_yx_fsv16); + k.EnableOutputLayout(DataLayout::b_fs_zyx_fsv16); k.EnableTensorOffset(); k.EnableTensorPitches(); diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/border_gpu_ref.cl b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/border_gpu_ref.cl index 38234b49b5fbd4..3bc1f018f1fb41 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/border_gpu_ref.cl +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/border_gpu_ref.cl @@ -5,10 +5,35 @@ #include "include/batch_headers/data_types.cl" #include "include/batch_headers/fetch_data.cl" +inline uint FUNC(get_input_index)(uint b, uint f, uint w, uint z, uint y, uint x) +{ +#if INPUT0_DIMS < 5 + return INPUT0_GET_INDEX(b, f, y, x); +#elif INPUT0_DIMS == 5 + return INPUT0_GET_INDEX(b, f, z, y, x); +#elif INPUT0_DIMS == 6 + return INPUT0_GET_INDEX(b, f, w, z, y, x); +#else +#error [clDNN border_gpu_ref.cl]: input format - not supported +#endif +} + +inline uint FUNC(get_output_index)(uint b, uint f, uint w, uint z, uint y, uint x) +{ +#if OUTPUT_DIMS < 5 + return OUTPUT_GET_INDEX(b, f, y, x); +#elif OUTPUT_DIMS == 5 + return OUTPUT_GET_INDEX(b, f, z, y, x); +#elif OUTPUT_DIMS == 6 + return OUTPUT_GET_INDEX(b, f, w, z, y, x); +#else +#error [clDNN border_gpu_ref.cl]: output format - not supported +#endif +} KERNEL(border_gpu_ref)( - const __global UNIT_TYPE* input, - __global UNIT_TYPE* output) + const __global INPUT0_TYPE* input, + __global OUTPUT_TYPE* output) { // [CONSTEXPR] // Border sizes (left-top set and right-bottom set): @@ -72,7 +97,7 @@ KERNEL(border_gpu_ref)( const uint out_w = out_yw / OUTPUT_SIZE_Y; #ifdef BORDER_TYPE_CONSTANT - UNIT_TYPE in_val = TO_UNIT_TYPE(BORDER_VALUE); + INPUT0_TYPE in_val = TO_INPUT0_TYPE(BORDER_VALUE); if (out_x >= blt_sx & out_x < in_lx & out_y >= blt_sy & out_y < in_ly & @@ -88,7 +113,7 @@ KERNEL(border_gpu_ref)( const uint in_f = out_f - blt_sf; const uint in_b = out_b - blt_sb; - const uint in_pos = GET_DATA_INDEX_6D(INPUT0, in_b, in_f, in_w, in_z, in_y, in_x); + const uint in_pos = FUNC_CALL(get_input_index)(in_b, in_f, in_w, in_z, in_y, in_x); in_val = input[in_pos]; } #elif defined BORDER_TYPE_EDGE @@ -99,8 +124,8 @@ KERNEL(border_gpu_ref)( const uint in_f = (out_f >= blt_sf & out_f < in_lf) ? out_f - blt_sf : (out_f < blt_sf ? 0 : in_sf - 1); const uint in_b = (out_b >= blt_sb & out_b < in_lb) ? out_b - blt_sb : (out_b < blt_sb ? 0 : in_sb - 1); - const uint in_pos = GET_DATA_INDEX_6D(INPUT0, in_b, in_f, in_w, in_z, in_y, in_x); - UNIT_TYPE in_val = input[in_pos]; + const uint in_pos = FUNC_CALL(get_input_index)(in_b, in_f, in_w, in_z, in_y, in_x); + INPUT0_TYPE in_val = input[in_pos]; #elif defined BORDER_TYPE_MIRROR const uint in_x = (out_x >= blt_sx & out_x < in_lx) ? out_x - blt_sx : (out_x < blt_sx ? blt_sx - 1 - out_x : in_sx + in_lx - 1 - out_x); const uint in_y = (out_y >= blt_sy & out_y < in_ly) ? out_y - blt_sy : (out_y < blt_sy ? blt_sy - 1 - out_y : in_sy + in_ly - 1 - out_y); @@ -109,8 +134,8 @@ KERNEL(border_gpu_ref)( const uint in_f = (out_f >= blt_sf & out_f < in_lf) ? out_f - blt_sf : (out_f < blt_sf ? blt_sf - 1 - out_f : in_sf + in_lf - 1 - out_f); const uint in_b = (out_b >= blt_sb & out_b < in_lb) ? out_b - blt_sb : (out_b < blt_sb ? blt_sb - 1 - out_b : in_sb + in_lb - 1 - out_b); - const uint in_pos = GET_DATA_INDEX_6D(INPUT0, in_b, in_f, in_w, in_z, in_y, in_x); - UNIT_TYPE in_val = input[in_pos]; + const uint in_pos = FUNC_CALL(get_input_index)(in_b, in_f, in_w, in_z, in_y, in_x); + INPUT0_TYPE in_val = input[in_pos]; #elif defined BORDER_TYPE_MIRROR_101 const uint in_x = (out_x >= blt_sx & out_x < in_lx) ? out_x - blt_sx : (out_x < blt_sx ? blt_sx - out_x : in_sx + in_lx - 2 - out_x); const uint in_y = (out_y >= blt_sy & out_y < in_ly) ? out_y - blt_sy : (out_y < blt_sy ? blt_sy - out_y : in_sy + in_ly - 2 - out_y); @@ -119,12 +144,12 @@ KERNEL(border_gpu_ref)( const uint in_f = (out_f >= blt_sf & out_f < in_lf) ? out_f - blt_sf : (out_f < blt_sf ? blt_sf - out_f : in_sf + in_lf - 2 - out_f); const uint in_b = (out_b >= blt_sb & out_b < in_lb) ? out_b - blt_sb : (out_b < blt_sb ? blt_sb - out_b : in_sb + in_lb - 2 - out_b); - const uint in_pos = GET_DATA_INDEX_6D(INPUT0, in_b, in_f, in_w, in_z, in_y, in_x); - UNIT_TYPE in_val = input[in_pos]; + const uint in_pos = FUNC_CALL(get_input_index)(in_b, in_f, in_w, in_z, in_y, in_x); + INPUT0_TYPE in_val = input[in_pos]; #else #error Unsupported border type. #endif - const uint out_pos = GET_DATA_INDEX_6D(OUTPUT, out_b, out_f, out_w, out_z, out_y, out_x); + const uint out_pos = FUNC_CALL(get_output_index)(out_b, out_f, out_w, out_z, out_y, out_x); output[out_pos] = in_val; } diff --git a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/pooling_gpu_b_fs_zyx_fsv16_imad.cl b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/pooling_gpu_b_fs_zyx_fsv16_imad.cl index 3b55a1a401c72a..ca8342d122507a 100644 --- a/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/pooling_gpu_b_fs_zyx_fsv16_imad.cl +++ b/inference-engine/thirdparty/clDNN/kernel_selector/core/cl_kernels/pooling_gpu_b_fs_zyx_fsv16_imad.cl @@ -126,26 +126,45 @@ KERNEL(pooling_gpu_b_fs_zyx_fsv16)( ACTIVATION_VEC16 pool_result; #if defined AVG_POOLING #if INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE != 0 - __attribute__((opencl_unroll_hint(INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE))) - for (uint i = 0; i < INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE; i++) { + if (last_in_f_group) { + __attribute__((opencl_unroll_hint(INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE))) + for (uint i = 0; i < INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE; i++) { +#if ENABLE_ROUND +#if defined(DYNAMIC_KERNEL_DIVIDER) || defined(DYNAMIC_WITH_PADDING_KERNEL_DIVIDER) + pool_result[i] = convert_int(round(((float)result[i] / max(num_elements, (uint)1)))); #else - __attribute__((opencl_unroll_hint(FEATURE_SLICE_SIZE))) - for (uint i = 0; i < FEATURE_SLICE_SIZE; i++) { + pool_result[i] = convert_int(round((float)result[i] / (int)(POOL_SIZE_X * INPUT0_SIZE_Z * INPUT0_SIZE_Y))); +#endif +#else // ENABLE_ROUND +#if defined(DYNAMIC_KERNEL_DIVIDER) || defined(DYNAMIC_WITH_PADDING_KERNEL_DIVIDER) + pool_result[i] = (float)result[i] / max(num_elements, (uint)1); +#else + pool_result[i] = (float)result[i] / (int)(POOL_SIZE_X * INPUT0_SIZE_Z * INPUT0_SIZE_Y); #endif +#endif // ENABLE_ROUND + } + } else { +#endif + __attribute__((opencl_unroll_hint(FEATURE_SLICE_SIZE))) + for (uint i = 0; i < FEATURE_SLICE_SIZE; i++) { +// INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE != 0 #if ENABLE_ROUND #if defined(DYNAMIC_KERNEL_DIVIDER) || defined(DYNAMIC_WITH_PADDING_KERNEL_DIVIDER) - pool_result[i] = convert_int(round(((float)result[i] / max(num_elements, (uint)1)))); + pool_result[i] = convert_int(round(((float)result[i] / max(num_elements, (uint)1)))); #else - pool_result[i] = convert_int(round((float)result[i] / (int)(POOL_SIZE_X * INPUT0_SIZE_Z * INPUT0_SIZE_Y))); + pool_result[i] = convert_int(round((float)result[i] / (int)(POOL_SIZE_X * INPUT0_SIZE_Z * INPUT0_SIZE_Y))); #endif #else // ENABLE_ROUND #if defined(DYNAMIC_KERNEL_DIVIDER) || defined(DYNAMIC_WITH_PADDING_KERNEL_DIVIDER) - pool_result[i] = (float)result[i] / max(num_elements, (uint)1); + pool_result[i] = (float)result[i] / max(num_elements, (uint)1); #else - pool_result[i] = (float)result[i] / (int)(POOL_SIZE_X * INPUT0_SIZE_Z * INPUT0_SIZE_Y); + pool_result[i] = (float)result[i] / (int)(POOL_SIZE_X * INPUT0_SIZE_Z * INPUT0_SIZE_Y); #endif #endif // ENABLE_ROUND + } +#if INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE != 0 } +#endif // INPUT0_FEATURE_NUM % FEATURE_SLICE_SIZE != 0 #else // AVG_POOLING pool_result = TO_ACTIVATION_VEC16(result); #endif // AVG_POOLING diff --git a/inference-engine/thirdparty/clDNN/runtime/CMakeLists.txt b/inference-engine/thirdparty/clDNN/runtime/CMakeLists.txt index 0367cf831ddedb..d4d6b319dcddfb 100644 --- a/inference-engine/thirdparty/clDNN/runtime/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/runtime/CMakeLists.txt @@ -67,10 +67,7 @@ target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE ) if(ENABLE_ONEDNN_FOR_GPU) - add_dependencies("${CLDNN_BUILD__PROJ}" onednn_gpu_build) - target_link_libraries("${CLDNN_BUILD__PROJ}" PUBLIC ${ONEDNN_LIBRARY}) - target_include_directories("${CLDNN_BUILD__PROJ}" PUBLIC ${ONEDNN_INCLUDE_DIRS}) - target_compile_definitions("${CLDNN_BUILD__PROJ}" PUBLIC ENABLE_ONEDNN_FOR_GPU) + target_link_libraries("${CLDNN_BUILD__PROJ}" PUBLIC onednn_gpu) endif() if(WIN32) @@ -80,4 +77,7 @@ elseif((NOT ANDROID) AND (UNIX)) endif() target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE inference_engine) + +ov_install_static_lib("${CLDNN_BUILD__PROJ}" gpu) + # ====================================================================================================== diff --git a/inference-engine/thirdparty/clDNN/runtime/device_query.cpp b/inference-engine/thirdparty/clDNN/runtime/device_query.cpp index 6285b36f4cb7b9..07e5cbe1f043c0 100644 --- a/inference-engine/thirdparty/clDNN/runtime/device_query.cpp +++ b/inference-engine/thirdparty/clDNN/runtime/device_query.cpp @@ -10,14 +10,19 @@ namespace cldnn { -device_query::device_query(engine_types engine_type, runtime_types runtime_type, void* user_context, void* user_device, int target_tile_id) { +device_query::device_query(engine_types engine_type, + runtime_types runtime_type, + void* user_context, + void* user_device, + int ctx_device_id, + int target_tile_id) { switch (engine_type) { case engine_types::ocl: { if (runtime_type != runtime_types::ocl) throw std::runtime_error("Unsupported runtime type for ocl engine"); ocl::ocl_device_detector ocl_detector; - _available_devices = ocl_detector.get_available_devices(user_context, user_device, target_tile_id); + _available_devices = ocl_detector.get_available_devices(user_context, user_device, ctx_device_id, target_tile_id); break; } default: throw std::runtime_error("Unsupported engine type in device_query"); diff --git a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.cpp b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.cpp index e864877cc3e69c..4ba20d57dfa2df 100644 --- a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.cpp +++ b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.cpp @@ -300,5 +300,13 @@ ocl_device::ocl_device(const cl::Device dev, const cl::Context& ctx, const cl_pl , _info(init_device_info(dev)) , _mem_caps(init_memory_caps(dev, _info)) { } +bool ocl_device::is_same(const device::ptr other) { + auto casted = downcast(other.get()); + if (!casted) + return false; + + return _context == casted->get_context() && _device == casted->get_device() && _platform == casted->get_platform(); +} + } // namespace ocl } // namespace cldnn diff --git a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.hpp b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.hpp index ecb3498e4886b1..e68a6078490f53 100644 --- a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.hpp +++ b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device.hpp @@ -28,6 +28,8 @@ struct ocl_device : public device { const cl::Context& get_context() const { return _context; } cl_platform_id get_platform() const { return _platform; } + bool is_same(const device::ptr other) override; + ~ocl_device() = default; private: diff --git a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.cpp b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.cpp index c22b831da3be13..5334b1e64335a0 100644 --- a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.cpp +++ b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.cpp @@ -91,11 +91,14 @@ static std::vector getSubDevices(cl::Device& rootDevice) { return subDevices; } -std::map ocl_device_detector::get_available_devices(void* user_context, void* user_device, int target_tile_id) const { +std::map ocl_device_detector::get_available_devices(void* user_context, + void* user_device, + int ctx_device_id, + int target_tile_id) const { bool host_out_of_order = true; // Change to false, if debug requires in-order queue. std::vector dev_orig, dev_sorted; if (user_context != nullptr) { - dev_orig = create_device_list_from_user_context(host_out_of_order, user_context); + dev_orig = create_device_list_from_user_context(host_out_of_order, user_context, ctx_device_id); } else if (user_device != nullptr) { dev_orig = create_device_list_from_user_device(host_out_of_order, user_device); } else { @@ -171,13 +174,14 @@ std::vector ocl_device_detector::create_device_list(bool out_out_or return ret; } -std::vector ocl_device_detector::create_device_list_from_user_context(bool out_out_order, void* user_context) const { +std::vector ocl_device_detector::create_device_list_from_user_context(bool out_out_order, void* user_context, int ctx_device_id) const { cl::Context ctx = cl::Context(static_cast(user_context), true); auto all_devices = ctx.getInfo(); std::vector ret; - for (auto& device : all_devices) { - if (!does_device_match_config(out_out_order, device)) + for (size_t i = 0; i < all_devices.size(); i++) { + auto& device = all_devices[i]; + if (!does_device_match_config(out_out_order, device) || i != ctx_device_id) continue; ret.emplace_back(std::make_shared(device, ctx, device.getInfo())); } diff --git a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.hpp b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.hpp index 9ee7aeea11deda..81cf6d8836c60c 100644 --- a/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.hpp +++ b/inference-engine/thirdparty/clDNN/runtime/ocl/ocl_device_detector.hpp @@ -19,10 +19,11 @@ class ocl_device_detector { public: ocl_device_detector() = default; - std::map get_available_devices(void* user_context, void* user_device, int target_tile_id = -1) const; + std::map get_available_devices(void *user_context, void *user_device, int ctx_device_id = 0, int target_tile_id = -1) const; + private: std::vector create_device_list(bool out_out_order) const; - std::vector create_device_list_from_user_context(bool out_out_order, void* user_context) const; + std::vector create_device_list_from_user_context(bool out_out_order, void* user_context, int ctx_device_id = 0) const; std::vector create_device_list_from_user_device(bool out_out_order, void* user_device) const; }; diff --git a/inference-engine/thirdparty/clDNN/src/CMakeLists.txt b/inference-engine/thirdparty/clDNN/src/CMakeLists.txt index c0b86111581102..df2cde95958f03 100644 --- a/inference-engine/thirdparty/clDNN/src/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/src/CMakeLists.txt @@ -128,9 +128,7 @@ target_link_libraries("${CLDNN_BUILD__PROJ}" PRIVATE ) if(ENABLE_ONEDNN_FOR_GPU) - target_link_libraries("${CLDNN_BUILD__PROJ}" PUBLIC ${ONEDNN_LIBRARY}) - target_include_directories("${CLDNN_BUILD__PROJ}" PUBLIC ${ONEDNN_INCLUDE_DIRS}) - target_compile_definitions("${CLDNN_BUILD__PROJ}" PUBLIC ENABLE_ONEDNN_FOR_GPU) + target_link_libraries("${CLDNN_BUILD__PROJ}" PUBLIC onednn_gpu) endif() if(COMMAND add_cpplint_target) diff --git a/inference-engine/thirdparty/clDNN/src/border.cpp b/inference-engine/thirdparty/clDNN/src/border.cpp index 886275d6719562..478acf99fb8b81 100644 --- a/inference-engine/thirdparty/clDNN/src/border.cpp +++ b/inference-engine/thirdparty/clDNN/src/border.cpp @@ -87,23 +87,12 @@ std::string border_inst::to_string(border_node const& node) { border_inst::typed_primitive_inst(network& network, border_node const& node) : parent(network, node) { auto input_layout = node.input().get_output_layout(); - const auto input_format = input_layout.format; const auto& input_sizes = input_layout.size; auto lt_sizes = argument.left_top_sizes.sub(tensor(0)); auto rb_sizes = argument.right_bottom_sizes.sub(tensor(0)); auto b_type = argument.type; - CLDNN_ERROR_NOT_PROPER_FORMAT(node.id(), - "Input format", - input_format.value, - "supported border primitive input formats", - format::bfyx, - format::yxfb, - format::byxf, - format::bfzyx, - format::bfwzyx); - tensor null_tensor = tensor(0); // Check if sizes of border are in proper range. diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/add_onednn_optimization_attributes.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/add_onednn_optimization_attributes.cpp new file mode 100644 index 00000000000000..bb7b396467ce75 --- /dev/null +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/add_onednn_optimization_attributes.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "pass_manager.h" +#include "program_node.h" + +using namespace cldnn; + +void add_onednn_optimization_attributes::run(program& p) { +#ifdef ENABLE_ONEDNN_FOR_GPU + for (auto& node : p.get_processing_order()) { + if (node->get_preferred_impl_type() == impl_types::onednn) { + node->init_onednn_primitive_attributes(); + } + } +#endif // ENABLE_ONEDNN_FOR_GPU +} diff --git a/inference-engine/thirdparty/clDNN/src/graph_optimizer/basic_memory_dependencies.cpp b/inference-engine/thirdparty/clDNN/src/graph_optimizer/basic_memory_dependencies.cpp index 13b95c7478ad8f..306c16b58e8b21 100644 --- a/inference-engine/thirdparty/clDNN/src/graph_optimizer/basic_memory_dependencies.cpp +++ b/inference-engine/thirdparty/clDNN/src/graph_optimizer/basic_memory_dependencies.cpp @@ -36,7 +36,7 @@ void basic_memory_dependencies::run(program& p) { add_memory_dependency(it, node); } - if (node->is_type()) { + if (node->is_type() && node->get_preferred_impl_type() == impl_types::onednn) { auto& conv = node->as(); bool can_reuse_eltwise_mem = false; size_t eltw_dep = 0; @@ -59,6 +59,7 @@ void basic_memory_dependencies::run(program& p) { } } } + if (can_reuse_eltwise_mem) { auto& eltw_node = conv.get_dependency(eltw_dep); eltw_node.can_share_buffer(false); diff --git a/inference-engine/thirdparty/clDNN/src/impls/ocl/border.cpp b/inference-engine/thirdparty/clDNN/src/impls/ocl/border.cpp index 83ef5ef102e9f0..c95189ea099f9c 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/ocl/border.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/ocl/border.cpp @@ -72,22 +72,36 @@ attach_border_impl::attach_border_impl() { std::make_tuple(data_types::f16, format::yxfb), std::make_tuple(data_types::i8, format::yxfb), std::make_tuple(data_types::u8, format::yxfb), + std::make_tuple(data_types::f32, format::bfyx), std::make_tuple(data_types::f16, format::bfyx), std::make_tuple(data_types::i8, format::bfyx), std::make_tuple(data_types::u8, format::bfyx), + std::make_tuple(data_types::f32, format::byxf), std::make_tuple(data_types::f16, format::byxf), std::make_tuple(data_types::i8, format::byxf), std::make_tuple(data_types::u8, format::byxf), + std::make_tuple(data_types::f32, format::bfzyx), std::make_tuple(data_types::f16, format::bfzyx), std::make_tuple(data_types::i8, format::bfzyx), std::make_tuple(data_types::u8, format::bfzyx), + std::make_tuple(data_types::f32, format::bfwzyx), std::make_tuple(data_types::f16, format::bfwzyx), std::make_tuple(data_types::i8, format::bfwzyx), std::make_tuple(data_types::u8, format::bfwzyx), + + std::make_tuple(data_types::f32, format::b_fs_yx_fsv16), + std::make_tuple(data_types::f16, format::b_fs_yx_fsv16), + std::make_tuple(data_types::i8, format::b_fs_yx_fsv16), + std::make_tuple(data_types::u8, format::b_fs_yx_fsv16), + + std::make_tuple(data_types::f32, format::b_fs_zyx_fsv16), + std::make_tuple(data_types::f16, format::b_fs_zyx_fsv16), + std::make_tuple(data_types::i8, format::b_fs_zyx_fsv16), + std::make_tuple(data_types::u8, format::b_fs_zyx_fsv16), }); } diff --git a/inference-engine/thirdparty/clDNN/src/impls/ocl/reduce.cpp b/inference-engine/thirdparty/clDNN/src/impls/ocl/reduce.cpp index ef412f5dc345b3..e63cf6dd315e70 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/ocl/reduce.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/ocl/reduce.cpp @@ -101,6 +101,11 @@ attach_reduce_impl::attach_reduce_impl() { std::make_tuple(data_types::i32, format::b_fs_yx_fsv16), std::make_tuple(data_types::i8, format::b_fs_yx_fsv16), std::make_tuple(data_types::u8, format::b_fs_yx_fsv16), + std::make_tuple(data_types::f32, format::b_fs_yx_fsv32), + std::make_tuple(data_types::f16, format::b_fs_yx_fsv32), + std::make_tuple(data_types::i32, format::b_fs_yx_fsv32), + std::make_tuple(data_types::i8, format::b_fs_yx_fsv32), + std::make_tuple(data_types::u8, format::b_fs_yx_fsv32), }); } diff --git a/inference-engine/thirdparty/clDNN/src/impls/onednn/concatenation_onednn.cpp b/inference-engine/thirdparty/clDNN/src/impls/onednn/concatenation_onednn.cpp index 8051ff4fcbf105..2367674d7624d1 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/onednn/concatenation_onednn.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/onednn/concatenation_onednn.cpp @@ -73,7 +73,7 @@ struct concatenation_onednn : typed_primitive_onednn_impl dummy = nullptr; diff --git a/inference-engine/thirdparty/clDNN/src/impls/onednn/convolution_onednn.cpp b/inference-engine/thirdparty/clDNN/src/impls/onednn/convolution_onednn.cpp index b186d770314af7..214f62ba090bd1 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/onednn/convolution_onednn.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/onednn/convolution_onednn.cpp @@ -47,6 +47,7 @@ struct convolution_onednn : typed_primitive_onednn_impl get_arguments(convolution_inst& instance) const override { std::unordered_map args = parent::get_arguments(instance); + auto attrs = instance.get_node().get_onednn_primitive_attributes(); { auto weights = instance.weights_memory(0); @@ -58,13 +59,13 @@ struct convolution_onednn : typed_primitive_onednn_implget_onednn_memory(_pd.weights_desc(1))}); } - if (has_zero_points(DNNL_ARG_SRC, _attrs)) { + if (has_zero_points(DNNL_ARG_SRC, attrs)) { auto a_zp = instance.activations_zero_points_memory(0); dnnl::memory::desc desc = onednn::layout_to_memory_desc(a_zp->get_layout(), dnnl::memory::format_tag::a, true); args.insert({DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_SRC, a_zp->get_onednn_memory(desc)}); } - if (has_zero_points(DNNL_ARG_WEIGHTS, _attrs)) { + if (has_zero_points(DNNL_ARG_WEIGHTS, attrs)) { auto w_zp = instance.weights_zero_points_memory(0); dnnl::memory::desc desc = onednn::layout_to_memory_desc(w_zp->get_layout(), dnnl::memory::format_tag::a, true); args.insert({DNNL_ARG_ATTR_ZERO_POINTS | DNNL_ARG_WEIGHTS, w_zp->get_onednn_memory(desc)}); @@ -74,7 +75,7 @@ struct convolution_onednn : typed_primitive_onednn_impl get_primitive_attributes(const typed_program_node& arg) { - auto attrs = parent::get_primitive_attributes(arg); + auto attrs = arg.get_onednn_primitive_attributes(); if (arg.activations_zero_points_term()) { auto& a_zp = arg.activations_zero_points(); diff --git a/inference-engine/thirdparty/clDNN/src/impls/onednn/deconvolution_onednn.cpp b/inference-engine/thirdparty/clDNN/src/impls/onednn/deconvolution_onednn.cpp index f6400f80eddf28..00c98348eadd14 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/onednn/deconvolution_onednn.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/onednn/deconvolution_onednn.cpp @@ -62,7 +62,7 @@ struct deconvolution_onednn : typed_primitive_onednn_impl get_primitive_attributes(const typed_program_node& arg) { - auto attrs = parent::get_primitive_attributes(arg); + auto attrs = arg.get_onednn_primitive_attributes(); return attrs; } diff --git a/inference-engine/thirdparty/clDNN/src/impls/onednn/fully_connected_onednn.cpp b/inference-engine/thirdparty/clDNN/src/impls/onednn/fully_connected_onednn.cpp index f150760558c667..2796070a51b93a 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/onednn/fully_connected_onednn.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/onednn/fully_connected_onednn.cpp @@ -142,7 +142,7 @@ struct fully_connected_onednn : typed_primitive_onednn_impldata, attr.get(), engine.get_onednn_engine(), nullptr}; return new fully_connected_onednn(arg, desc, attr, prim_desc, get_weights_reorder(arg, prim_desc)); diff --git a/inference-engine/thirdparty/clDNN/src/impls/onednn/pooling_onednn.cpp b/inference-engine/thirdparty/clDNN/src/impls/onednn/pooling_onednn.cpp index a23af05094dee3..361d1bfd3719b6 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/onednn/pooling_onednn.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/onednn/pooling_onednn.cpp @@ -71,7 +71,7 @@ struct pooling_onednn : typed_primitive_onednn_impldata, attr.get(), engine.get_onednn_engine(), nullptr}; return new pooling_onednn(arg, desc, attr, prim_desc); diff --git a/inference-engine/thirdparty/clDNN/src/impls/onednn/primitive_onednn_base.h b/inference-engine/thirdparty/clDNN/src/impls/onednn/primitive_onednn_base.h index 10748a4c68ba4d..4f0bcc3a874199 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/onednn/primitive_onednn_base.h +++ b/inference-engine/thirdparty/clDNN/src/impls/onednn/primitive_onednn_base.h @@ -26,36 +26,6 @@ namespace cldnn { namespace onednn { -enum class onednn_post_op_type : uint32_t { - eltwise_act, - eltwise_clip, - eltwise_linear, - eltwise_round, - binary_mul, - binary_add, - binary_max, - binary_min, - scale, - sum, - optimized, - optimized_eltwise, - optimized_sum -}; - -struct onednn_post_op_desc { - onednn_post_op_type op_type; - size_t mem_offset; - size_t mem_dep; -}; - -// This map contains information about onednn post-ops types, memory buffer offsets and dependencies -// key is cldnn::primitive_id, -// value is an instance of struct onednn_post_op_desc containing info about post-ops related to the node defined by key: -// op_type - onednn_post_op_type (enum), -// mem_offset - index of memory buffer for current post-operation, -// mem_dep - memory dependency for working with fused node -static std::unordered_map> onednn_fusing_map; - template struct typed_primitive_onednn_impl : public typed_primitive_impl { const typed_program_node& _outer; @@ -82,7 +52,7 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl { protected: virtual bool optimized_out(typed_primitive_inst&) const { return false; } - static bool has_out_scales(const std::shared_ptr& attr) { + static bool has_output_scales(const std::shared_ptr& attr) { int mask; std::vector scales; attr->get_output_scales(mask, scales); @@ -98,408 +68,22 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl { return !zp.empty() && (reinterpret_cast(zp[0]) == drsv); } - static dnnl::post_ops try_optimize_post_ops(const typed_program_node& arg, dnnl::post_ops& p_ops, - const std::shared_ptr& attr, - bool& optimization_is_completed) { - // Get current node id for creating of optimization map - auto node_id = arg.id(); - - // Create new dnnl::post_ops object which will be filled inside the optimization process - dnnl::post_ops optimized_p_ops; - - // Add new post-op into optimized_p_ops structure - auto add_post_op = [&](onednn_post_op_type type, const dnnl::post_ops& cur_p_ops, dnnl::post_ops& new_p_ops, int idx) { - switch (type) { - case onednn_post_op_type::eltwise_act: - case onednn_post_op_type::eltwise_clip: - case onednn_post_op_type::eltwise_linear: - case onednn_post_op_type::eltwise_round: - { - dnnl::algorithm alg; - float scale, alpha, beta; - cur_p_ops.get_params_eltwise(idx, scale, alg, alpha, beta); - new_p_ops.append_eltwise(scale, alg, alpha, beta); - break; - } - - case onednn_post_op_type::binary_add: - case onednn_post_op_type::binary_mul: - case onednn_post_op_type::binary_max: - case onednn_post_op_type::binary_min: - { - dnnl::algorithm alg; - dnnl::memory::desc desc; - cur_p_ops.get_params_binary(idx, alg, desc); - new_p_ops.append_binary(alg, desc); - break; - } - - case onednn_post_op_type::scale: - { - break; - } - - case onednn_post_op_type::sum: - { - float scale; - dnnl::memory::data_type data_type; - cur_p_ops.get_params_sum(idx, scale, data_type); - new_p_ops.append_sum(scale, data_type); - break; - } - - case onednn_post_op_type::optimized: - case onednn_post_op_type::optimized_sum: - case onednn_post_op_type::optimized_eltwise: - { - // Current operation already has been optimized => don't need extra actions - break; - } - - default: - throw std::runtime_error("Unsupported onednn post-operation type"); - } - }; - - // Check that post-op type is any optimized - auto type_is_any_optimized = [](onednn_post_op_type type) -> bool { - return type == onednn_post_op_type::optimized || type == onednn_post_op_type::optimized_sum || - type == onednn_post_op_type::optimized_eltwise; - }; - - // Check that post-op type is eltwise - auto type_is_eltwise = [](onednn_post_op_type type) -> bool { - return type == onednn_post_op_type::eltwise_round || type == onednn_post_op_type::eltwise_linear || - type == onednn_post_op_type::eltwise_clip || type == onednn_post_op_type::eltwise_act; - }; - - // Check that post-op type is binary_add or binary_mul - auto type_is_binary_add_or_mul = [](onednn_post_op_type type) -> bool { - return type == onednn_post_op_type::binary_add || type == onednn_post_op_type::binary_mul; - }; - - // Simple post-op type checks - auto type_is_optimized = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::optimized; }; - auto type_is_eltwise_linear = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::eltwise_linear; }; - auto type_is_optimized_eltwise = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::optimized_eltwise; }; - auto type_is_binary_add = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::binary_add; }; - auto type_is_binary_mul = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::binary_mul; }; - auto type_is_sum = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::sum; }; - auto type_is_optimized_sum = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::optimized_sum; }; - auto type_is_scale = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::scale; }; - - auto& cur_post_ops = onednn_fusing_map[node_id]; - - size_t cur_post_op_idx = 1; - size_t prev_post_op_idx = 0; - bool optimization_done = false; - - // Check and update post-op map if we already optimized something - for (size_t post_op_idx = 0; post_op_idx < cur_post_ops.size(); post_op_idx++) { - if (type_is_optimized_sum(cur_post_ops[post_op_idx].op_type)) - cur_post_ops[post_op_idx].op_type = onednn_post_op_type::sum; - else if (type_is_optimized_eltwise(cur_post_ops[post_op_idx].op_type)) - cur_post_ops[post_op_idx].op_type = onednn_post_op_type::eltwise_linear; - else if (type_is_optimized(cur_post_ops[post_op_idx].op_type)) - cur_post_ops.erase(cur_post_ops.begin() + post_op_idx); - } - - // Get post-ops size for current node - auto post_ops_size = cur_post_ops.size(); - - // Try to combine pairs of arithmetic post-ops (adds and muls) into one operation inside this cycle - while (!optimization_done) { - auto cur_type = cur_post_ops[cur_post_op_idx].op_type; - auto prev_type = cur_post_ops[prev_post_op_idx].op_type; - - // Ignore optimized operations for "previous" operation in our operation pair - while (type_is_any_optimized(prev_type) && cur_post_op_idx < post_ops_size - 1) { - prev_post_op_idx++; - cur_post_op_idx++; - prev_type = cur_post_ops[prev_post_op_idx].op_type; - cur_type = cur_post_ops[cur_post_op_idx].op_type; - } - - // Ignore optimized operations for "current" operation in our operation pair - while (type_is_any_optimized(cur_type) && cur_post_op_idx < post_ops_size - 1) { - cur_post_op_idx++; - cur_type = cur_post_ops[cur_post_op_idx].op_type; - } - - auto cur_idx = static_cast(has_out_scales(attr) ? (cur_post_op_idx >= 1 ? cur_post_op_idx - 1 : 0) : cur_post_op_idx); - auto prev_idx = static_cast(has_out_scales(attr) ? (prev_post_op_idx >= 1 ? prev_post_op_idx - 1 : 0) : prev_post_op_idx); - - // If this is the last pair and it's optimized - add the last post-op and go out from the cycle - if (cur_post_op_idx == post_ops_size - 1 && (type_is_any_optimized(cur_type) || type_is_any_optimized(prev_type))) { - if (!type_is_any_optimized(prev_type)) { - add_post_op(prev_type, p_ops, optimized_p_ops, prev_idx); - } - if (!type_is_any_optimized(cur_type)) { - add_post_op(cur_type, p_ops, optimized_p_ops, cur_idx); - } - break; - } - - // Post-ops combinations which can be simplified - auto eltw_and_eltw = type_is_eltwise(cur_type) && type_is_eltwise(prev_type); - auto bin_and_eltw = type_is_binary_add_or_mul(cur_type) && type_is_eltwise_linear(prev_type); - auto eltw_and_bin = type_is_eltwise_linear(cur_type) && type_is_binary_add_or_mul(prev_type); - auto sum_and_eltw = type_is_sum(cur_type) && type_is_eltwise(prev_type); - auto eltw_and_scale = type_is_eltwise_linear(cur_type) && type_is_scale(prev_type); - - auto can_try_optimize = eltw_and_eltw || - bin_and_eltw || - eltw_and_bin || - sum_and_eltw || - eltw_and_scale; - - bool cur_ops_pair_is_optimized = false; - - if (can_try_optimize) { - if (eltw_and_eltw) { - dnnl::algorithm cur_alg, prev_alg; - float cur_scale, prev_scale, cur_alpha, prev_alpha, cur_beta, prev_beta; - - p_ops.get_params_eltwise(prev_idx, prev_scale, prev_alg, prev_alpha, prev_beta); - p_ops.get_params_eltwise(cur_idx, cur_scale, cur_alg, cur_alpha, cur_beta); - - auto eltw_linear_and_eltw_linear = type_is_eltwise_linear(cur_type) && type_is_eltwise_linear(prev_type); - auto eltw_linear_and_eltw_non_linear = type_is_eltwise_linear(cur_type) && !type_is_eltwise_linear(prev_type) && cur_beta == 0; - - // eltwise_linear + eltwise_linear combination can be optimized always - if (eltw_linear_and_eltw_linear) { - dnnl::post_ops eltw_p_op; - float optimized_alpha = cur_alpha * prev_alpha * prev_scale; - float optimized_beta = cur_alpha * prev_beta * prev_scale + cur_beta; - float optimized_scale = cur_scale; - eltw_p_op.append_eltwise(optimized_scale, cur_alg, optimized_alpha, optimized_beta); - - // Combine 2 eltwises into one - add_post_op(cur_type, eltw_p_op, optimized_p_ops, 0); - } else if (eltw_linear_and_eltw_non_linear) { - dnnl::post_ops eltw_p_op; - eltw_p_op.append_eltwise(cur_scale * prev_scale * cur_alpha, prev_alg, prev_alpha, prev_beta); - - // Combine 2 eltwises into one - add_post_op(prev_type, eltw_p_op, optimized_p_ops, 0); - } - - if (eltw_linear_and_eltw_linear || eltw_linear_and_eltw_non_linear) { - // Marked current and previous eltwise operations as 'optimized' (they will be ignored on the next iteration of cycle) - cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized; - cur_post_ops[prev_post_op_idx].op_type = onednn_post_op_type::optimized_eltwise; - - // Set the flag if extra optimizations checking is needed - if (cur_post_op_idx < post_ops_size - 1) { - if (type_is_eltwise_linear(cur_post_ops[cur_post_op_idx + 1].op_type) || - type_is_binary_add_or_mul(cur_post_ops[cur_post_op_idx + 1].op_type) || - type_is_optimized_eltwise(cur_post_ops[cur_post_op_idx + 1].op_type)) { - optimization_is_completed = true; - } - } - - cur_ops_pair_is_optimized = true; - } - } else if (bin_and_eltw) { - dnnl::algorithm alg; - dnnl::memory::desc desc; - float scale, alpha, beta; - - cldnn::program_node& cur_node = arg.get_dependency(cur_post_ops[cur_post_op_idx].mem_dep); - - p_ops.get_params_binary(cur_idx, alg, desc); - p_ops.get_params_eltwise(prev_idx, scale, alg, alpha, beta); - - // Eltwise operations can use runtime non-constant data buffers, so check that memory buffers consist of constant data only - auto bin_ops_can_be_optimized = cur_node.is_type() && cur_node.is_constant() && - cur_node.get_users().size() == 1 && desc.data_type() == dnnl_f32; - - auto bin_add_and_eltw = alpha == 1.0f && scale == 1.0f && type_is_binary_add(cur_type) && bin_ops_can_be_optimized; - auto bin_mul_and_eltw = beta == 0.f && type_is_binary_mul(cur_type) && bin_ops_can_be_optimized; - - if (bin_add_and_eltw || bin_mul_and_eltw) { - memory::ptr cur_bin_mem_ptr = cur_node.as().get_attached_memory_ptr(); - if (cur_bin_mem_ptr == nullptr) - throw std::runtime_error("OneDNN post-ops optimization error: nonexistent node for bin + eltw"); - auto& stream = cur_bin_mem_ptr->get_engine()->get_program_stream(); - mem_lock bin_and_eltw_lock(cur_bin_mem_ptr, stream); - - size_t cur_bin_mem_size = cur_node.get_output_layout().count(); - - // Update all binary coefficients - if (bin_add_and_eltw) { - for (size_t data_idx = 0; data_idx < cur_bin_mem_size; data_idx++) { - bin_and_eltw_lock[data_idx] += beta; - } - } else { - for (size_t data_idx = 0; data_idx < cur_bin_mem_size; data_idx++) { - bin_and_eltw_lock[data_idx] *= alpha * scale; - } - } - - // Marked previous eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle) - cur_post_ops[prev_post_op_idx].op_type = onednn_post_op_type::optimized; - - cur_ops_pair_is_optimized = true; - } - } else if (eltw_and_bin) { - dnnl::algorithm alg; - dnnl::memory::desc desc; - float scale, alpha, beta; - - cldnn::program_node& prev_node = arg.get_dependency(cur_post_ops[prev_post_op_idx].mem_dep); - - p_ops.get_params_eltwise(cur_idx, scale, alg, alpha, beta); - p_ops.get_params_binary(prev_idx, alg, desc); - - // Eltwise operations can use runtime non-constant data buffers, so check that memory buffers consist of constant data only - auto bin_ops_can_be_optimized = prev_node.is_type() && prev_node.is_constant() && - prev_node.get_users().size() == 1 && desc.data_type() == dnnl_f32; - - auto eltw_and_bin_add = alpha == 1.0f && scale == 1.0f && type_is_binary_add(prev_type) && bin_ops_can_be_optimized; - auto eltw_and_bin_mul = beta == 0.f && type_is_binary_mul(prev_type) && bin_ops_can_be_optimized; - - if (eltw_and_bin_add || eltw_and_bin_mul) { - memory::ptr prev_bin_mem_ptr = prev_node.as().get_attached_memory_ptr(); - if (prev_bin_mem_ptr == nullptr) - throw std::runtime_error("OneDNN post-ops optimization error: nonexistent node for eltw + bin"); - auto& stream = prev_bin_mem_ptr->get_engine()->get_program_stream(); - mem_lock eltw_and_bin_lock(prev_bin_mem_ptr, stream); - - size_t prev_bin_mem_size = prev_node.get_output_layout().count(); - - // Update all binary coefficients - if (eltw_and_bin_add) { - for (size_t data_idx = 0; data_idx < prev_bin_mem_size; data_idx++) { - eltw_and_bin_lock[data_idx] += beta; - } - } else { - for (size_t data_idx = 0; data_idx < prev_bin_mem_size; data_idx++) { - eltw_and_bin_lock[data_idx] *= alpha * scale; - } - } - - // Marked current eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle) - cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized; - - cur_ops_pair_is_optimized = true; - } - } else if (sum_and_eltw) { - dnnl::algorithm alg; - float sum_scale, eltw_scale, alpha, beta; - dnnl::memory::data_type data_type; - - dnnl::algorithm next_alg; - float next_scale, next_alpha, next_beta; - size_t next_idx = cur_idx + 1; - size_t next_post_op_idx = cur_post_op_idx + 1; - - bool can_optimize_eltw_and_sum = false; - - if (cur_post_op_idx < post_ops_size - 1) { - auto next_type = cur_post_ops[next_post_op_idx].op_type; - if (type_is_eltwise_linear(next_type)) { - p_ops.get_params_eltwise(next_idx, next_scale, next_alg, next_alpha, next_beta); - - if (next_beta == 0) - can_optimize_eltw_and_sum = true; - } - } - - // Try to optimize eltwise (any) + sum + eltwise_linear (with beta = 0) chain of operations - if (can_optimize_eltw_and_sum) { - p_ops.get_params_sum(cur_idx, sum_scale, data_type); - p_ops.get_params_eltwise(prev_idx, eltw_scale, alg, alpha, beta); - - dnnl::post_ops eltw_p_op_prev, sum_p_op; - - eltw_p_op_prev.append_eltwise(eltw_scale * next_alpha * next_scale, alg, alpha, beta); - sum_p_op.append_sum(sum_scale * next_alpha, data_type); - - add_post_op(prev_type, eltw_p_op_prev, optimized_p_ops, 0); - add_post_op(cur_type, sum_p_op, optimized_p_ops, 0); - - // Marked current, previous and next operations as 'optimized' (they will be ignored on the next iteration of cycle) - cur_post_ops[prev_post_op_idx].op_type = onednn_post_op_type::optimized_eltwise; - cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized_sum; - cur_post_ops[next_post_op_idx].op_type = onednn_post_op_type::optimized; - - // Set the flag if extra optimizations checking is needed - if (next_post_op_idx < post_ops_size - 1) { - if (type_is_eltwise_linear(cur_post_ops[next_post_op_idx + 1].op_type) || - type_is_optimized_eltwise(cur_post_ops[next_post_op_idx + 1].op_type)) { - optimization_is_completed = true; - } - } - - cur_ops_pair_is_optimized = true; - } - } else if (eltw_and_scale) { - dnnl::algorithm alg; - float eltw_scale, alpha, beta; - - cldnn::program_node& prev_node = arg.get_dependency(cur_post_ops[prev_post_op_idx].mem_dep); - - p_ops.get_params_eltwise(cur_idx, eltw_scale, alg, alpha, beta); - - // Eltwise can be inserted into the output_scale if cur_beta is equal to 0.f - if (beta == 0.f && prev_node.get_output_layout().data_type == data_types::f32) { - memory::ptr prev_scale_mem_ptr = prev_node.as().get_attached_memory_ptr(); - if (prev_scale_mem_ptr == nullptr) - throw std::runtime_error("OneDNN post-ops optimization error: nonexistent node for eltw + scale"); - auto& stream = prev_scale_mem_ptr->get_engine()->get_program_stream(); - mem_lock eltw_and_scale_lock(prev_scale_mem_ptr, stream); - - size_t prev_scale_mem_size = prev_node.get_output_layout().count(); - - // Update all scale coefficients - for (size_t data_idx = 0; data_idx < prev_scale_mem_size; data_idx++) { - eltw_and_scale_lock[data_idx] *= alpha * eltw_scale; - } - - // Marked current eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle) - cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized; - - cur_ops_pair_is_optimized = true; - } - } - } - - // If no optimizations have been applied then copy post-op info into the new optimized_p_ops structure - if (!(has_out_scales(attr) && prev_post_op_idx == 0) && !cur_ops_pair_is_optimized) { - add_post_op(prev_type, p_ops, optimized_p_ops, prev_idx); - } - - if (cur_post_op_idx == post_ops_size - 1 && !cur_ops_pair_is_optimized) { - add_post_op(cur_type, p_ops, optimized_p_ops, cur_idx); - optimization_done = true; - } else if (cur_post_ops[cur_post_op_idx].op_type != onednn_post_op_type::optimized) { - cur_post_op_idx++; - prev_post_op_idx++; - } - } - - optimization_is_completed = !optimization_is_completed; - - return optimized_p_ops; - } - void configure_post_ops_arguments(typed_primitive_inst& instance, std::unordered_map& args) const { - // Get current node id for creating of optimization map - auto node_id = instance.id(); + auto& node = instance.get_node(); auto& engine = instance.get_network().get_engine(); auto dnnl_engine = engine.get_onednn_engine(); // Get current post-ops info - dnnl::post_ops post_ops = _attrs->get_post_ops(); + auto onednn_attrs = node.get_onednn_primitive_attributes(); + dnnl::post_ops post_ops = onednn_attrs->get_post_ops(); // Create onednn memory buffers for post-ops - auto& cur_post_ops = onednn_fusing_map[node_id]; + auto& cur_post_ops = node.get_fused_primitives_onednn(); auto post_ops_size = cur_post_ops.size(); for (size_t post_op_idx = 0, num_of_optimized_post_ops = 0; post_op_idx < post_ops_size; post_op_idx++) { auto post_op_type = cur_post_ops[post_op_idx].op_type; auto memory_offset = cur_post_ops[post_op_idx].mem_offset; - auto onednn_post_op_idx = has_out_scales(_attrs) && post_op_idx > 0 ? post_op_idx - 1 : post_op_idx; + auto onednn_post_op_idx = has_output_scales(onednn_attrs) && post_op_idx > 0 ? post_op_idx - 1 : post_op_idx; onednn_post_op_idx -= num_of_optimized_post_ops; switch (post_op_type) { @@ -576,296 +160,6 @@ struct typed_primitive_onednn_impl : public typed_primitive_impl { void init_kernels() override { } - static std::shared_ptr get_primitive_attributes(const typed_program_node& arg) { - const std::vector& cldnn_post_ops = arg.get_fused_primitives(); - auto attrs = std::make_shared(); - dnnl::post_ops post_ops; - size_t memory_offset = 0; - - // Create onednn post-ops list related to the current node - std::vector fused_ops; - - // Added this for debug purposes only - size_t empty_mem = 0xff; - - // Add information about post-operation into the list, update indices - auto update_onednn_post_op_list = [&](onednn_post_op_type type, size_t m_dep) { - onednn_post_op_desc cur_op_desc = { type, memory_offset, m_dep }; - fused_ops.push_back(cur_op_desc); - - auto has_memory_buffers = type == onednn_post_op_type::binary_add || - type == onednn_post_op_type::binary_mul || - type == onednn_post_op_type::binary_max || - type == onednn_post_op_type::binary_min || - type == onednn_post_op_type::scale || - type == onednn_post_op_type::sum; - if (has_memory_buffers) - memory_offset++; - }; - - for (size_t idx = 0; idx < cldnn_post_ops.size(); idx++) { - auto node = cldnn_post_ops[idx].node; - - if (node->is_type()) { - auto fused_desc = node->as().get_primitive(); - dnnl::algorithm alg = onednn::convert_activation_func(fused_desc->activation_function); - post_ops.append_eltwise(1.0f, alg, fused_desc->additional_params.a, fused_desc->additional_params.b); - update_onednn_post_op_list(onednn_post_op_type::eltwise_act, empty_mem); - } else if (node->is_type()) { - auto& e_node = node->as(); - auto dep_idx = cldnn_post_ops[idx].dep_start_idx; - auto in = arg.get_dependency(dep_idx).get_output_layout(); - - if (e_node.get_primitive()->mode == eltwise_mode::sum) { - if (e_node.get_primitive()->needs_onednn_sum_post_op(in)) { - post_ops.append_sum(1.0f, onednn::convert_data_type(in.data_type)); - update_onednn_post_op_list(onednn_post_op_type::sum, dep_idx); - } else { - dnnl::memory::desc in_desc = onednn::layout_to_memory_desc(in, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_add, in_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx); - } - } else { - if (in.size.spatial[0] > 1 || in.size.spatial[1] > 1 || in.size.batch[0] > 1) - throw std::runtime_error("Unsupported eltwise mode for fused onednn op"); - if (idx == 0 && !has_out_scales(attrs)) { - int mask = in.count() > 1 ? 2 : 0; - attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL}); - update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx); - } else { - dnnl::memory::desc in_desc = onednn::layout_to_memory_desc(in, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_mul, in_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx); - } - } - } else if (node->is_type()) { - auto& q_node = node->as(); - auto dep_idx = cldnn_post_ops[idx].dep_start_idx; - - if (q_node.get_per_tensor_output_range() && q_node.get_output_lo_val() < q_node.get_output_hi_val()) { - // 1. pre-scale & pre-shift - { - if (q_node.get_per_tensor_input_scale() && q_node.get_per_tensor_input_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), q_node.get_input_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - if (q_node.get_per_tensor_input_scale()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), 0.0f); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto in_scale = arg.get_dependency(dep_idx++).get_output_layout(); - if (idx == 0 && !has_out_scales(attrs) && in_scale.data_type == data_types::f32 && - arg.type() == convolution::type_id() && - !data_type_traits::is_floating_point(arg.get_dependency(0).get_output_layout().data_type)) { - int mask = in_scale.count() > 1 ? 2 : 0; - attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL}); - update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx - 1); - } else { - dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); - } - } - - if (q_node.get_need_pre_shift()) { - if (q_node.get_per_tensor_input_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_input_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto in_shift = arg.get_dependency(dep_idx++).get_output_layout(); - dnnl::memory::desc in_shift_desc = onednn::layout_to_memory_desc(in_shift, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_add, in_shift_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); - } - } - } - } - - // 2. round - auto out_dt = cldnn_post_ops[idx].output_layout.data_type; - bool output_type_is_int8 = out_dt == data_types::u8 || out_dt == data_types::i8; - if (!output_type_is_int8) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_round, 0.0f, 0.0f); - update_onednn_post_op_list(onednn_post_op_type::eltwise_round, empty_mem); - } - - // 3. post-scale & post-shift - if (q_node.get_need_post_scale() && q_node.get_need_post_shift() && - q_node.get_per_tensor_output_scale() && q_node.get_per_tensor_output_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), q_node.get_output_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - if (q_node.get_need_post_scale()) { - if (q_node.get_per_tensor_output_scale()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), 0.0f); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto out_scale = arg.get_dependency(dep_idx++).get_output_layout(); - dnnl::memory::desc out_scale_desc = onednn::layout_to_memory_desc(out_scale, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_mul, out_scale_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); - } - } - - if (q_node.get_need_post_shift()) { - if (q_node.get_per_tensor_output_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_output_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto out_shift = arg.get_dependency(dep_idx++).get_output_layout(); - dnnl::memory::desc out_shift_desc = onednn::layout_to_memory_desc(out_shift, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_add, out_shift_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); - } - } - } - - // 4. clamp - if (q_node.get_need_clamp()) { - float out_lo = q_node.get_need_min_clamp() ? q_node.get_output_lo_val() : data_type_traits::min(out_dt); - float out_hi = q_node.get_need_max_clamp() ? q_node.get_output_hi_val() : data_type_traits::max(out_dt); - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_clip, out_lo, out_hi); - update_onednn_post_op_list(onednn_post_op_type::eltwise_clip, empty_mem); - } - } else { - // 1. clamp - if (q_node.get_need_clamp()) { - auto in_lo = arg.get_dependency(dep_idx++).get_output_layout(); - auto in_hi = arg.get_dependency(dep_idx++).get_output_layout(); - dnnl::algorithm clamp_max = dnnl::algorithm::binary_max; - dnnl::algorithm clamp_min = dnnl::algorithm::binary_min; - dnnl::memory::desc in_lo_desc = onednn::layout_to_memory_desc(in_lo, dnnl::memory::format_tag::ab, true); - dnnl::memory::desc in_hi_desc = onednn::layout_to_memory_desc(in_hi, dnnl::memory::format_tag::ab, true); - - post_ops.append_binary(clamp_max, in_lo_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_max, dep_idx - 2); - post_ops.append_binary(clamp_min, in_hi_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_min, dep_idx - 1); - } - - // 2. pre-scale & pre-shift - { - if (q_node.get_per_tensor_input_scale() && q_node.get_per_tensor_input_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), q_node.get_input_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - if (q_node.get_per_tensor_input_scale()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), 0.0f); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto in_scale = arg.get_dependency(dep_idx++).get_output_layout(); - if (idx == 0 && !q_node.get_need_clamp() && !has_out_scales(attrs) && in_scale.data_type == data_types::f32 && - arg.type() == convolution::type_id() && - !data_type_traits::is_floating_point(arg.get_dependency(0).get_output_layout().data_type)) { - int mask = in_scale.count() > 1 ? 2 : 0; - attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL}); - update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx - 1); - } else { - dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); - } - } - - if (q_node.get_need_pre_shift()) { - if (q_node.get_per_tensor_input_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_input_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto in_shift = arg.get_dependency(dep_idx++).get_output_layout(); - dnnl::memory::desc in_shift_desc = onednn::layout_to_memory_desc(in_shift, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_add, in_shift_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); - } - } - } - } - - // 3. round - { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_round, 0.0f, 0.0f); - update_onednn_post_op_list(onednn_post_op_type::eltwise_round, empty_mem); - } - - // 4. post-scale & post-shift - if (q_node.get_need_post_scale() && q_node.get_need_post_shift() && - q_node.get_per_tensor_output_scale() && q_node.get_per_tensor_output_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), q_node.get_output_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - if (q_node.get_need_post_scale()) { - if (q_node.get_per_tensor_output_scale()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), 0.0f); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto out_scale = arg.get_dependency(dep_idx++).get_output_layout(); - dnnl::memory::desc out_scale_desc = onednn::layout_to_memory_desc(out_scale, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_mul, out_scale_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); - } - } - - if (q_node.get_need_post_shift()) { - if (q_node.get_per_tensor_output_shift()) { - post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_output_shift_val()); - update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); - } else { - auto out_shift = arg.get_dependency(dep_idx++).get_output_layout(); - dnnl::memory::desc out_shift_desc = onednn::layout_to_memory_desc(out_shift, dnnl::memory::format_tag::ab, true); - post_ops.append_binary(dnnl::algorithm::binary_add, out_shift_desc); - update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); - } - } - } - } - } else if (node->is_type()) { - continue; - } else { - throw std::runtime_error("Unsupported fused op of " + node->get_primitive()->type_string() + " type for oneDNN primitive"); - } - } - - if (cldnn_post_ops.size() && arg.get_fused_activations_funcs().size()) - throw std::runtime_error("Unsupported mix of fused ops and activations"); - - for (size_t i = 0; i < arg.get_fused_activations_funcs().size(); i++) { - auto activation_type = arg.get_fused_activations_funcs()[i]; - auto params = arg.get_fused_activations_params()[i]; - dnnl::algorithm alg = onednn::convert_activation_func(activation_type); - post_ops.append_eltwise(1.0f, alg, params.a, params.b); - update_onednn_post_op_list(onednn_post_op_type::eltwise_act, empty_mem); - } - - // Update total onednn post-ops info - auto it = onednn_fusing_map.find(arg.id()); - if (it != onednn_fusing_map.end()) { - it->second = std::move(fused_ops); - } else { - onednn_fusing_map.emplace(arg.id(), std::move(fused_ops)); - } - - // Trying to optimize more than 1 post-ops - auto post_ops_size = onednn_fusing_map[arg.id()].size(); - - if (post_ops_size > 1) { - dnnl::post_ops optimized_post_ops = post_ops; - bool optimization_is_finished = false; - - // Trying to combine multiplications and additions which are placed one after another. - // We do it in the cycle because "eltw + eltw" cases can be simplified again in some cases. - do { - optimized_post_ops = try_optimize_post_ops(arg, optimized_post_ops, attrs, optimization_is_finished); - } while (!optimization_is_finished); - - attrs->set_post_ops(optimized_post_ops); - } else { - // Set post-ops without any optimizations - attrs->set_post_ops(post_ops); - } - - return attrs; - } - event::ptr aggregate_events(const std::vector& events, stream& stream, bool group = false, bool is_output = false) const { if (events.size() == 1 && !is_output) return events[0]; diff --git a/inference-engine/thirdparty/clDNN/src/impls/onednn/reorder_onednn.cpp b/inference-engine/thirdparty/clDNN/src/impls/onednn/reorder_onednn.cpp index 31a09be251c0f3..86f9efecb38686 100644 --- a/inference-engine/thirdparty/clDNN/src/impls/onednn/reorder_onednn.cpp +++ b/inference-engine/thirdparty/clDNN/src/impls/onednn/reorder_onednn.cpp @@ -55,13 +55,13 @@ struct reorder_onednn : typed_primitive_onednn_impl dummy = nullptr; diff --git a/inference-engine/thirdparty/clDNN/src/include/pass_manager.h b/inference-engine/thirdparty/clDNN/src/include/pass_manager.h index 670dac7adc6092..f825bd060efe2c 100644 --- a/inference-engine/thirdparty/clDNN/src/include/pass_manager.h +++ b/inference-engine/thirdparty/clDNN/src/include/pass_manager.h @@ -393,4 +393,10 @@ class update_loop_primitive_map : public base_pass { void run(program& p) override; }; +class add_onednn_optimization_attributes : public base_pass { +public: + add_onednn_optimization_attributes() : base_pass("add_onednn_optimization_attributes") {} + void run(program& p) override; +}; + } // namespace cldnn diff --git a/inference-engine/thirdparty/clDNN/src/include/program_node.h b/inference-engine/thirdparty/clDNN/src/include/program_node.h index 9b11846ee6ea77..3804b285065955 100644 --- a/inference-engine/thirdparty/clDNN/src/include/program_node.h +++ b/inference-engine/thirdparty/clDNN/src/include/program_node.h @@ -33,6 +33,29 @@ struct typed_program_node; class json_composite; class xml_composite; +#ifdef ENABLE_ONEDNN_FOR_GPU +enum class onednn_post_op_type : uint32_t { + eltwise_act, + eltwise_clip, + eltwise_linear, + eltwise_round, + binary_mul, + binary_add, + binary_max, + binary_min, + scale, + sum, + optimized, + optimized_eltwise, + optimized_sum +}; + +struct fused_primitive_desc_onednn { + onednn_post_op_type op_type; // onednn post-operation type + size_t mem_offset; // index of a memory buffer for current post-operation + size_t mem_dep; // memory dependency for working with fused node +}; +#endif // ENABLE_ONEDNN_FOR_GPU struct fused_primitive_desc { std::shared_ptr node; @@ -57,7 +80,7 @@ struct fused_primitive_desc { to API level where all primitives store only ids of related ones. */ struct program_node { - friend struct program; // to be removed when possible + friend struct program; // to be removed when possible friend class compile_graph; // to be removed when possible friend class graph_initializations; // to be removed when possible friend class pre_replace_deconv; // to be removed when possible @@ -293,6 +316,16 @@ struct program_node { const std::vector& get_fused_primitives() const { return fused_prims; } std::vector& get_fused_primitives() { return fused_prims; } +#ifdef ENABLE_ONEDNN_FOR_GPU + const std::shared_ptr& get_onednn_primitive_attributes() const { return onednn_attrs; } + std::shared_ptr& get_onednn_primitive_attributes() { return onednn_attrs; } + + const std::vector& get_fused_primitives_onednn() const { return fused_prims_onednn; } + std::vector& get_fused_primitives_onednn() { return fused_prims_onednn; } + + void init_onednn_primitive_attributes(); +#endif // ENABLE_ONEDNN_FOR_GPU + size_t get_fused_inputs_count() const { size_t count = 0; for (auto& fp : get_fused_primitives()) { @@ -360,7 +393,26 @@ struct program_node { std::vector fused_activations; std::vector fused_prims; + void invalidate_users() const; + +private: +#ifdef ENABLE_ONEDNN_FOR_GPU + std::vector fused_prims_onednn; + std::shared_ptr onednn_attrs; + + void add_onednn_fused_primitives(std::vector descs) { + fused_prims_onednn.erase(fused_prims_onednn.begin(), fused_prims_onednn.end()); + fused_prims_onednn.insert(fused_prims_onednn.end(), descs.begin(), descs.end()); + } + + void add_onednn_attrs(std::shared_ptr attrs) { + onednn_attrs = attrs; + } + + bool has_out_scales(const std::shared_ptr& attr); + dnnl::post_ops try_optimize_post_ops(dnnl::post_ops& p_ops, const std::shared_ptr& attr, bool& optimization_is_completed); +#endif // ENABLE_ONEDNN_FOR_GPU }; /* diff --git a/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp b/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp index 5b9f0fb311f275..c2b8aed63f49e3 100644 --- a/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp +++ b/inference-engine/thirdparty/clDNN/src/layout_optimizer.cpp @@ -859,17 +859,12 @@ layout layout_optimizer::get_expected_layout(layout const& current_layout, if (input_layout.size.batch[0] % 16 == 0) { expected_format = cldnn::format::bs_fs_yx_bsv32_fsv32; } else { - if (data_type_traits::is_floating_point(output_layout.data_type)) - expected_format = cldnn::format::b_fs_yx_fsv16; - else - expected_format = cldnn::format::b_fs_yx_fsv32; + expected_format = cldnn::format::b_fs_yx_fsv32; } } else if ((_optimization_attributes.b_fs_yx_fsv16_network && convolution_b_fs_yx_fsv16_opt(input_layout, output_layout, weights_layout, prim)) && is_2d) { - if (is_dw) - expected_format = cldnn::format::b_fs_yx_fsv32; - else - expected_format = cldnn::format::b_fs_yx_fsv16; + // TODO: optimize clDNN kernels for good support of b_fs_yx_fsv32 format + expected_format = cldnn::format::b_fs_yx_fsv32; } else { expected_format = imad_case(node); } diff --git a/inference-engine/thirdparty/clDNN/src/network.cpp b/inference-engine/thirdparty/clDNN/src/network.cpp index 1293b628d30895..d38ad87060f461 100644 --- a/inference-engine/thirdparty/clDNN/src/network.cpp +++ b/inference-engine/thirdparty/clDNN/src/network.cpp @@ -497,6 +497,9 @@ void network::allocate_primitives() { auto eltw_in_layout = eltw_in.get_output_layout(); auto out_layout = node->get_output_layout(); + if (!fused_op.node->as().get_primitive()->needs_onednn_sum_post_op(eltw_in_layout)) + continue; + if (eltw_in_layout.size == out_layout.size && eltw_in_layout.format == out_layout.format && eltw_in_layout.data_padding == out_layout.data_padding && diff --git a/inference-engine/thirdparty/clDNN/src/primitive_inst.cpp b/inference-engine/thirdparty/clDNN/src/primitive_inst.cpp index c99329cb6e3251..7aa46da302df86 100644 --- a/inference-engine/thirdparty/clDNN/src/primitive_inst.cpp +++ b/inference-engine/thirdparty/clDNN/src/primitive_inst.cpp @@ -269,7 +269,7 @@ memory::ptr primitive_inst::allocate_output() { }; bool usm_device_allocatable = true; - const auto& total_device_input_mem_size = std::accumulate(node_deps.begin(), node_deps.end(), 0, device_mem_acc); + const auto& total_device_input_mem_size = std::accumulate(node_deps.begin(), node_deps.end(), (uint64_t)0, device_mem_acc); if (total_device_input_mem_size > engine.get_device_info().max_global_mem_size) usm_device_allocatable = false; diff --git a/inference-engine/thirdparty/clDNN/src/program.cpp b/inference-engine/thirdparty/clDNN/src/program.cpp index 13accf3b8a5999..74f07313392fe6 100644 --- a/inference-engine/thirdparty/clDNN/src/program.cpp +++ b/inference-engine/thirdparty/clDNN/src/program.cpp @@ -47,6 +47,7 @@ #include "lstm_gemm_inst.h" #include "mutable_data_inst.h" #include "pooling_inst.h" +#include "border_inst.h" #include "primitive_inst.h" #include "prior_box_inst.h" #include "proposal_inst.h" @@ -534,6 +535,9 @@ void program::pre_optimize_graph(bool is_internal) { // check if there exists some layout incompatibilities and add an reorder node if required apply_opt_pass(); + + // add optimization attributes for onednn primitives + apply_opt_pass(); } void program::post_optimize_graph(bool is_internal) { @@ -1292,6 +1296,7 @@ void program::set_layout_optimizer_attributes(layout_optimizer& lo) { prim.type() != cldnn::input_layout::type_id() && prim.type() != cldnn::softmax::type_id() && prim.type() != cldnn::prior_box::type_id() && + prim.type() != cldnn::border::type_id() && prim.type() != cldnn::resample::type_id() && prim.type() != cldnn::crop::type_id() && prim.type() != cldnn::scale::type_id() && diff --git a/inference-engine/thirdparty/clDNN/src/program_node.cpp b/inference-engine/thirdparty/clDNN/src/program_node.cpp index a37bd13b5ffafc..b2b432e8cfd2f7 100644 --- a/inference-engine/thirdparty/clDNN/src/program_node.cpp +++ b/inference-engine/thirdparty/clDNN/src/program_node.cpp @@ -5,6 +5,14 @@ #include "program_node.h" #include "cldnn/graph/program.hpp" #include "primitive_inst.h" + +#ifdef ENABLE_ONEDNN_FOR_GPU +#include "convolution_inst.h" +#include "quantize_inst.h" +#include "reorder_inst.h" +#include +#endif // ENABLE_ONEDNN_FOR_GPU + #include "to_string_utils.h" #include "json_object.h" #include @@ -280,3 +288,699 @@ bool program_node::need_lockable_memory() const { return need_lockable_mem; } + + /* ----------------------------------------- */ + /* Onednn fused operations integration logic */ + /* ----------------------------------------- */ + +#ifdef ENABLE_ONEDNN_FOR_GPU + +bool program_node::has_out_scales(const std::shared_ptr& attr) { + int mask; + std::vector scales; + attr->get_output_scales(mask, scales); + const auto drfv = reinterpret_cast(DNNL_RUNTIME_F32_VAL); + return !scales.empty() && (reinterpret_cast(scales[0]) == drfv); +} + +dnnl::post_ops program_node::try_optimize_post_ops(dnnl::post_ops& p_ops, const std::shared_ptr& attr, + bool& optimization_is_completed) { + // Create new dnnl::post_ops object which will be filled inside the optimization process + dnnl::post_ops optimized_p_ops; + + // Add new post-op into optimized_p_ops structure + auto add_post_op = [&](onednn_post_op_type type, const dnnl::post_ops& cur_p_ops, dnnl::post_ops& new_p_ops, int idx) { + switch (type) { + case onednn_post_op_type::eltwise_act: + case onednn_post_op_type::eltwise_clip: + case onednn_post_op_type::eltwise_linear: + case onednn_post_op_type::eltwise_round: + { + dnnl::algorithm alg; + float scale, alpha, beta; + cur_p_ops.get_params_eltwise(idx, scale, alg, alpha, beta); + new_p_ops.append_eltwise(scale, alg, alpha, beta); + break; + } + + case onednn_post_op_type::binary_add: + case onednn_post_op_type::binary_mul: + case onednn_post_op_type::binary_max: + case onednn_post_op_type::binary_min: + { + dnnl::algorithm alg; + dnnl::memory::desc desc; + cur_p_ops.get_params_binary(idx, alg, desc); + new_p_ops.append_binary(alg, desc); + break; + } + + case onednn_post_op_type::scale: + { + break; + } + + case onednn_post_op_type::sum: + { + float scale; + dnnl::memory::data_type data_type; + cur_p_ops.get_params_sum(idx, scale, data_type); + new_p_ops.append_sum(scale, data_type); + break; + } + + case onednn_post_op_type::optimized: + case onednn_post_op_type::optimized_sum: + case onednn_post_op_type::optimized_eltwise: + { + // Current operation already has been optimized => don't need extra actions + break; + } + + default: + throw std::runtime_error("Unsupported onednn post-operation type"); + } + }; + + // Check that post-op type is any optimized + auto type_is_any_optimized = [](onednn_post_op_type type) -> bool { + return type == onednn_post_op_type::optimized || type == onednn_post_op_type::optimized_sum || + type == onednn_post_op_type::optimized_eltwise; + }; + + // Check that post-op type is eltwise + auto type_is_eltwise = [](onednn_post_op_type type) -> bool { + return type == onednn_post_op_type::eltwise_round || type == onednn_post_op_type::eltwise_linear || + type == onednn_post_op_type::eltwise_clip || type == onednn_post_op_type::eltwise_act; + }; + + // Check that post-op type is binary_add or binary_mul + auto type_is_binary_add_or_mul = [](onednn_post_op_type type) -> bool { + return type == onednn_post_op_type::binary_add || type == onednn_post_op_type::binary_mul; + }; + + // Simple post-op type checks + auto type_is_optimized = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::optimized; }; + auto type_is_eltwise_linear = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::eltwise_linear; }; + auto type_is_optimized_eltwise = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::optimized_eltwise; }; + auto type_is_binary_add = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::binary_add; }; + auto type_is_binary_mul = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::binary_mul; }; + auto type_is_sum = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::sum; }; + auto type_is_optimized_sum = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::optimized_sum; }; + auto type_is_scale = [](onednn_post_op_type type) -> bool { return type == onednn_post_op_type::scale; }; + + auto& cur_post_ops = get_fused_primitives_onednn(); + + size_t cur_post_op_idx = 1; + size_t prev_post_op_idx = 0; + bool optimization_done = false; + + // Check and update post-op map if we already optimized something + for (size_t post_op_idx = 0; post_op_idx < cur_post_ops.size(); post_op_idx++) { + if (type_is_optimized_sum(cur_post_ops[post_op_idx].op_type)) + cur_post_ops[post_op_idx].op_type = onednn_post_op_type::sum; + else if (type_is_optimized_eltwise(cur_post_ops[post_op_idx].op_type)) + cur_post_ops[post_op_idx].op_type = onednn_post_op_type::eltwise_linear; + else if (type_is_optimized(cur_post_ops[post_op_idx].op_type)) + cur_post_ops.erase(cur_post_ops.begin() + post_op_idx); + } + + // Get post-ops size for current node + auto post_ops_size = cur_post_ops.size(); + + // Try to combine pairs of arithmetic post-ops (adds and muls) into one operation inside this cycle + while (!optimization_done) { + auto cur_type = cur_post_ops[cur_post_op_idx].op_type; + auto prev_type = cur_post_ops[prev_post_op_idx].op_type; + + // Ignore optimized operations for "previous" operation in our operation pair + while (type_is_any_optimized(prev_type) && cur_post_op_idx < post_ops_size - 1) { + prev_post_op_idx++; + cur_post_op_idx++; + prev_type = cur_post_ops[prev_post_op_idx].op_type; + cur_type = cur_post_ops[cur_post_op_idx].op_type; + } + + // Ignore optimized operations for "current" operation in our operation pair + while (type_is_any_optimized(cur_type) && cur_post_op_idx < post_ops_size - 1) { + cur_post_op_idx++; + cur_type = cur_post_ops[cur_post_op_idx].op_type; + } + + auto cur_idx = static_cast(has_out_scales(attr) ? (cur_post_op_idx >= 1 ? cur_post_op_idx - 1 : 0) : cur_post_op_idx); + auto prev_idx = static_cast(has_out_scales(attr) ? (prev_post_op_idx >= 1 ? prev_post_op_idx - 1 : 0) : prev_post_op_idx); + + // If this is the last pair and it's optimized - add the last post-op and go out from the cycle + if (cur_post_op_idx == post_ops_size - 1 && (type_is_any_optimized(cur_type) || type_is_any_optimized(prev_type))) { + if (!type_is_any_optimized(prev_type)) { + add_post_op(prev_type, p_ops, optimized_p_ops, prev_idx); + } + if (!type_is_any_optimized(cur_type)) { + add_post_op(cur_type, p_ops, optimized_p_ops, cur_idx); + } + break; + } + + // Post-ops combinations which can be simplified + auto eltw_and_eltw = type_is_eltwise(cur_type) && type_is_eltwise(prev_type); + auto bin_and_eltw = type_is_binary_add_or_mul(cur_type) && type_is_eltwise_linear(prev_type); + auto eltw_and_bin = type_is_eltwise_linear(cur_type) && type_is_binary_add_or_mul(prev_type); + auto sum_and_eltw = type_is_sum(cur_type) && type_is_eltwise(prev_type); + auto eltw_and_scale = type_is_eltwise_linear(cur_type) && type_is_scale(prev_type); + + auto can_try_optimize = eltw_and_eltw || + bin_and_eltw || + eltw_and_bin || + sum_and_eltw || + eltw_and_scale; + + bool cur_ops_pair_is_optimized = false; + + if (can_try_optimize) { + if (eltw_and_eltw) { + dnnl::algorithm cur_alg, prev_alg; + float cur_scale, prev_scale, cur_alpha, prev_alpha, cur_beta, prev_beta; + + p_ops.get_params_eltwise(prev_idx, prev_scale, prev_alg, prev_alpha, prev_beta); + p_ops.get_params_eltwise(cur_idx, cur_scale, cur_alg, cur_alpha, cur_beta); + + auto eltw_linear_and_eltw_linear = type_is_eltwise_linear(cur_type) && type_is_eltwise_linear(prev_type); + auto eltw_linear_and_eltw_non_linear = type_is_eltwise_linear(cur_type) && !type_is_eltwise_linear(prev_type) && cur_beta == 0; + + // eltwise_linear + eltwise_linear combination can be optimized always + if (eltw_linear_and_eltw_linear) { + dnnl::post_ops eltw_p_op; + float optimized_alpha = cur_alpha * prev_alpha * prev_scale; + float optimized_beta = cur_alpha * prev_beta * prev_scale + cur_beta; + float optimized_scale = cur_scale; + eltw_p_op.append_eltwise(optimized_scale, cur_alg, optimized_alpha, optimized_beta); + + // Combine 2 eltwises into one + add_post_op(cur_type, eltw_p_op, optimized_p_ops, 0); + } else if (eltw_linear_and_eltw_non_linear) { + dnnl::post_ops eltw_p_op; + eltw_p_op.append_eltwise(cur_scale * prev_scale * cur_alpha, prev_alg, prev_alpha, prev_beta); + + // Combine 2 eltwises into one + add_post_op(prev_type, eltw_p_op, optimized_p_ops, 0); + } + + if (eltw_linear_and_eltw_linear || eltw_linear_and_eltw_non_linear) { + // Marked current and previous eltwise operations as 'optimized' (they will be ignored on the next iteration of cycle) + cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized; + cur_post_ops[prev_post_op_idx].op_type = onednn_post_op_type::optimized_eltwise; + + // Set the flag if extra optimizations checking is needed + if (cur_post_op_idx < post_ops_size - 1) { + if (type_is_eltwise_linear(cur_post_ops[cur_post_op_idx + 1].op_type) || + type_is_binary_add_or_mul(cur_post_ops[cur_post_op_idx + 1].op_type) || + type_is_optimized_eltwise(cur_post_ops[cur_post_op_idx + 1].op_type)) { + optimization_is_completed = true; + } + } + + cur_ops_pair_is_optimized = true; + } + } else if (bin_and_eltw) { + dnnl::algorithm alg; + dnnl::memory::desc desc; + float scale, alpha, beta; + + cldnn::program_node& cur_node = get_dependency(cur_post_ops[cur_post_op_idx].mem_dep); + + p_ops.get_params_binary(cur_idx, alg, desc); + p_ops.get_params_eltwise(prev_idx, scale, alg, alpha, beta); + + // Eltwise operations can use runtime non-constant data buffers, so check that memory buffers consist of constant data only + auto bin_ops_can_be_optimized = cur_node.is_type() && cur_node.is_constant() && + cur_node.get_users().size() == 1 && desc.data_type() == dnnl_f32; + + auto bin_add_and_eltw = alpha == 1.0f && scale == 1.0f && type_is_binary_add(cur_type) && bin_ops_can_be_optimized; + auto bin_mul_and_eltw = beta == 0.f && type_is_binary_mul(cur_type) && bin_ops_can_be_optimized; + + if (bin_add_and_eltw || bin_mul_and_eltw) { + memory::ptr cur_bin_mem_ptr = cur_node.as().get_attached_memory_ptr(); + if (cur_bin_mem_ptr == nullptr) + throw std::runtime_error("OneDNN post-ops optimization error: nonexistent node for bin + eltw"); + auto& stream = cur_bin_mem_ptr->get_engine()->get_program_stream(); + mem_lock bin_and_eltw_lock(cur_bin_mem_ptr, stream); + + size_t cur_bin_mem_size = cur_node.get_output_layout().count(); + + // Update all binary coefficients + if (bin_add_and_eltw) { + for (size_t data_idx = 0; data_idx < cur_bin_mem_size; data_idx++) { + bin_and_eltw_lock[data_idx] += beta; + } + } else { + for (size_t data_idx = 0; data_idx < cur_bin_mem_size; data_idx++) { + bin_and_eltw_lock[data_idx] *= alpha * scale; + } + } + + // Marked previous eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle) + cur_post_ops[prev_post_op_idx].op_type = onednn_post_op_type::optimized; + + cur_ops_pair_is_optimized = true; + } + } else if (eltw_and_bin) { + dnnl::algorithm alg; + dnnl::memory::desc desc; + float scale, alpha, beta; + + cldnn::program_node& prev_node = get_dependency(cur_post_ops[prev_post_op_idx].mem_dep); + + p_ops.get_params_eltwise(cur_idx, scale, alg, alpha, beta); + p_ops.get_params_binary(prev_idx, alg, desc); + + // Eltwise operations can use runtime non-constant data buffers, so check that memory buffers consist of constant data only + auto bin_ops_can_be_optimized = prev_node.is_type() && prev_node.is_constant() && + prev_node.get_users().size() == 1 && desc.data_type() == dnnl_f32; + + auto eltw_and_bin_add = alpha == 1.0f && scale == 1.0f && type_is_binary_add(prev_type) && bin_ops_can_be_optimized; + auto eltw_and_bin_mul = beta == 0.f && type_is_binary_mul(prev_type) && bin_ops_can_be_optimized; + + if (eltw_and_bin_add || eltw_and_bin_mul) { + memory::ptr prev_bin_mem_ptr = prev_node.as().get_attached_memory_ptr(); + if (prev_bin_mem_ptr == nullptr) + throw std::runtime_error("OneDNN post-ops optimization error: nonexistent node for eltw + bin"); + auto& stream = prev_bin_mem_ptr->get_engine()->get_program_stream(); + mem_lock eltw_and_bin_lock(prev_bin_mem_ptr, stream); + + size_t prev_bin_mem_size = prev_node.get_output_layout().count(); + + // Update all binary coefficients + if (eltw_and_bin_add) { + for (size_t data_idx = 0; data_idx < prev_bin_mem_size; data_idx++) { + eltw_and_bin_lock[data_idx] += beta; + } + } else { + for (size_t data_idx = 0; data_idx < prev_bin_mem_size; data_idx++) { + eltw_and_bin_lock[data_idx] *= alpha * scale; + } + } + + // Marked current eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle) + cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized; + + cur_ops_pair_is_optimized = true; + } + } else if (sum_and_eltw) { + dnnl::algorithm alg; + float sum_scale, eltw_scale, alpha, beta; + dnnl::memory::data_type data_type; + + dnnl::algorithm next_alg; + float next_scale, next_alpha, next_beta; + size_t next_idx = cur_idx + 1; + size_t next_post_op_idx = cur_post_op_idx + 1; + + bool can_optimize_eltw_and_sum = false; + + if (cur_post_op_idx < post_ops_size - 1) { + auto next_type = cur_post_ops[next_post_op_idx].op_type; + if (type_is_eltwise_linear(next_type)) { + p_ops.get_params_eltwise(next_idx, next_scale, next_alg, next_alpha, next_beta); + + if (next_beta == 0) + can_optimize_eltw_and_sum = true; + } + } + + // Try to optimize eltwise (any) + sum + eltwise_linear (with beta = 0) chain of operations + if (can_optimize_eltw_and_sum) { + p_ops.get_params_sum(cur_idx, sum_scale, data_type); + p_ops.get_params_eltwise(prev_idx, eltw_scale, alg, alpha, beta); + + dnnl::post_ops eltw_p_op_prev, sum_p_op; + + eltw_p_op_prev.append_eltwise(eltw_scale * next_alpha * next_scale, alg, alpha, beta); + sum_p_op.append_sum(sum_scale * next_alpha, data_type); + + add_post_op(prev_type, eltw_p_op_prev, optimized_p_ops, 0); + add_post_op(cur_type, sum_p_op, optimized_p_ops, 0); + + // Marked current, previous and next operations as 'optimized' (they will be ignored on the next iteration of cycle) + cur_post_ops[prev_post_op_idx].op_type = onednn_post_op_type::optimized_eltwise; + cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized_sum; + cur_post_ops[next_post_op_idx].op_type = onednn_post_op_type::optimized; + + // Set the flag if extra optimizations checking is needed + if (next_post_op_idx < post_ops_size - 1) { + if (type_is_eltwise_linear(cur_post_ops[next_post_op_idx + 1].op_type) || + type_is_optimized_eltwise(cur_post_ops[next_post_op_idx + 1].op_type)) { + optimization_is_completed = true; + } + } + + cur_ops_pair_is_optimized = true; + } + } else if (eltw_and_scale) { + dnnl::algorithm alg; + float eltw_scale, alpha, beta; + + cldnn::program_node& prev_node = get_dependency(cur_post_ops[prev_post_op_idx].mem_dep); + + p_ops.get_params_eltwise(cur_idx, eltw_scale, alg, alpha, beta); + + // Eltwise can be inserted into the output_scale if cur_beta is equal to 0.f + if (beta == 0.f && prev_node.get_output_layout().data_type == data_types::f32) { + memory::ptr prev_scale_mem_ptr = prev_node.as().get_attached_memory_ptr(); + if (prev_scale_mem_ptr == nullptr) + throw std::runtime_error("OneDNN post-ops optimization error: nonexistent node for eltw + scale"); + auto& stream = prev_scale_mem_ptr->get_engine()->get_program_stream(); + mem_lock eltw_and_scale_lock(prev_scale_mem_ptr, stream); + + size_t prev_scale_mem_size = prev_node.get_output_layout().count(); + + // Update all scale coefficients + for (size_t data_idx = 0; data_idx < prev_scale_mem_size; data_idx++) { + eltw_and_scale_lock[data_idx] *= alpha * eltw_scale; + } + + // Marked current eltwise operation as 'optimized' (it will be ignored on the next iteration of cycle) + cur_post_ops[cur_post_op_idx].op_type = onednn_post_op_type::optimized; + + cur_ops_pair_is_optimized = true; + } + } + } + + // If no optimizations have been applied then copy post-op info into the new optimized_p_ops structure + if (!(has_out_scales(attr) && prev_post_op_idx == 0) && !cur_ops_pair_is_optimized) { + add_post_op(prev_type, p_ops, optimized_p_ops, prev_idx); + } + + if (cur_post_op_idx == post_ops_size - 1 && !cur_ops_pair_is_optimized) { + add_post_op(cur_type, p_ops, optimized_p_ops, cur_idx); + optimization_done = true; + } else if (cur_post_ops[cur_post_op_idx].op_type != onednn_post_op_type::optimized) { + cur_post_op_idx++; + prev_post_op_idx++; + } + } + + optimization_is_completed = !optimization_is_completed; + + add_onednn_fused_primitives(cur_post_ops); + + return optimized_p_ops; +} + + +void program_node::init_onednn_primitive_attributes() { + const std::vector& cldnn_post_ops = get_fused_primitives(); + auto attrs = std::make_shared(); + dnnl::post_ops post_ops; + size_t memory_offset = 0; + + // Create onednn post-ops list related to the current node + std::vector fused_ops; + + // Added this for debug purposes only + size_t empty_mem = 0xff; + + // Add information about post-operation into the list, update indices + auto update_onednn_post_op_list = [&](onednn_post_op_type type, size_t m_dep) { + fused_primitive_desc_onednn cur_op_desc = { type, memory_offset, m_dep }; + fused_ops.push_back(cur_op_desc); + + auto has_memory_buffers = type == onednn_post_op_type::binary_add || + type == onednn_post_op_type::binary_mul || + type == onednn_post_op_type::binary_max || + type == onednn_post_op_type::binary_min || + type == onednn_post_op_type::scale || + type == onednn_post_op_type::sum; + if (has_memory_buffers) + memory_offset++; + }; + + for (size_t idx = 0; idx < cldnn_post_ops.size(); idx++) { + auto node = cldnn_post_ops[idx].node; + + if (node->is_type()) { + auto fused_desc = node->as().get_primitive(); + dnnl::algorithm alg = onednn::convert_activation_func(fused_desc->activation_function); + post_ops.append_eltwise(1.0f, alg, fused_desc->additional_params.a, fused_desc->additional_params.b); + update_onednn_post_op_list(onednn_post_op_type::eltwise_act, empty_mem); + } else if (node->is_type()) { + auto& e_node = node->as(); + auto dep_idx = cldnn_post_ops[idx].dep_start_idx; + auto in = get_dependency(dep_idx).get_output_layout(); + + if (e_node.get_primitive()->mode == eltwise_mode::sum) { + if (e_node.get_primitive()->needs_onednn_sum_post_op(in)) { + post_ops.append_sum(1.0f, onednn::convert_data_type(in.data_type)); + update_onednn_post_op_list(onednn_post_op_type::sum, dep_idx); + } else { + dnnl::memory::desc in_desc = onednn::layout_to_memory_desc(in, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_add, in_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx); + } + } else { + if (in.size.spatial[0] > 1 || in.size.spatial[1] > 1 || in.size.batch[0] > 1) + throw std::runtime_error("Unsupported eltwise mode for fused onednn op"); + if (idx == 0 && !has_out_scales(attrs)) { + int mask = in.count() > 1 ? 2 : 0; + attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL}); + update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx); + } else { + dnnl::memory::desc in_desc = onednn::layout_to_memory_desc(in, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_mul, in_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx); + } + } + } else if (node->is_type()) { + auto& q_node = node->as(); + auto dep_idx = cldnn_post_ops[idx].dep_start_idx; + + // ********************************* Common case with output range usage ********************************* // + if (q_node.get_per_tensor_output_range() && q_node.get_output_lo_val() < q_node.get_output_hi_val()) { + // 1. pre-scale & pre-shift + { + if (q_node.get_per_tensor_input_scale() && q_node.get_per_tensor_input_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), q_node.get_input_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + if (q_node.get_per_tensor_input_scale()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), 0.0f); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto in_scale = get_dependency(dep_idx++).get_output_layout(); + if (idx == 0 && !has_out_scales(attrs) && in_scale.data_type == data_types::f32 && + is_type() && + !data_type_traits::is_floating_point(get_dependency(0).get_output_layout().data_type)) { + int mask = in_scale.count() > 1 ? 2 : 0; + attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL}); + update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx - 1); + } else { + dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); + } + } + + if (q_node.get_need_pre_shift()) { + if (q_node.get_per_tensor_input_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_input_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto in_shift = get_dependency(dep_idx++).get_output_layout(); + dnnl::memory::desc in_shift_desc = onednn::layout_to_memory_desc(in_shift, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_add, in_shift_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); + } + } + } + } + + // 2. round + auto out_dt = cldnn_post_ops[idx].output_layout.data_type; + { + bool output_type_is_int8 = out_dt == data_types::u8 || out_dt == data_types::i8; + if (!output_type_is_int8) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_round, 0.0f, 0.0f); + update_onednn_post_op_list(onednn_post_op_type::eltwise_round, empty_mem); + } + } + + // 3. post-scale & post-shift + { + if (q_node.get_need_post_scale() && q_node.get_need_post_shift() && + q_node.get_per_tensor_output_scale() && q_node.get_per_tensor_output_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), q_node.get_output_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + if (q_node.get_need_post_scale()) { + if (q_node.get_per_tensor_output_scale()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), 0.0f); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto out_scale = get_dependency(dep_idx++).get_output_layout(); + dnnl::memory::desc out_scale_desc = onednn::layout_to_memory_desc(out_scale, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_mul, out_scale_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); + } + } + + if (q_node.get_need_post_shift()) { + if (q_node.get_per_tensor_output_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_output_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto out_shift = get_dependency(dep_idx++).get_output_layout(); + dnnl::memory::desc out_shift_desc = onednn::layout_to_memory_desc(out_shift, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_add, out_shift_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); + } + } + } + } + + // 4. clamp + { + if (q_node.get_need_clamp()) { + float out_lo = q_node.get_need_min_clamp() ? q_node.get_output_lo_val() : data_type_traits::min(out_dt); + float out_hi = q_node.get_need_max_clamp() ? q_node.get_output_hi_val() : data_type_traits::max(out_dt); + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_clip, out_lo, out_hi); + update_onednn_post_op_list(onednn_post_op_type::eltwise_clip, empty_mem); + } + } + // ********************************* Rare case with input range usage ********************************* // + } else { + // 1. clamp + { + if (q_node.get_need_clamp()) { + auto in_lo = get_dependency(dep_idx++).get_output_layout(); + auto in_hi = get_dependency(dep_idx++).get_output_layout(); + dnnl::algorithm clamp_max = dnnl::algorithm::binary_max; + dnnl::algorithm clamp_min = dnnl::algorithm::binary_min; + dnnl::memory::desc in_lo_desc = onednn::layout_to_memory_desc(in_lo, dnnl::memory::format_tag::ab, true); + dnnl::memory::desc in_hi_desc = onednn::layout_to_memory_desc(in_hi, dnnl::memory::format_tag::ab, true); + + post_ops.append_binary(clamp_max, in_lo_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_max, dep_idx - 2); + post_ops.append_binary(clamp_min, in_hi_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_min, dep_idx - 1); + } + } + + // 2. pre-scale & pre-shift + { + if (q_node.get_per_tensor_input_scale() && q_node.get_per_tensor_input_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), q_node.get_input_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + if (q_node.get_per_tensor_input_scale()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_input_scale_val(), 0.0f); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto in_scale = get_dependency(dep_idx++).get_output_layout(); + if (idx == 0 && !q_node.get_need_clamp() && !has_out_scales(attrs) && in_scale.data_type == data_types::f32 && + is_type() && + !data_type_traits::is_floating_point(get_dependency(0).get_output_layout().data_type)) { + int mask = in_scale.count() > 1 ? 2 : 0; + attrs->set_output_scales(mask, {DNNL_RUNTIME_F32_VAL}); + update_onednn_post_op_list(onednn_post_op_type::scale, dep_idx - 1); + } else { + dnnl::memory::desc in_scale_desc = onednn::layout_to_memory_desc(in_scale, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_mul, in_scale_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); + } + } + + if (q_node.get_need_pre_shift()) { + if (q_node.get_per_tensor_input_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_input_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto in_shift = get_dependency(dep_idx++).get_output_layout(); + dnnl::memory::desc in_shift_desc = onednn::layout_to_memory_desc(in_shift, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_add, in_shift_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); + } + } + } + } + + // 3. round + { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_round, 0.0f, 0.0f); + update_onednn_post_op_list(onednn_post_op_type::eltwise_round, empty_mem); + } + + // 4. post-scale & post-shift + { + if (q_node.get_need_post_scale() && q_node.get_need_post_shift() && + q_node.get_per_tensor_output_scale() && q_node.get_per_tensor_output_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), q_node.get_output_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + if (q_node.get_need_post_scale()) { + if (q_node.get_per_tensor_output_scale()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, q_node.get_output_scale_val(), 0.0f); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto out_scale = get_dependency(dep_idx++).get_output_layout(); + dnnl::memory::desc out_scale_desc = onednn::layout_to_memory_desc(out_scale, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_mul, out_scale_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_mul, dep_idx - 1); + } + } + + if (q_node.get_need_post_shift()) { + if (q_node.get_per_tensor_output_shift()) { + post_ops.append_eltwise(1.0f, dnnl::algorithm::eltwise_linear, 1.0f, q_node.get_output_shift_val()); + update_onednn_post_op_list(onednn_post_op_type::eltwise_linear, empty_mem); + } else { + auto out_shift = get_dependency(dep_idx++).get_output_layout(); + dnnl::memory::desc out_shift_desc = onednn::layout_to_memory_desc(out_shift, dnnl::memory::format_tag::ab, true); + post_ops.append_binary(dnnl::algorithm::binary_add, out_shift_desc); + update_onednn_post_op_list(onednn_post_op_type::binary_add, dep_idx - 1); + } + } + } + } + } + } else if (node->is_type()) { + continue; + } else { + throw std::runtime_error("Unsupported fused op of " + node->get_primitive()->type_string() + " type for oneDNN primitive"); + } + } + + if (cldnn_post_ops.size() && get_fused_activations_funcs().size()) + throw std::runtime_error("Unsupported mix of fused ops and activations"); + + for (size_t i = 0; i < get_fused_activations_funcs().size(); i++) { + auto activation_type = get_fused_activations_funcs()[i]; + auto params = get_fused_activations_params()[i]; + dnnl::algorithm alg = onednn::convert_activation_func(activation_type); + post_ops.append_eltwise(1.0f, alg, params.a, params.b); + update_onednn_post_op_list(onednn_post_op_type::eltwise_act, empty_mem); + } + + // Trying to optimize more than 1 post-ops + if (fused_ops.size() > 1) { + dnnl::post_ops optimized_post_ops = post_ops; + bool optimization_is_finished = false; + + add_onednn_fused_primitives(fused_ops); + + // Trying to combine multiplications and additions which are placed one after another. + // We do it in the cycle because some optimization cases can be simplified again from time to time + do { + optimized_post_ops = try_optimize_post_ops(optimized_post_ops, attrs, optimization_is_finished); + } while (!optimization_is_finished); + + attrs->set_post_ops(optimized_post_ops); + } else { + // Set post-ops without any optimizations + add_onednn_fused_primitives(fused_ops); + attrs->set_post_ops(post_ops); + } + + add_onednn_attrs(attrs); +} + +#endif // ENABLE_ONEDNN_FOR_GPU diff --git a/inference-engine/thirdparty/clDNN/tests/CMakeLists.txt b/inference-engine/thirdparty/clDNN/tests/CMakeLists.txt index 02189c28ffc01c..ca83c08ffa955d 100644 --- a/inference-engine/thirdparty/clDNN/tests/CMakeLists.txt +++ b/inference-engine/thirdparty/clDNN/tests/CMakeLists.txt @@ -99,6 +99,11 @@ if(COMMAND set_ie_threading_interface_for) set_ie_threading_interface_for("${CLDNN_BUILD__PROJ}") endif() +# Workaround to avoid warnings during LTO build +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set_target_properties("${CLDNN_BUILD__PROJ}" PROPERTIES LINK_FLAGS_RELEASE "-Wno-error=maybe-uninitialized -Wno-maybe-uninitialized") +endif() + set_property(TARGET "${CLDNN_BUILD__PROJ}" PROPERTY PROJECT_LABEL "${CLDNN_BUILD__PROJ_LABEL}") # Set library dependencies diff --git a/inference-engine/thirdparty/clDNN/tests/test_cases/border_gpu_test.cpp b/inference-engine/thirdparty/clDNN/tests/test_cases/border_gpu_test.cpp index df8a8d47c203a3..d2b3daf18685a7 100644 --- a/inference-engine/thirdparty/clDNN/tests/test_cases/border_gpu_test.cpp +++ b/inference-engine/thirdparty/clDNN/tests/test_cases/border_gpu_test.cpp @@ -106,6 +106,84 @@ TEST(border_gpu, basic_yxfb_0x0x1x2_0x0x3x4_border_constant) { } } +TEST(border_gpu, basic_fsv16_0x0x1x2_0x0x3x4_border_constant) { + // Input (XY) : 4x3 + // Output (XY): 10x7 + + constexpr auto in_size_b = 1; + constexpr auto in_size_f = 1; + constexpr auto in_size_y = 3; + constexpr auto in_size_x = 4; + + constexpr auto blt_size_b = 0; + constexpr auto blt_size_f = 0; + constexpr auto blt_size_y = 1; + constexpr auto blt_size_x = 2; + + constexpr auto brb_size_b = 0; + constexpr auto brb_size_f = 0; + constexpr auto brb_size_y = 3; + constexpr auto brb_size_x = 4; + + constexpr auto out_size_b = in_size_b + blt_size_b + brb_size_b; + constexpr auto out_size_f = in_size_f + blt_size_f + brb_size_f; + constexpr auto out_size_y = in_size_y + blt_size_y + brb_size_y; + constexpr auto out_size_x = in_size_x + blt_size_x + brb_size_x; + + auto& engine = get_test_engine(); + auto input = engine.allocate_memory({data_types::f32, format::yxfb, {in_size_b, in_size_f, in_size_x, in_size_y}}); + + topology topology; + topology.add( + input_layout("input", input->get_layout()) + ); + topology.add( + reorder("border_input", "input", cldnn::format::b_fs_yx_fsv16, cldnn::data_types::f32), + border("border", "border_input", + {blt_size_b, blt_size_f, blt_size_x, blt_size_y}, + {brb_size_b, brb_size_f, brb_size_x, brb_size_y}, + border_type::constant, 0.0f), + reorder("output", "border", cldnn::format::yxfb, cldnn::data_types::f32) + ); + + std::vector input_data = { + 1, -2, 3, -4, + 5, 6, 7, 8, + -10, 12, 13, -13, + }; + std::vector out_data = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, -2, 3, -4, 0, 0, 0, 0, + 0, 0, 5, 6, 7, 8, 0, 0, 0, 0, + 0, 0, -10, 12, 13, -13, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + set_values(input, input_data); + + cldnn::network network(engine, topology); + network.set_input_data("input", input); + auto outputs = network.execute(); + + auto output = outputs.at("output").get_memory(); + cldnn::mem_lock output_ptr(output, get_test_stream()); + + ASSERT_EQ(out_data.size(), static_cast(out_size_b * out_size_f * out_size_y * out_size_x)); + + for (auto b = 0; b < out_size_b; ++b) { // B + for (auto f = 0; f < out_size_f; ++f) { // F + for (auto y = 0; y < out_size_y; ++y) { // Y + for (auto x = 0; x < out_size_x; ++x) { // X + auto output_off = ((y * out_size_x + x) * out_size_f + f) * out_size_b + b; // YXFB + + EXPECT_EQ(output_ptr[output_off], out_data[output_off]); + } + } + } + } +} + TEST(border_gpu, basic_bfzyx_0x0x1x01_0x0x0x0x3_border_constant) { constexpr auto in_size_b = 1; diff --git a/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp b/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp index 70173fc326fde4..c99c788fa76a3d 100644 --- a/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp +++ b/inference-engine/thirdparty/clDNN/tests/test_cases/fusings_gpu_test.cpp @@ -545,6 +545,7 @@ class ConvEltwTest : public ::BaseFusingTest { #define CASE_CONV_U8S8_12 {32, 15, 5, 5}, {32, 30, 3, 3}, {1, 1, 3, 3}, tensor{1}, tensor{0}, tensor{1}, 1, data_types::u8, format::bfyx, data_types::i8, format::bfyx, data_types::f32, format::bfyx #define CASE_CONV_U8S8_13 {32, 16, 4, 5}, {32, 32, 4, 5}, {1, 1, 1, 1}, tensor{1}, tensor{0}, tensor{1}, 1, data_types::u8, format::bfyx, data_types::i8, format::bfyx, data_types::f32, format::bfyx #define CASE_CONV_U8S8_14 {32, 17, 4, 5}, {32, 17, 4, 5}, {1, 1, 3, 3}, tensor{1}, tensor{0, 0, -1, -1, 0, 0}, tensor{1}, 17, data_types::u8, format::bfyx, data_types::i8, format::goiyx, data_types::f32, format::bfyx +#define CASE_CONV_U8S8_15 {1, 15, 2, 2}, {1, 30, 1, 1}, {1, 1, 3, 3}, tensor{1}, tensor{0}, tensor{1}, 1, data_types::u8, format::bfyx, data_types::i8, format::bfyx, data_types::f32, format::bfyx #define CASE_CONV_S8S8_1 {1, 15, 4, 5}, {1, 30, 2, 3}, {1, 1, 3, 3}, tensor{1}, tensor{0}, tensor{1}, 1, data_types::i8, format::bfyx, data_types::i8, format::bfyx, data_types::f32, format::bfyx #define CASE_CONV_S8S8_2 {1, 15, 5, 5}, {1, 30, 3, 3}, {1, 1, 3, 3}, tensor{1}, tensor{0}, tensor{1}, 1, data_types::i8, format::bfyx, data_types::i8, format::bfyx, data_types::f32, format::bfyx @@ -9434,6 +9435,47 @@ INSTANTIATE_TEST_SUITE_P(fusings_gpu, conv_int8_scale_shift_swish_onednn, bc_test_params{CASE_CONV_S8S8_15, 2, 7}, })); +class conv_int8_eltwise_scale_onednn : public ConvFusingTestOneDNN {}; +TEST_P(conv_int8_eltwise_scale_onednn, u8_eltwise_prod_out_reuse) { + auto p = GetParam(); + + create_topologies(input_layout("input", get_input_layout(p)), + data("weights", get_mem(get_weights_layout(p), -2, 2)), + data("bias", get_mem(get_bias_layout(p))), + data("sum_data", get_mem(get_per_channel_layout(p), 1.0f/p.kernel.count())), + data("scale_data", get_mem(get_per_channel_layout(p), 1.0f/p.kernel.count())), + convolution("conv_prim", "input", {"weights"}, {"bias"}, p.groups, p.stride, p.pad, p.dilation, p.out_shape, data_types::f32, false), + eltwise("sum", {"conv_prim", "sum_data"}, eltwise_mode::sum, data_types::f32), + eltwise("scale", {"sum", "scale_data"}, eltwise_mode::prod, data_types::f32), + crop("crop", "scale", get_output_layout(p).size, {0, 0, 0, 0}), + reorder("reorder_bfyx", "crop", p.default_format, data_types::f32) + ); + + tolerance = 1.f; + + auto input_prim = get_mem(get_input_layout(p)); + + auto forcing_format = p.input_format; + implementation_desc conv_impl = { forcing_format, "", impl_types::onednn }; + bo_fused.set_option(build_option::force_implementations({ {"conv_prim", conv_impl} })); + + network network_not_fused(this->engine, this->topology_non_fused, bo_not_fused); + network network_fused(this->engine, this->topology_fused, bo_fused); + network_fused.set_input_data("input", input_prim); + network_not_fused.set_input_data("input", input_prim); + + // First network.execute() call + compare(network_not_fused, network_fused, p); + // Second network.execute() call to make sure that scales have not been wrongly overwritten within first iteration + // and don't affect final result of second iteration + compare(network_not_fused, network_fused, p); +} + +INSTANTIATE_TEST_SUITE_P(fusings_gpu, conv_int8_eltwise_scale_onednn, + ::testing::ValuesIn(std::vector{ + bc_test_params{CASE_CONV_U8S8_15, 2, 5}, + })); + /* ----------------------------------------------------------------------------------------------------- */ /* ------------------------------ OneDNN post-ops cases with optimizations ----------------------------- */ /* ----------------------------------------------------------------------------------------------------- */ diff --git a/inference-engine/thirdparty/clDNN/tests/test_cases/pooling_gpu_test.cpp b/inference-engine/thirdparty/clDNN/tests/test_cases/pooling_gpu_test.cpp index 8650127f4085ed..ac5629a8f01c3d 100644 --- a/inference-engine/thirdparty/clDNN/tests/test_cases/pooling_gpu_test.cpp +++ b/inference-engine/thirdparty/clDNN/tests/test_cases/pooling_gpu_test.cpp @@ -2719,7 +2719,7 @@ INSTANTIATE_TEST_SUITE_P( smoke_low_precision_2d_spatial, pooling_random_test, testing::Combine(testing::Values(1, 2), - testing::Values(3, 8, 64), + testing::Values(3, 8, 19, 64), testing::Values(std::tuple(12, 12, 1), std::tuple(24, 24, 1)), testing::Values(std::tuple(4, 4, 1), std::tuple(2, 2, 1)), testing::Values(std::tuple(2, 2, 1)), @@ -2736,7 +2736,7 @@ INSTANTIATE_TEST_SUITE_P( smoke_low_precision_3d_spatial, pooling_random_test, testing::Combine(testing::Values(1, 2), - testing::Values(3, 8, 64), + testing::Values(3, 8, 27, 64), testing::Values(std::tuple(12, 12, 12), std::tuple(24, 24, 24)), testing::Values(std::tuple(4, 4, 4), std::tuple(2, 2, 2)), testing::Values(std::tuple(2, 2, 2)), diff --git a/inference-engine/thirdparty/movidius/XLink/CMakeLists.txt b/inference-engine/thirdparty/movidius/XLink/CMakeLists.txt index bf513666b7d6da..ca5bc6a001562b 100644 --- a/inference-engine/thirdparty/movidius/XLink/CMakeLists.txt +++ b/inference-engine/thirdparty/movidius/XLink/CMakeLists.txt @@ -19,11 +19,10 @@ if(NOT WIN32) ${LIBUSB_LIBRARY}) endif() -target_include_directories(${TARGET_NAME} - PUBLIC - ${XLINK_INCLUDE} - PRIVATE - ${XLINK_PLATFORM_INCLUDE}) +target_include_directories(${TARGET_NAME} PRIVATE ${XLINK_PLATFORM_INCLUDE}) +foreach(dir IN LISTS XLINK_INCLUDE) + target_include_directories(${TARGET_NAME} PUBLIC $) +endforeach() target_compile_definitions(${TARGET_NAME} PRIVATE @@ -42,3 +41,4 @@ endif() set_property(TARGET ${TARGET_NAME} PROPERTY C_STANDARD 99) openvino_developer_export_targets(COMPONENT inference_engine_vpu TARGETS ${TARGET_NAME}) +ov_install_static_lib(${TARGET_NAME} myriad) diff --git a/inference-engine/thirdparty/movidius/mvnc/CMakeLists.txt b/inference-engine/thirdparty/movidius/mvnc/CMakeLists.txt index 94d461ab911799..f62a65ea8390c6 100644 --- a/inference-engine/thirdparty/movidius/mvnc/CMakeLists.txt +++ b/inference-engine/thirdparty/movidius/mvnc/CMakeLists.txt @@ -10,15 +10,14 @@ include(${XLINK_DIR}/XLink.cmake) file(GLOB_RECURSE MVNC_SOURCES "include/*" "src/*") -set(WATCHDOG_INCLUDE - ${CMAKE_CURRENT_SOURCE_DIR}/include/watchdog/) +set(WATCHDOG_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include/watchdog/) add_library(${TARGET_NAME} STATIC ${MVNC_SOURCES}) target_include_directories(${TARGET_NAME} PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/include" - ${WATCHDOG_INCLUDE} + $ + $ PRIVATE ${XLINK_INCLUDE} ${XLINK_PLATFORM_INCLUDE}) @@ -74,6 +73,7 @@ if(NOT WIN32) endif() openvino_developer_export_targets(COMPONENT inference_engine_vpu TARGETS ${TARGET_NAME}) +ov_install_static_lib(${TARGET_NAME} myriad) if(ENABLE_TESTS AND ENABLE_MYRIAD_MVNC_TESTS) add_subdirectory(tests) diff --git a/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c b/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c index de5d39bb7c80e5..d91cd98f8a0694 100644 --- a/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c +++ b/inference-engine/thirdparty/movidius/mvnc/src/mvnc_api.c @@ -103,7 +103,11 @@ static int global_lock_fd = -1; #define STRINGIFY(_text) #_text #define CASE(entry) case entry: return STRINGIFY(entry); - +#define FREE_AND_NULL(fDynMem, fPointer, sDynMem, sPointer) \ + free(fDynMem); \ + fPointer = NULL; \ + free(sDynMem); \ + sPointer = NULL // To suppress warning in the macro below #if defined __GNUC__ || defined __clang__ @@ -2199,10 +2203,7 @@ ncStatus_t ncGraphDestroy(struct ncGraphHandle_t ** graphHandle) CHECK_HANDLE_CORRECT_WINFO(g, MVLOG_ERROR, "Graph handle is corrupt or has been destroyed"); if (g->state == NC_GRAPH_CREATED || g->state == NC_GRAPH_DEALLOCATED) { - free(g); - gh->private_data = NULL; - free(gh); - *graphHandle = NULL; + FREE_AND_NULL(g, gh->private_data, gh, *graphHandle); return NC_OK; } GLOBAL_LOCK(); @@ -2220,28 +2221,24 @@ ncStatus_t ncGraphDestroy(struct ncGraphHandle_t ** graphHandle) cmd.id = g->id; CHECK_MUTEX_SUCCESS(pthread_mutex_lock(&d->graph_stream_m)); rc = trySendCommand(d->graph_monitor_stream_id, &cmd, sizeof(cmd)); - if(rc != 0){ - CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->graph_stream_m)); - return rc; - } - if (checkGraphMonitorResponse(d->graph_monitor_stream_id)) { - CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->graph_stream_m)); - return NC_ERROR; + if (rc != 0){ + mvLog(MVLOG_WARN, "can't send command\n"); + rc = NC_ERROR; + } else if (checkGraphMonitorResponse(d->graph_monitor_stream_id)) { + mvLog(MVLOG_WARN, "myriad NACK\n"); + rc = NC_ERROR; } XLinkCloseStream(g->graph_stream_id); CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->graph_stream_m)); CHECK_MUTEX_SUCCESS(pthread_mutex_lock(&d->dev_data_m)); if (deallocateGraph(gh->private_data)) { mvLog(MVLOG_ERROR, "This graph has already been destroyed"); - CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->dev_data_m)); - return NC_INVALID_PARAMETERS; + rc = NC_INVALID_PARAMETERS; } CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->dev_data_m)); - free(g); - gh->private_data = NULL; - free(gh); - *graphHandle = NULL; - return NC_OK; + FREE_AND_NULL(g, gh->private_data, gh, *graphHandle); + + return rc; } ncStatus_t ncGraphSetOption(struct ncGraphHandle_t * graphHandle, @@ -3021,10 +3018,6 @@ ncStatus_t ncFifoAllocate(struct ncFifoHandle_t * fifoHandle, handle->datasize = handle->host_tensor_desc.totalSize; - if (d->fifos) - handle->next = d->fifos; - d->fifos = handle; - bufferAllocateCommand_t cmd; cmd.type = GRAPH_BUFFER_ALLOCATE_CMD; struct tensorDescriptor_t privateDesc; @@ -3077,6 +3070,10 @@ ncStatus_t ncFifoAllocate(struct ncFifoHandle_t * fifoHandle, mvLog(MVLOG_ERROR, "myriad NACK\n"); return NC_ERROR; } + if (d->fifos) + handle->next = d->fifos; + d->fifos = handle; + CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->graph_stream_m)); handle->state = NC_FIFO_ALLOCATED; @@ -3094,7 +3091,7 @@ ncStatus_t ncFifoDestroy(struct ncFifoHandle_t ** fifoHandle) } struct _fifoPrivate_t *handle = fh->private_data; - + ncStatus_t rc = NC_OK; if (handle->state == NC_FIFO_CREATED || handle->state == NC_FIFO_DEALLOCATED) { pthread_mutex_t * fifo_mutex = &fh->private_data->fifo_mutex; #if !(defined(_WIN32) || defined(_WIN64)) @@ -3116,18 +3113,14 @@ ncStatus_t ncFifoDestroy(struct ncFifoHandle_t ** fifoHandle) CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(fifo_mutex)); CHECK_MUTEX_SUCCESS(pthread_mutex_destroy(fifo_mutex)); - free(fh->private_data); - fh->private_data = NULL; - - free(fh); - *fifoHandle = NULL; + FREE_AND_NULL(fh->private_data, fh->private_data, fh, *fifoHandle); return NC_OK; } if (!findFifo(handle)) { mvLog(MVLOG_ERROR, "fifo handle seems to be corrupt or has been destroyed"); - return NC_INVALID_HANDLE; + rc = NC_INVALID_HANDLE; } //clean up fifo /*if (fifoReadAccess(handle)) { @@ -3146,11 +3139,10 @@ ncStatus_t ncFifoDestroy(struct ncFifoHandle_t ** fifoHandle) if (XLinkWriteData(handle->streamId, (uint8_t *) & msg, sizeof(msg)) != 0) { mvLog(MVLOG_ERROR, "Failed to write to fifo before deleting it!"); - return NC_ERROR; + rc = NC_ERROR; } } - ncStatus_t rc = NC_OK; graphCommonCommand_t cmd; cmd.type = GRAPH_BUFFER_DEALLOCATE_CMD; cmd.id = handle->id; @@ -3158,30 +3150,24 @@ ncStatus_t ncFifoDestroy(struct ncFifoHandle_t ** fifoHandle) struct _devicePrivate_t *d = handle->dev; CHECK_MUTEX_SUCCESS(pthread_mutex_lock(&d->graph_stream_m)); rc = trySendCommand(d->graph_monitor_stream_id, &cmd, sizeof(cmd)); - if(rc != 0){ - CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->graph_stream_m)); + if (rc != 0) { mvLog(MVLOG_WARN, "can't send command\n"); - return rc; - } - if (checkGraphMonitorResponse(d->graph_monitor_stream_id)) { - CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->graph_stream_m)); + rc = NC_ERROR; + } else if (checkGraphMonitorResponse(d->graph_monitor_stream_id)) { mvLog(MVLOG_WARN, "myriad NACK\n"); - return NC_ERROR; + rc = NC_ERROR; } CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->graph_stream_m)); CHECK_MUTEX_SUCCESS(pthread_mutex_lock(&d->dev_data_m)); if (deallocateFifo(handle)) { - CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->dev_data_m)); - return NC_INVALID_PARAMETERS; + mvLog(MVLOG_WARN, "failed deallocateFifo\n"); + rc = NC_INVALID_PARAMETERS; } CHECK_MUTEX_SUCCESS(pthread_mutex_unlock(&d->dev_data_m)); - free(fh->private_data); - fh->private_data = NULL; - free(fh); - *fifoHandle = NULL; - return NC_OK; + FREE_AND_NULL(fh->private_data, fh->private_data, fh, *fifoHandle); + return rc; } diff --git a/licensing/onednn_third-party-programs.txt b/licensing/onednn_third-party-programs.txt index 5bfd9c6864a894..0fed79906332f4 100644 --- a/licensing/onednn_third-party-programs.txt +++ b/licensing/onednn_third-party-programs.txt @@ -102,9 +102,9 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -3. Instrumentation and Tracing Technology API (src/cpu/jit_utils/jitprofiling/) -Copyright (c) 2011, Intel Corporation -All rights reserved. +3. Instrumentation and Tracing Technology API (src/common/ittnotify/) +Copyright (c) 2011, Intel Corporation. All rights reserved. +Copyright (c) 2005-2014 Intel Corporation. All rights reserved. 3-Clause BSD License @@ -168,14 +168,111 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -5. Font Roboto (doc/assets/fonts/Roboto*) -Copyright 2011 The Roboto Project Authors (https://github.com/google/roboto) +------------------------------------------------------------------------------ + +The following individuals and institutions are among the Contributors: + +* Aaron C. Meadows +* Adriaan de Groot +* Aleksey Avdeev +* Alexander Neundorf +* Alexander Smorkalov +* Alexey Sokolov +* Alex Merry +* Alex Turbov +* Andreas Pakulat +* Andreas Schneider +* André Rigland Brodtkorb +* Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf +* Benjamin Eikel +* Bjoern Ricks +* Brad Hards +* Christopher Harvey +* Christoph Grüninger +* Clement Creusot +* Daniel Blezek +* Daniel Pfeifer +* Enrico Scholz +* Eran Ifrah +* Esben Mose Hansen, Ange Optimization ApS +* Geoffrey Viola +* Google Inc +* Gregor Jasny +* Helio Chissini de Castro +* Ilya Lavrenov +* Insight Software Consortium +* Jan Woetzel +* Julien Schueller +* Kelly Thompson +* Konstantin Podsvirov +* Laurent Montel +* Mario Bensi +* Martin Gräßlin +* Mathieu Malaterre +* Matthaeus G. Chajdas +* Matthias Kretz +* Matthias Maennich +* Michael Hirsch, Ph.D. +* Michael Stürmer +* Miguel A. Figueroa-Villanueva +* Mike Jackson +* Mike McQuaid +* Nicolas Bock +* Nicolas Despres +* Nikita Krupen'ko +* NVIDIA Corporation +* OpenGamma Ltd. +* Patrick Stotko +* Per Øyvind Karlsen +* Peter Collingbourne +* Petr Gotthard +* Philip Lowman +* Philippe Proulx +* Raffi Enficiaud, Max Planck Society +* Raumfeld +* Roger Leigh +* Rolf Eike Beer +* Roman Donchenko +* Roman Kharitonov +* Ruslan Baratov +* Sebastian Holtermann +* Stephen Kelly +* Sylvain Joubert +* The Qt Company Ltd. +* Thomas Sondergaard +* Tobias Hunger +* Todd Gamblin +* Tristan Carel +* University of Dundee +* Vadim Zhukov +* Will Dicharry + +See version control history for details of individual contributions. + +The above copyright and license notice applies to distributions of +CMake in source and binary form. Third-party software packages supplied +with CMake under compatible licenses provide their own copyright notices +documented in corresponding subdirectories or source files. + +------------------------------------------------------------------------------ + +CMake was initially developed by Kitware with the following sponsorship: + + * National Library of Medicine at the National Institutes of Health + as part of the Insight Segmentation and Registration Toolkit (ITK). + + * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel + Visualization Initiative. + + * National Alliance for Medical Image Computing (NAMIC) is funded by the + National Institutes of Health through the NIH Roadmap for Medical Research, + Grant U54 EB005149. + + * Kitware, Inc. -MathJax (doc/assets/mathjax) -Copyright (c) 2009-2018 The MathJax Consortium -Copyright (c) 2015-2017 Martin Hensel -Copyright (c) 2007, Apostolos Syropoulos ( idx >= 0, \ + 'Channel index {} is incompatible with old_api_map in node {}.'.format(idx, node_name) + return list(order).index(idx) + def find_and_replace_pattern(self, graph: Graph): all_params = [(p.soft_get('name', p.id), p, list(p.out_port(0).data.get_shape())) for p in graph.get_op_nodes(type='Parameter')] - suitable_params = [(name, p, shape) for name, p, shape in all_params if len(shape) == 4 and shape[1] == 3] + suitable_params = [(name, p, shape) for name, p, shape in all_params if + len(shape) == 4 and shape[self.get_fw_index(p, 1)] == 3] log.debug('All network inputs: {}'.format({name: shape for name, _, shape in all_params})) log.debug('Will reverse input channels for: {}'.format({name: shape for name, _, shape in suitable_params})) @@ -66,10 +94,14 @@ def find_and_replace_pattern(self, graph: Graph): extra={'is_warning': True}) for name, parameter, _ in suitable_params: - reverse_channels = ReverseChannels(graph, {'name': name + '/reverse_input_channels'}).create_node() - parameter.out_port(0).get_connection().set_source(reverse_channels.out_port(0), - attributes_save_mode='source') - parameter.out_port(0).connect(reverse_channels.in_port(0)) + reverse_index = self.get_fw_index(parameter, 1) + + if parameter.out_port(0).disconnected(): + continue + + reverse_channels = ReverseChannels(graph, {'name': name + '/reverse_input_channels', + 'axis': reverse_index}).create_node() + parameter.out_port(0).get_connection().insert_node(reverse_channels, attributes_save_mode='source') class ReverseChannelsPropagationDown(BackReplacementPattern): @@ -95,11 +127,30 @@ class ReverseChannelsPropagationDown(BackReplacementPattern): 'Shape': lambda node, rc: ReverseChannelsPropagationDown.pass_rc_through_shape(node, rc), 'ShapeOf': lambda node, rc: ReverseChannelsPropagationDown.pass_rc_through_shape(node, rc), - 'Pad': lambda node, rc: ReverseChannelsPropagationDown.pass_rc_through(node, rc), + 'Pad': lambda node, rc: ReverseChannelsPropagationDown.pass_rc_through_zero_port_only(node, rc), + 'Transpose': lambda node, rc: ReverseChannelsPropagationDown.pass_rc_through_transpose(node, rc), } @staticmethod - def pass_rc_through(node: Node, reverse_channels: Node): + def pass_rc_through_transpose(node: Node, reverse_channels: Node): + if node.in_port(1).disconnected() or node.in_port(0).disconnected(): + return False + order = node.in_port(1).data.get_value() + reverse_axis = reverse_channels.axis + data_rank = len(list(node.in_port(0).data.get_shape())) + + if reverse_axis < 0: + reverse_axis = data_rank + reverse_axis + assert 0 < reverse_axis < data_rank, "Incorrect ReverseChannels axis in node {}.".format(reverse_channels) + + if order is None: + return False + new_axis = list(order).index(reverse_axis) + reverse_channels.axis = new_axis + return ReverseChannelsPropagationDown.pass_rc_through_zero_port_only(node, reverse_channels) + + @staticmethod + def pass_rc_through_zero_port_only(node: Node, reverse_channels: Node): r""" BEFORE AFTER @@ -295,11 +346,30 @@ class ReverseChannelsPropagationUp(BackReplacementPattern): 'Subtract': lambda node, rc: ReverseChannelsPropagationUp.lift_up_through_eltwise(node, rc), 'Pow': lambda node, rc: ReverseChannelsPropagationUp.lift_up_through_eltwise(node, rc), 'Convert': lambda node, rc: ReverseChannelsPropagationUp.lift_up_through_eltwise(node, rc), - 'Pad': lambda node, rc: ReverseChannelsPropagationUp.lift_up_through_pad(node, rc), + 'Pad': lambda node, rc: ReverseChannelsPropagationUp.lift_up_through_zero_port_only(node, rc), + 'Transpose': lambda node, rc: ReverseChannelsPropagationUp.lift_up_through_transpose(node, rc), } @staticmethod - def lift_up_through_pad(node: Node, reverse_channels: Node): + def lift_up_through_transpose(node: Node, reverse_channels: Node): + if node.in_port(1).disconnected() or node.in_port(0).disconnected(): + return False + order = node.in_port(1).data.get_value() + reverse_axis = reverse_channels.axis + data_rank = len(list(node.in_port(0).data.get_shape())) + + if reverse_axis < 0: + reverse_axis = data_rank + reverse_axis + assert 0 < reverse_axis < data_rank, "Incorrect ReverseChannels axis in node {}.".format(reverse_channels) + + if order is None: + return False + new_axis = order[reverse_axis] + reverse_channels.axis = new_axis + return ReverseChannelsPropagationUp.lift_up_through_zero_port_only(node, reverse_channels) + + @staticmethod + def lift_up_through_zero_port_only(node: Node, reverse_channels: Node): r""" BEFORE AFTER @@ -307,7 +377,7 @@ def lift_up_through_pad(node: Node, reverse_channels: Node): \ previous_op previous_op ReverseChannels previous_op \ / \ / - Pad Pad + Node Node | | ReverseChannels next_op | @@ -323,7 +393,16 @@ def lift_up_through_pad(node: Node, reverse_channels: Node): reverse_channels.out_port(0).disconnect() reverse_channels.in_port(0).disconnect() src = node_input_port_0.get_connection().get_source() - node_input_port_0.get_connection().set_source(reverse_channels.out_port(0)) + + if src.node.soft_get('type') == 'Parameter': + # For Parameter nodes tensor debug attributes should not move to the last node + # of subgraph. It is needed for the proper mapping of input framework name. + # For this reason "source" mode is used to keep tensor debug attributes at Parameter node. + node_input_port_0.get_connection().set_source(reverse_channels.out_port(0), + attributes_save_mode="source") + else: + node_input_port_0.get_connection().set_source(reverse_channels.out_port(0)) + src.connect(reverse_channels.in_port(0)) for reverse_channels_destination in reverse_channels_out_nodes: node.out_port(0).get_connection().add_destination(reverse_channels_destination) diff --git a/model-optimizer/extensions/back/add_outputs_recursive.py b/model-optimizer/extensions/back/add_outputs_recursive.py new file mode 100644 index 00000000000000..f8bff57ec67bde --- /dev/null +++ b/model-optimizer/extensions/back/add_outputs_recursive.py @@ -0,0 +1,318 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +import numpy as np + +from extensions.ops.If import If +from extensions.ops.loop import Loop +from extensions.ops.tensor_iterator import TensorIterator +from mo.back.replacement import BackReplacementPattern +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension_value +from mo.front.tf.graph_utils import create_op_node_with_second_input +from mo.graph.graph import Graph, Node +from mo.ops.result import Result +from mo.ops.unsqueeze import Unsqueeze + + +def ti_set_output_port_shape(cycle_node, internal_id, port_num, iterations_count, axis): + int_node_name = TensorIterator.find_internal_layer_id(cycle_node.body, internal_id) + int_node = Node(cycle_node.body, int_node_name) + assert int_node.op == 'Result' + out_shape = int_node.in_port(0).data.get_shape().copy() + # inside cycle node Unsqueeze was added to have the first dimension for concatenating results along it + assert len(out_shape) >= 1 + if axis is not None: + out_shape[axis] = iterations_count + + assert port_num in cycle_node.out_ports() + cycle_node.out_port(port_num).data.set_shape(out_shape) + + +def get_iterations_count_from_output_record(output_rec): + def check_field(record, field): + return field in record and record[field] is not None + + iterations_count = 1 + # 1. check if we need to concatenate iteration results for given output + if not check_field(output_rec, 'axis'): + # in this case we do not concatenate outputs, so iterations count is not needed really + return None + + # 2. check if given output record contains values for 'end', so iterations count can be calculated from this record + if check_field(output_rec, 'end') and output_rec['end'] != -1 and \ + check_field(output_rec, 'start') and output_rec['start'] != -1: + stride = output_rec['stride'] if check_field(output_rec, 'stride') else 1 + # get iterations count from output record + iterations_count = (output_rec['end'] - output_rec['start']) / stride + return iterations_count + + return dynamic_dimension_value + + +# shape inference for TensorIterator +# copy shapes from internal nodes + insert correct iterations count where needed +def ti_infer(step_node, port_num): + out_port_map = step_node.output_port_map + port_num = port_num + len(step_node.in_ports()) + # find out which internal layer maps to port_num + found_rec = None + for record in out_port_map: + if record['external_port_id'] == port_num: + found_rec = record + break + assert found_rec is not None, \ + "External port {} is not connected with body in node {}".format(port_num, + step_node.soft_get('name', step_node.id)) + + port_num = port_num - len(step_node.in_ports()) + + # find out iterations count for TensorIterator to set output shape correctly + + iterations_count = get_iterations_count_from_output_record(found_rec) + if iterations_count is dynamic_dimension_value: + iterations_count = TensorIterator.find_iterations_count_for_output(step_node) + + ti_set_output_port_shape(step_node, found_rec['internal_layer_id'], port_num, iterations_count, + found_rec['axis']) + + +# shape inference for Loop +# copy shapes from internal nodes + insert correct iterations count where needed +# iterations count always in the first dimension +def loop_infer(step_node, port_num): + out_port_map = step_node.output_port_map + int_layer_id = None + iterations_count = Loop.iterations_count(step_node) + for record in out_port_map: + if record['external_port_id'] == port_num: + int_layer_id = record['internal_layer_id'] + + ti_set_output_port_shape(step_node, int_layer_id, port_num, iterations_count, 0) + + +def max_internal_layer_id(graph): + max_int_layer_id = 0 + for n in graph.get_op_nodes(): + if n.has_and_set('internal_layer_id') and n.internal_layer_id > max_int_layer_id: + max_int_layer_id = n.internal_layer_id + return max_int_layer_id + + +# Add Result (and Unsqueeze is add_unsqueeze=True) to node port port_num in graph cur_graph. +# New nodes will have internal id equal to cur_max_layer_id + 1 (and cur_max_layer_id + 2 if 2 nodes were added) +# New nodes will be inserted in tracks on position i. +def add_output_in_body(node, port_num, cur_graph, cur_max_layer_id, tracks, track_index, add_unsqueeze=True): + port = node.out_port(port_num) + if add_unsqueeze: + unsq_name = port.node.soft_get('name', port.node.id) + "/Unsqueeze" + unsq_node = create_op_node_with_second_input(cur_graph, Unsqueeze, + int64_array([0]), + {'name': unsq_name}) + port.connect(unsq_node.in_port(0)) + unsq_node['internal_layer_id'] = cur_max_layer_id + 1 + cur_max_layer_id += 1 + tracks.insert(track_index, {'node': unsq_node, 'graph': cur_graph}) + port = unsq_node.out_port(0) + + out_name = port.node.soft_get('name', port.node.id) + ":" + str(port_num) + res_node = Result(cur_graph, {'name': out_name}).create_node() + port.connect(res_node.in_port(0)) + res_node['internal_layer_id'] = cur_max_layer_id + 1 + cur_max_layer_id += 1 + tracks.insert(track_index, {'node': res_node, 'graph': cur_graph}) + + return res_node + + +class AddOutputRecursive(BackReplacementPattern): + """ + Add output to node inside loops. Path to node set in 'additional_outputs' attribute of graph. + Path structure: [node_loop_1, loop_2_in_loop_1,.., if_node, [then_list, else_list]] + After if operation should be sub-list with 2 elements then_list and else_list where each is one node or list of + nodes in according path + For cycles results from all iterations will be concatenated along 0 dimension. + """ + enabled = False + run_not_recursively = True + + @staticmethod + def add_output_for_path(graphs_nodes_path): + # add output to nodes according to path + step_node = graphs_nodes_path[-1]['node'] + cur_graph = graphs_nodes_path[-1]['graph'] + + ports_to_add_nodes = [] + for o_p in step_node.out_ports(): + ports_to_add_nodes.append(o_p) + + # update internal_layer_id for new Results + for i in range(len(graphs_nodes_path)-1, 0, -1): + cur_max_layer_id = max_internal_layer_id(cur_graph) + 1 + cur_loop_node = graphs_nodes_path[i-1]['node'] + new_out_ports = [] + if cur_loop_node.op is not 'If': + # add Unsqueeze and Result for TensorIterator and Loop and update output_port_map + for p_num in ports_to_add_nodes: + res_node = add_output_in_body(step_node, p_num, cur_graph, cur_max_layer_id, + graphs_nodes_path, i) + + # IR reader fix output port map for Loop, but have not change for TensorIterator + new_port_id = len(cur_loop_node.out_ports()) + if cur_loop_node.op == 'TensorIterator': + new_port_id = new_port_id + len(cur_loop_node.in_ports()) + cur_loop_node.output_port_map.append({'axis': 0, 'stride': 1, 'part_size': 1, 'start': 0, + 'end': -1, 'external_port_id': new_port_id, + 'internal_layer_id': res_node['internal_layer_id']}) + port_id = new_port_id + if cur_loop_node.op == 'TensorIterator': + port_id = port_id - len(cur_loop_node.in_ports()) + + new_out_ports.append(port_id) + cur_loop_node.add_output_port(port_id) + else: + # add Result nodes for If and update output_id + for p_num in ports_to_add_nodes: + res_node = add_output_in_body(step_node, p_num, cur_graph, cur_max_layer_id, graphs_nodes_path, i, + add_unsqueeze=False) + + if cur_loop_node.then_graph == cur_graph: + new_port_id = len(cur_loop_node.out_ports()) + res_node['output_id'] = new_port_id + cur_loop_node.add_output_port(new_port_id) + new_out_ports.append(new_port_id) + else: + res_node['output_id'] = list(cur_loop_node.out_ports().keys())[-1] + ports_to_add_nodes = new_out_ports + step_node = cur_loop_node + cur_graph = graphs_nodes_path[i-1]['graph'] + + i = 0 + for p_num in ports_to_add_nodes: + port = step_node.out_port(p_num) + out_name = step_node.soft_get('name', step_node.id) + "." + str(p_num) + res_node = Result(cur_graph, {'name': out_name}).create_node() + port.connect(res_node.in_port(0)) + # add name of Result to fw_tensor_debug_info to avoid renaming + if step_node.out_nodes()[p_num].has_and_set('fw_tensor_debug_info'): + step_node.out_nodes()[p_num]['fw_tensor_debug_info'].append(out_name) + else: + step_node.out_nodes()[p_num]['fw_tensor_debug_info'] = [[out_name, out_name]] + if step_node.op == 'TensorIterator': + step_node.out_edges()[len(step_node.out_edges())-1]['external_port_id'] = p_num + \ + len(step_node.in_ports()) + graphs_nodes_path.insert(0, {'node': res_node, 'graph': cur_graph}) + i += 1 + return graphs_nodes_path + + @staticmethod + def infer_shapes_of_nodes_in_path(graphs_nodes_path): + # update shape for new or updated nodes + for i in range(len(graphs_nodes_path) - 1, -1, -1): + step_node = graphs_nodes_path[i]['node'] + # update shapes for Loop, TI, If, Unsqueeze + # Result to end node in path added to existing port with already calculated shapes + for p_num in step_node.out_ports(): + if not step_node.out_port(p_num).disconnected(): + if step_node.op == 'TensorIterator': + ti_infer(step_node, p_num) + elif step_node.op == 'Loop': + loop_infer(step_node, p_num) + elif step_node.op == 'Unsqueeze': + assert step_node.in_port(1).get_source().node.has('value') + axis = step_node.in_port(1).get_source().node.value[0] + out_shape = list(step_node.in_port(0).get_source().data.get_shape()) + out_shape.insert(axis, 1) + step_node.out_port(p_num).data.set_shape(out_shape) + elif step_node.op == 'If': + If.update_if_output_ports_shape(step_node) + + @staticmethod + def split_path_to_simple_tracks(graph, path): + # Split complex path into simple linear tracks. + # In path after If node list with 2 sub-lists should be. In this function such path is split into 2 tracks: + # one for each sublist with linear structure. + # Number of tracks got from path is 2 * number of If operations in path. + # Track is looks like list of paths with 2 fields : list of nodes on current path and list of according graphs + # Example: + # input path : [loop_1, loop_2, if_1, [[loop3_1, node_1], [node_2]]] + # output track: [{'nodes': [loop_1, loop_2, if_1, loop3_1, node_1], + # 'graphs':[graph, loop_1.body, loop_2.body, if.then_graph, loop3_1.body]}, + # {'nodes': [loop_1, loop_2, if_1, node_2], + # 'graphs':[graph, loop_1.body, loop_2.body, if.else_graph]}] + + # structure to save tracks + # list with tracks, each track is list of pairs {'node', 'graph'} + paths_nodes_graphs = list() + paths_nodes_graphs.append([]) + # stack for sub-graphs that will be traversed in future + future_graphs_stack = [graph] + # index for track that we currently fill + track_idx = 0 + # save lists that were started but not finished during processing + lists_stack = [{'list': path, 'pos': -1}] + while len(lists_stack) != 0: + cur_list_pos = lists_stack.pop(-1) + # current list to process + cur_list = cur_list_pos['list'] + # index in current list/sub-list + list_idx = cur_list_pos['pos'] + 1 + while list_idx < len(cur_list): + el = cur_list[list_idx] + if isinstance(el, (list, np.ndarray)): + lists_stack.append({'list': cur_list, 'pos': list_idx}) + # if we have previous node non-list then current sublist is for If node + # and new tracks should be added for sub-graphs (the first subgraph will continue current track) + if list_idx != 0 and isinstance(cur_list[list_idx - 1], str): + for i in range(len(el) - 1): + # copy all nodes from existing track to new one + paths_nodes_graphs.append(paths_nodes_graphs[-1][:]) + # new sublist started, so reset index + cur_list = el + list_idx = 0 + else: + assert isinstance(el, str) + cur_graph = future_graphs_stack.pop(-1) + step_node = Node(cur_graph, el) + paths_nodes_graphs[track_idx].append({'node': step_node, 'graph': cur_graph}) + + # if node is not last, check that next node will be on current track or not + if list_idx != len(cur_list) - 1: + # so detect if we are in sublist with branches for If + # then in stack sublist is not the first node of list + # and have previous node with If operation name + if len(lists_stack) != 0 and lists_stack[-1]['pos'] != 0 and \ + isinstance(lists_stack[-1]['list'][lists_stack[-1]['pos']-1], str): + # switch to next track + if list_idx != len(cur_list) - 1: + track_idx += 1 + else: + assert step_node.has_and_set('sub_graphs'), "Node without sub-graphs is not last in path" + # the first graph should be first in traverse + for sub_graphs_name in reversed(step_node['sub_graphs']): + future_graphs_stack.append(step_node[sub_graphs_name]) + list_idx += 1 + + return paths_nodes_graphs + + def find_and_replace_pattern(self, graph: Graph): + + if 'additional_outputs' not in graph.graph: + return + + path = graph.graph['additional_outputs'] + paths_nodes_graphs = self.split_path_to_simple_tracks(graph, path) + + paths_nodes_graphs_old = [] + for i in range(len(paths_nodes_graphs)): + paths_nodes_graphs_old.append(paths_nodes_graphs[i][:]) + paths_nodes_graphs[i] = self.add_output_for_path(paths_nodes_graphs[i]) + + for i in range(len(paths_nodes_graphs)): + self.infer_shapes_of_nodes_in_path(paths_nodes_graphs[i]) + + new_nodes = [] + for i in range(len(paths_nodes_graphs)): + # new Result added to main graph should be on last place + if paths_nodes_graphs_old[i][0]['node'] != paths_nodes_graphs[i][0]['node']: + new_nodes.append(paths_nodes_graphs[i][0]['node']) + + return new_nodes diff --git a/model-optimizer/extensions/back/fuse_sub_div_min.py b/model-optimizer/extensions/back/fuse_sub_div_min.py deleted file mode 100644 index 9c13708150b12e..00000000000000 --- a/model-optimizer/extensions/back/fuse_sub_div_min.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np - -from extensions.ops.elementwise import Sub, Div, Negative -from mo.back.replacement import BackReplacementPattern -from mo.graph.graph import Node, Graph - - -class Negate(BackReplacementPattern): - enabled = True - force_clean_up = True - - @staticmethod - def pattern(): - return dict( - nodes=[ - ('mul', {'type': 'Multiply'}) - ], - edges=[], - ) - - @staticmethod - def replace_pattern(graph: Graph, match: [str, Node]): - mul = match['mul'] - name = mul.soft_get('name', mul.id) - - mul_POS_port = None - if mul.in_port(0).data.get_value() is not None and np.all(mul.in_port(0).data.get_value() == -1): - mul_POS_port = mul.in_port(1) - if mul.in_port(1).data.get_value() is not None and np.all(mul.in_port(1).data.get_value() == -1): - mul_POS_port = mul.in_port(0) - - if mul_POS_port is None: - return - - negative = Negative(graph, {'name': name + '/Negate'}).create_node() - - mul.out_port(0).get_connection().set_source(negative.out_port(0)) - mul_POS_port.get_connection().set_destination(negative.in_port(0)) - - -class EltwisesToSubtract(BackReplacementPattern): - enabled = True - force_clean_up = True - - def run_after(self): - return [Negate] - - @staticmethod - def pattern(): - return dict( - nodes=[ - ('neg', {'type': 'Negative'}), - ('neg_d', {}), - ('add', {'type': 'Add'}) - ], - edges=[ - ('neg', 'neg_d'), - ('neg_d', 'add'), - ], - ) - - @staticmethod - def replace_pattern(graph: Graph, match: [str, Node]): - neg = match['neg'] - add = match['add'] - - name = add.soft_get('name', add.id) - - minuend_port = add.in_port(0).get_source() \ - if add.in_port(1).get_source().node.id == neg.id else add.in_port(1).get_source() - subtrahned_port = neg.in_port(0).get_source() - - sub = Sub(graph, {'name': name + '/sub'}).create_node() - - add.out_port(0).get_connection().set_source(sub.out_port(0)) - minuend_port.connect(sub.in_port(0)) - subtrahned_port.connect(sub.in_port(1)) - - -class EltwisesToDiv(BackReplacementPattern): - enabled = True - force_clean_up = True - - @staticmethod - def pattern(): - return dict( - nodes=[ - ('const', {'type': 'Const'}), - ('const_d', {'value': lambda val: val is not None and np.all(val == -1)}), - ('inv', {'type': 'Pow'}), - ('inv_d', {}), - ('mul', {'type': 'Multiply'}) - ], - edges=[ - ('const', 'const_d'), - ('const_d', 'inv', {'in': 1}), - ('inv', 'inv_d'), - ('inv_d', 'mul'), - ], - ) - - @staticmethod - def replace_pattern(graph: Graph, match: [str, Node]): - pow = match['inv'] - mul = match['mul'] - const = match['const'] - - name = mul.soft_get('name', mul.id) - - devidend_port = mul.in_port(0).get_source() if mul.in_port(1).get_source().node.id == pow.id else mul.in_port( - 1).get_source() - divider_port = pow.in_port(0).get_source() if pow.in_port(1).get_source().node.id == const.id else pow.in_port( - 1).get_source() - - div = Div(graph, {'name': name + '/div'}).create_node() - - mul.out_port(0).get_connection().set_source(div.out_port(0)) - devidend_port.connect(div.in_port(0)) - divider_port.connect(div.in_port(1)) diff --git a/model-optimizer/extensions/front/tf/IteratorGetNextCut.py b/model-optimizer/extensions/front/tf/IteratorGetNextCut.py new file mode 100644 index 00000000000000..3cced57f6587ae --- /dev/null +++ b/model-optimizer/extensions/front/tf/IteratorGetNextCut.py @@ -0,0 +1,45 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from collections import defaultdict + +from mo.front.extractor import add_input_ops +from mo.graph.graph import Graph +from mo.middle.passes.convert_data_type import SUPPORTED_DATA_TYPES, np_data_type_to_precision +from mo.utils.error import Error +from mo.front.common.replacement import FrontReplacementPattern + + +class IteratorGetNextCut(FrontReplacementPattern): + """ + Cuts OneShotIterator -> IteratorGetNext pattern + in order to enable Out Of the Box (OOB) usage. + Pass is run only if user didn't specify any inputs names and shapes. + """ + enabled = True + graph_condition = [lambda graph: graph.graph['cmd_params'].input is None] + + def run_before(self): + from extensions.front.output_cut import OutputCut + from extensions.front.input_cut import InputCut + return [OutputCut, InputCut] + + def run_after(self): + return [] + + def find_and_replace_pattern(self, graph: Graph): + iter_get_next_shapes = defaultdict(list) + for iter_get_next in graph.get_op_nodes(op='IteratorGetNext'): + iter_get_next_name = iter_get_next.soft_get('name', iter_get_next.id) + for port in iter_get_next.out_ports(): + if not np_data_type_to_precision(iter_get_next.types[port]) in SUPPORTED_DATA_TYPES: + raise Error("In IteratorGetNext node '{}' data type '{}' is not supported".format( + iter_get_next_name, iter_get_next.types[port])) + + iter_get_next_shapes[iter_get_next_name].append(dict( + shape=iter_get_next.shapes[port], + out=port, + data_type=iter_get_next.types[port] + )) + + add_input_ops(graph, iter_get_next_shapes, True) diff --git a/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py b/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py index e79991647145e3..c9318c976e56d8 100644 --- a/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py +++ b/model-optimizer/extensions/front/tf/IteratorGetNext_ext.py @@ -20,5 +20,5 @@ def extract(cls, node): result_shapes = [] for shape_pb in shapes: result_shapes.append(tf_tensor_shape(shape_pb)) - Op.update_node_stat(node, {'shapes': result_shapes, 'types': extracted_types}) + Op.update_node_stat(node, {'shapes': result_shapes, 'types': extracted_types, 'out_ports_count': 1}) return cls.enabled diff --git a/model-optimizer/extensions/front/tf/activation_ext.py b/model-optimizer/extensions/front/tf/activation_ext.py index 3780d77f7f3392..c2cf3c42ee59c6 100644 --- a/model-optimizer/extensions/front/tf/activation_ext.py +++ b/model-optimizer/extensions/front/tf/activation_ext.py @@ -1,8 +1,8 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from extensions.ops.activation_ops import Abs, Elu, Erf, Exp, ReLU, LeakyReLU, LogicalNot, ReLU6, Sigmoid, \ - Sin, Sinh, Cos, Cosh, Tan, Tanh, Ceiling, Atanh, Acosh, Asinh, Mish, Log +from extensions.ops.activation_ops import Abs, Acos, Asin, Atan, Elu, Erf, Exp, ReLU, LeakyReLU, LogicalNot, ReLU6, \ + Sigmoid, Sin, Sinh, Cos, Cosh, Tan, Tanh, Ceiling, Atanh, Acosh, Asinh, Mish, Log from mo.front.extractor import FrontExtractorOp @@ -218,3 +218,33 @@ class LogExtractor(FrontExtractorOp): def extract(cls, node): Log.update_node_stat(node) return cls.enabled + + +class AsinExtractor(FrontExtractorOp): + op = 'Asin' + enabled = True + + @classmethod + def extract(cls, node): + Asin.update_node_stat(node) + return cls.enabled + + +class AcosExtractor(FrontExtractorOp): + op = 'Acos' + enabled = True + + @classmethod + def extract(cls, node): + Acos.update_node_stat(node) + return cls.enabled + + +class AtanExtractor(FrontExtractorOp): + op = 'Atan' + enabled = True + + @classmethod + def extract(cls, node): + Atan.update_node_stat(node) + return cls.enabled diff --git a/model-optimizer/extensions/ops/gathernd.py b/model-optimizer/extensions/ops/gathernd.py index 1175698fa96b89..01e6e2f36c4794 100644 --- a/model-optimizer/extensions/ops/gathernd.py +++ b/model-optimizer/extensions/ops/gathernd.py @@ -16,7 +16,7 @@ def __init__(self, graph: Graph, attrs: dict): mandatory_props = { 'type': self.op, 'op': self.op, - 'version': 'opset5', + 'version': 'opset8', 'infer': self.infer, 'in_ports_count': 2, 'out_ports_count': 1, @@ -56,41 +56,55 @@ def infer(node: Node): assert len(indices_shape) > 0, "Indices must not be a scalar" assert (batch_dims + indices_shape[-1]) <= len(data_shape), \ "Length of a tuple with indices must not exceed a rank of data tensor excluding batch dimensions" + assert node['version'] in ['opset5', 'opset8'], 'Unsupported version of GatherND operation: {}, operation ' \ + 'name : {}'.format(node['version'], node.soft_get('name')) # compute output shape + batch = [] if batch_dims > 0: - if is_fully_defined(data_shape[:batch_dims]): - batch = [np.prod(data_shape[:batch_dims]).tolist()] - else: - batch = [dynamic_dimension_value] - else: - batch = [] + if node['version'] == 'opset5': # Support old version of gatherND shape inference + if is_fully_defined(data_shape[:batch_dims]): + batch = [np.prod(data_shape[:batch_dims]).tolist()] + else: + batch = [dynamic_dimension_value] + elif node['version'] == 'opset8': + for dim in range(batch_dims): + assert compatible_dims(indices_shape[dim], data_shape[dim]),\ + "Batch dimensions in data.shape and indices.shape must be compatible" + if is_fully_defined(indices_shape[:batch_dims]): + batch = indices_shape[:batch_dims].tolist() + elif is_fully_defined(data_shape[:batch_dims]): + batch = data_shape[:batch_dims].tolist() + else: + for ind in range(batch_dims): + if indices_shape[ind] != dynamic_dimension_value: + batch.append(indices_shape[ind]) + elif data_shape[ind] != dynamic_dimension_value: + batch.append(data_shape[ind]) + else: + batch.append(dynamic_dimension_value) + slice_shape = list(data_shape[(batch_dims + indices_shape[-1]):]) - output_shape = batch + list(indices_shape[batch_dims:-1]) + slice_shape + + output_shape = batch + list(indices_shape)[batch_dims:-1] + slice_shape node.out_port(0).data.set_shape(output_shape) - # compute output value if all input values are defined - if is_fully_defined(indices_value) and is_fully_defined(data_value): - output_value = np.zeros(output_shape, dtype=data_value.dtype) - if batch_dims == 0: - output_indices_range = int64_array(indices_shape[:-1]) - for output_index in np.ndindex(tuple(output_indices_range)): - indices_tuple = indices_value[output_index] - output_value[output_index] = data_value[tuple(indices_tuple.T)] - else: - batch_dims_range = int64_array(indices_shape[:batch_dims]) - for batch_indices in np.ndindex(tuple(batch_dims_range)): - # compute batch index in output tensor - batch_ind = 0 - num_elements = 1 - for ind in reversed(range(len(batch_dims_range))): - batch_ind += batch_indices[ind] * num_elements - num_elements *= batch_dims_range[ind] - output_indices_range = int64_array(indices_shape[batch_dims:-1]) - for output_index in np.ndindex(tuple(output_indices_range)): - tmp_ind = batch_indices + output_index - indices_tuple = tuple(indices_value[tmp_ind].T) - full_input_ind = batch_indices + indices_tuple - full_output_ind = tuple(np.array([batch_ind]).T) + output_index - output_value[full_output_ind] = data_value[full_input_ind] + # compute output value if all input indices are defined + if is_fully_defined(indices_value) and data_value is not None: + batch_dims_size = 1 + + for i in range(batch_dims): + batch_dims_size *= indices_shape[i] + + output_data = [] + + reshaped_indices = indices_value.reshape(batch_dims_size, -1, indices_shape[-1]) + + reshaped_data = data_value.reshape((batch_dims_size,) + tuple((data_shape[batch_dims:]))) + + for batch_dim in range(reshaped_indices.shape[0]): + for outer_dim in range(reshaped_indices.shape[1]): + gather_index = tuple(reshaped_indices[batch_dim][outer_dim]) + output_data.append(reshaped_data[(batch_dim,) + gather_index]) + output_value = np.asarray(output_data, dtype=data_value.dtype).reshape(output_shape) node.out_port(0).data.set_value(output_value) diff --git a/model-optimizer/extensions/ops/tensor_iterator.py b/model-optimizer/extensions/ops/tensor_iterator.py index 0d62d4ad5449c0..acc2c67cccef22 100644 --- a/model-optimizer/extensions/ops/tensor_iterator.py +++ b/model-optimizer/extensions/ops/tensor_iterator.py @@ -1,10 +1,10 @@ # Copyright (C) 2018-2021 Intel Corporation # SPDX-License-Identifier: Apache-2.0 - from copy import copy, deepcopy +from math import ceil from extensions.ops.parameter import Parameter -from mo.front.common.partial_infer.utils import shape_array +from mo.front.common.partial_infer.utils import shape_array, is_fully_defined, dynamic_dimension_value from mo.graph.graph import Node, dict_includes, Graph from mo.ops.const import Const from mo.ops.op import Op @@ -347,6 +347,51 @@ def ti_type_infer(node): ti_graph.remove_nodes_from([node.id for node in fake_input_const_nodes]) + @staticmethod + def find_iterations_count_for_output(ti_node): + def check_field(record, field): + return field in record and record[field] is not None + iterations_count = dynamic_dimension_value + # find out iterations count from inputs. + # If no input contains 'axis' attribute then no slicing is in TI and it has only one iteration + # If several inputs have axis attribute with different iterations count then we use maximum value. + for in_rec in ti_node.input_port_map: + if not check_field(in_rec, 'axis'): + continue + assert check_field(in_rec, 'external_port_id'), "external_port_id not set for input of {} node".format(ti_node.id) + in_shape = ti_node.in_port(in_rec['external_port_id']).data.get_shape() + if check_field(in_rec, 'end') and in_rec['end'] >= 0 and \ + check_field(in_rec, 'start') and in_rec['start'] >= 0: + in_rec_end = in_rec['end'] + in_rec_start = in_rec['start'] + elif check_field(in_rec, 'end') and in_rec['end'] >= 0: + in_rec_end = in_rec['end'] + in_rec_start = in_shape[in_rec['axis']] if not check_field(in_rec, 'start') else \ + in_shape[in_rec['axis']] + 1 + in_rec['start'] + elif check_field(in_rec, 'start') and in_rec['start'] >= 0: + in_rec_end = in_shape[in_rec['axis']] if not check_field(in_rec, 'end') else \ + in_shape[in_rec['axis']] + 1 + in_rec['end'] + in_rec_start = in_rec['start'] + else: + in_rec_end = ti_node.in_port(in_rec['external_port_id']).data.get_shape()[in_rec['axis']] + in_rec_start = 0 + + if check_field(in_rec, 'stride'): + in_rec_stride = in_rec['stride'] + else: + in_rec_stride = 1 + + # in case of dynamic iterations count don't continue any calculations on this iteration + if not is_fully_defined(in_rec_end) or not is_fully_defined(in_rec_start): + continue + + if iterations_count is not dynamic_dimension_value and \ + ceil((in_rec_end - in_rec_start) / in_rec_stride) != iterations_count: + raise Error("TensorIterator node {} have inputs with different iterations count".format(ti_node.id)) + iterations_count = ceil((in_rec_end - in_rec_start) / in_rec_stride) + + return iterations_count + def get_internal_node_by_layer_id(ti, internal_layer_id): suitable_nodes = ti.body.get_op_nodes(internal_layer_id=internal_layer_id) diff --git a/model-optimizer/mo/back/offline_transformations.py b/model-optimizer/mo/back/offline_transformations.py index c41aa8b95ca9ce..79f9d847323fbe 100644 --- a/model-optimizer/mo/back/offline_transformations.py +++ b/model-optimizer/mo/back/offline_transformations.py @@ -33,8 +33,11 @@ def apply_moc_transformations(net: object): from openvino.offline_transformations import ApplyMOCTransformations # pylint: disable=import-error,no-name-in-module ApplyMOCTransformations(net, False) +def compress_model(net:object): + from openvino.offline_transformations import CompressModelTransformation # pylint: disable=import-error,no-name-in-module + CompressModelTransformation(net) -def apply_offline_transformations(input_model: str, framework: str, transforms: list): +def apply_offline_transformations(input_model: str, framework: str, transforms: list, compress_fp16=False): # This variable is only needed by GenerateMappingFile transformation # to produce correct mapping extract_names = framework in ['tf', 'mxnet', 'kaldi'] @@ -58,6 +61,10 @@ def read_network(path_to_xml): apply_user_transformations(net, transforms) apply_moc_transformations(net) + + if compress_fp16: + compress_model(net) + Serialize(net, str(input_model + ".xml").encode('utf-8'), (input_model + ".bin").encode('utf-8')) path_to_mapping = input_model + ".mapping" GenerateMappingFile(net, path_to_mapping.encode('utf-8'), extract_names) @@ -68,6 +75,7 @@ def read_network(path_to_xml): parser.add_argument("--input_model") parser.add_argument("--framework") parser.add_argument("--transform") + parser.add_argument("--compress_fp16", action='store_true') args = parser.parse_args() - apply_offline_transformations(args.input_model, args.framework, parse_transform(args.transform)) \ No newline at end of file + apply_offline_transformations(args.input_model, args.framework, parse_transform(args.transform), args.compress_fp16) diff --git a/model-optimizer/mo/main.py b/model-optimizer/mo/main.py index c939d9523ed919..e8831184125c50 100644 --- a/model-optimizer/mo/main.py +++ b/model-optimizer/mo/main.py @@ -205,6 +205,12 @@ def raise_ie_not_found(): except Exception as e: raise_ie_not_found() + if 'data_type' in argv and argv.data_type in ['FP16', 'half']: + argv.data_type = 'FP32' + argv.compress_fp16 = True + else: + argv.compress_fp16 = False + # This is just to check that transform key is valid and transformations are available check_available_transforms(parse_transform(argv.transform)) @@ -355,10 +361,15 @@ def emit_ir(graph: Graph, argv: argparse.Namespace): if not argv.legacy_ir_generation: path_to_offline_transformations = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'back', 'offline_transformations.py') - status = subprocess.run([sys.executable, path_to_offline_transformations, + cmd = [sys.executable, path_to_offline_transformations, "--input_model", orig_model_name, "--framework", argv.framework, - "--transform", argv.transform], env=os.environ) + "--transform", argv.transform] + if "compress_fp16" in argv and argv.compress_fp16: + cmd += ["--compress_fp16"] + # restore data_type cmd parameter + argv.data_type = 'FP16' + status = subprocess.run(cmd, env=os.environ) return_code = status.returncode except Exception as e: return_code = "failed" diff --git a/model-optimizer/mo/moc_frontend/serialize.py b/model-optimizer/mo/moc_frontend/serialize.py index abe150742e1d62..2de7c800d0225d 100644 --- a/model-optimizer/mo/moc_frontend/serialize.py +++ b/model-optimizer/mo/moc_frontend/serialize.py @@ -19,6 +19,10 @@ def moc_emit_ir(ngraph_function: Function, argv: argparse.Namespace): apply_user_transformations(network, parse_transform(argv.transform)) apply_moc_transformations(network) + if argv.compress_fp16: + from mo.back.offline_transformations import compress_model + compress_model(network) + orig_model_name = os.path.normpath(os.path.join(output_dir, argv.model_name)) network.serialize(orig_model_name + ".xml", orig_model_name + ".bin") diff --git a/model-optimizer/mo/pipeline/common.py b/model-optimizer/mo/pipeline/common.py index 6dfafa840d3ab2..319b99e9d57032 100644 --- a/model-optimizer/mo/pipeline/common.py +++ b/model-optimizer/mo/pipeline/common.py @@ -173,18 +173,19 @@ def convert_inputs_of_specific_ops(graph: Graph): def prepare_emit_ir(graph: Graph, data_type: str, output_dir: str, output_model_name: str, mean_data: [list, None] = None, input_names: list = None, meta_info: dict = None, - use_temporary_path=False): + use_temporary_path=False, used_by_ir_reader=False): if input_names is None: input_names = [] if meta_info is None: meta_info = {} graph.strict_mode = False - # convert Parameter data types - convert_data_type.convert_parameters_data_type(graph, data_type) - # convert blobs (usually weights and biases) - for sub_graph in [graph] + collect_sub_graphs(graph): - convert_data_type.convert_blobs(sub_graph, data_type) + if not used_by_ir_reader: + # convert Parameter data types + convert_data_type.convert_parameters_data_type(graph, data_type) + # convert blobs (usually weights and biases) + for sub_graph in [graph] + collect_sub_graphs(graph): + convert_data_type.convert_blobs(sub_graph, data_type) # restore data type for specific inputs/outputs of specific ops to the data types required by nGraph for_graph_and_each_sub_graph_recursively(graph, convert_inputs_of_specific_ops) diff --git a/model-optimizer/mo/utils/get_ov_update_message.py b/model-optimizer/mo/utils/get_ov_update_message.py index 95165f6bafa738..9d8ccdba31c825 100644 --- a/model-optimizer/mo/utils/get_ov_update_message.py +++ b/model-optimizer/mo/utils/get_ov_update_message.py @@ -8,9 +8,9 @@ def get_ov_update_message(): - expected_update_date = datetime.date(year=2021, month=10, day=15) + expected_update_date = datetime.date(year=2022, month=2, day=15) current_date = datetime.date.today() - link = 'https://software.intel.com/content/www/us/en/develop/tools/openvino-toolkit/download.html?cid=other&source=prod&campid=ww_2021_bu_IOTG_OpenVINO-2021-4-LTS&content=upg_all&medium=organic' + link = 'https://software.intel.com/content/www/us/en/develop/tools/openvino-toolkit/download.html?cid=other&source=prod&campid=ww_2022_bu_IOTG_OpenVINO-2022-1&content=upg_all&medium=organic' return msg_fmt.format(link) if current_date >= expected_update_date else None diff --git a/model-optimizer/mo/utils/ir_reader/extender.py b/model-optimizer/mo/utils/ir_reader/extender.py index 13bc5dddaed611..afa71ac6ecabb8 100644 --- a/model-optimizer/mo/utils/ir_reader/extender.py +++ b/model-optimizer/mo/utils/ir_reader/extender.py @@ -60,5 +60,8 @@ def use_shapes_from_ir(node: Node): # Set all output shapes the same as restored from IR for num in node.out_ports(): - node.out_port(num).data.set_shape(int64_array(node.ports[i][0])) + if i in node.ports: + node.out_port(num).data.set_shape(int64_array(node.ports[i][0])) + else: + assert node.out_port(num).data.get_shape() is not None, "Newly added port does not have set shape" i += 1 diff --git a/model-optimizer/mo/utils/ir_reader/restore_graph.py b/model-optimizer/mo/utils/ir_reader/restore_graph.py index d18aa77089815f..1a4e3cca6df2f1 100644 --- a/model-optimizer/mo/utils/ir_reader/restore_graph.py +++ b/model-optimizer/mo/utils/ir_reader/restore_graph.py @@ -88,4 +88,4 @@ def save_restored_graph(graph: Graph, path: str, meta_data, name=None): for_graph_and_each_sub_graph_recursively(graph, RemoveConstOps().find_and_replace_pattern) for_graph_and_each_sub_graph_recursively(graph, CreateConstNodesReplacement().find_and_replace_pattern) - prepare_emit_ir(graph, data_type, path, name, meta_info=meta_data) + prepare_emit_ir(graph, data_type, path, name, meta_info=meta_data, used_by_ir_reader=True) diff --git a/model-optimizer/mo/utils/runtime_info.py b/model-optimizer/mo/utils/runtime_info.py index 1c61eb0e7fbcf2..3941794686ae83 100644 --- a/model-optimizer/mo/utils/runtime_info.py +++ b/model-optimizer/mo/utils/runtime_info.py @@ -29,6 +29,17 @@ def __init__(self): """ self.info = defaultdict(dict) + def contains(self, attribute_name: str): + attr_count = [key[0] for key in list(self.info.keys())].count(attribute_name) + assert attr_count <= 1, 'Incorrect rt_info attribute, got more than one {}.'.format(attribute_name) + return attr_count > 0 + + def get_attribute_version(self, attribute_name: str): + for name, version in list(self.info.keys()): + if name == attribute_name: + return version + raise Exception("rt_info does not contain attribute with name {}".format(attribute_name)) + class RTInfoElement: """ diff --git a/model-optimizer/unit_tests/extensions/analysis/Iterator_get_next_test.py b/model-optimizer/unit_tests/extensions/analysis/Iterator_get_next_test.py index 801873bdbb996e..05946988c0b72d 100644 --- a/model-optimizer/unit_tests/extensions/analysis/Iterator_get_next_test.py +++ b/model-optimizer/unit_tests/extensions/analysis/Iterator_get_next_test.py @@ -26,8 +26,8 @@ def test_positive(self): inputs_desc = {} message = InputsAnalysis.iterator_get_next_analysis(graph, inputs_desc) ref_message = 'It looks like there is IteratorGetNext as input\n' \ - 'Run the Model Optimizer with:\n\t\t--input "iter_get_next:0[2 2],iter_get_next:1[1 1]"\n' \ - 'And replace all negative values with positive values' + 'Run the Model Optimizer without --input option \n' \ + 'Otherwise, try to run the Model Optimizer with:\n\t\t--input "iter_get_next:0[2 2],iter_get_next:1[1 1]"\n' self.assertEqual(message, ref_message) def test_negative(self): diff --git a/model-optimizer/unit_tests/extensions/back/MatMulNormalizer_test.py b/model-optimizer/unit_tests/extensions/back/MatMulNormalizer_test.py index 30805aa19aa84b..e6b98ce3b91c44 100644 --- a/model-optimizer/unit_tests/extensions/back/MatMulNormalizer_test.py +++ b/model-optimizer/unit_tests/extensions/back/MatMulNormalizer_test.py @@ -15,7 +15,7 @@ from mo.ops.reshape import Reshape from mo.utils.ir_engine.compare_graphs import compare_graphs from unit_tests.utils.graph import build_graph, regular_op_with_shaped_data, valued_const_with_data, \ - result, connect, connect_data + shaped_const_with_data, result, connect, connect_data from unit_tests.utils.graph import regular_op_with_empty_data as op_with_empty_data @@ -101,9 +101,8 @@ def test_reshape_on_the_B_input(self, class FQTransposePullerTest(unittest.TestCase): - def nodes(self, input_shape, transpose_shape, fq_shape): - return { - **regular_op_with_shaped_data('input', input_shape, dict(type='Parameter', op='Parameter')), + def nodes(self, input_shape, transpose_shape, fq_shape, is_input_const): + nodes = { **valued_const_with_data('il', np.array([[[[0]]]])), **valued_const_with_data('ih', np.array([[[[255]]]])), **valued_const_with_data('ol', np.array([[[[0]]]])), @@ -116,8 +115,16 @@ def nodes(self, input_shape, transpose_shape, fq_shape): **result(), } + if is_input_const: + input_node = shaped_const_with_data('input', input_shape) + else: + input_node = regular_op_with_shaped_data('input', input_shape, dict(type='Parameter', op='Parameter')) + + nodes.update(input_node) + return nodes + def test_positive(self): - nodes = self.nodes([1, 3, 224, 224], [1, 224, 224, 3], [1, 3, 224, 224]) + nodes = self.nodes([1, 3, 224, 224], [1, 224, 224, 3], [1, 3, 224, 224], True) edges = [ *connect('input', '0:FQ'), *connect('il', '1:FQ'), @@ -132,7 +139,7 @@ def test_positive(self): PullTransposeThroughFQUp().find_and_replace_pattern(graph) graph.clean_up() - nodes = self.nodes([1, 3, 224, 224], [1, 224, 224, 3], [1, 224, 224, 3]) + nodes = self.nodes([1, 3, 224, 224], [1, 224, 224, 3], [1, 224, 224, 3], True) edges = [ *connect('input', '0:transpose'), *connect('order:0', '1:transpose'), @@ -148,8 +155,8 @@ def test_positive(self): (flag, resp) = compare_graphs(graph, graph_ref, 'output', check_op_attrs=True) self.assertTrue(flag, resp) - def test_negative(self): - nodes = self.nodes([1, 3, 224, 224], [1, 224, 224, 3], [1, 3, 224, 224]) + def test_negative_1(self): + nodes = self.nodes([1, 3, 224, 224], [1, 224, 224, 3], [1, 3, 224, 224], True) edges = [ *connect('input', '0:FQ'), *connect('il', '1:FQ'), @@ -168,3 +175,21 @@ def test_negative(self): (flag, resp) = compare_graphs(graph, graph_ref, 'output', check_op_attrs=True) self.assertTrue(flag, resp) + def test_negative_2(self): + nodes = self.nodes([1, 3, 224, 224], [1, 224, 224, 3], [1, 3, 224, 224], False) + edges = [ + *connect('input', '0:FQ'), + *connect('il', '1:FQ'), + *connect('ih', '2:FQ'), + *connect('ol', '3:FQ'), + *connect('oh', '4:FQ'), + *connect('FQ:0', '0:transpose'), + *connect('order:0', '1:transpose'), + *connect('transpose:0', 'output'), + ] + graph = build_graph(nodes_attrs=nodes, edges=edges, nodes_with_edges_only=True) + graph_ref = graph.copy() + PullTransposeThroughFQUp().find_and_replace_pattern(graph) + + (flag, resp) = compare_graphs(graph, graph_ref, 'output', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/model-optimizer/unit_tests/extensions/back/ReverseInputChannels_test.py b/model-optimizer/unit_tests/extensions/back/ReverseInputChannels_test.py index 634f3ea9aef39c..1b5c8777bc0779 100644 --- a/model-optimizer/unit_tests/extensions/back/ReverseInputChannels_test.py +++ b/model-optimizer/unit_tests/extensions/back/ReverseInputChannels_test.py @@ -3,13 +3,16 @@ import unittest -from extensions.back.ReverseInputChannels import ReverseChannelsPropagationUp, ReverseChannelsPropagationDown +from extensions.back.ReverseInputChannels import ReverseChannelsPropagationUp, ReverseChannelsPropagationDown, \ + InsertReverseChannels +from mo.front.common.partial_infer.utils import int64_array, float32_array from mo.graph.graph import Node, Graph +from mo.utils.ir_engine.compare_graphs import compare_graphs +from mo.utils.runtime_info import OldAPIMap, RTInfo from unit_tests.utils.graph import build_graph, result, connect, regular_op_with_shaped_data, valued_const_with_data -from mo.front.common.partial_infer.utils import int64_array, float32_array nodes = { - **regular_op_with_shaped_data('placeholder1', [1, 3, 10, 10], {'type': 'Parameter'}), + **regular_op_with_shaped_data('placeholder1', [1, 3, 10, 10], {'type': 'Parameter', 'rt_info': RTInfo()}), **regular_op_with_shaped_data('placeholder2', [1, 1, 1, 1], {'type': 'Parameter'}), **regular_op_with_shaped_data('mul', [1, 3, 10, 10], {'type': 'Multiply'}), @@ -35,6 +38,17 @@ **result('result2'), } +nodes3 = { + **regular_op_with_shaped_data('placeholder', [1, 3, 10, 10], {'type': 'Parameter'}), + **regular_op_with_shaped_data('transpose', [1, 3, 10, 10], {'type': 'Transpose'}), + **valued_const_with_data('transpose_order', int64_array([0, 3, 1, 2])), + **regular_op_with_shaped_data('reverse_channels_up', [1, 3, 10, 10], {'type': 'ReverseChannels', 'axis': 3}), + **regular_op_with_shaped_data('reverse_channels_down', [1, 3, 10, 10], {'type': 'ReverseChannels', 'axis': 1}), + **result('result'), + **result('result2'), +} + + class ReverseInputChannelsTest(unittest.TestCase): def check_graph_attrs(self, graph: Graph, parameter_node_names: list): for node in graph.get_op_nodes(): @@ -75,12 +89,11 @@ def test_lift_up_through_pad(self): node = Node(graph, 'pad') reverse_channels = Node(graph, 'reverse_channels') - keep_moving_up, new_reverses = ReverseChannelsPropagationUp.lift_up_through_pad(node, reverse_channels) + keep_moving_up, new_reverses = ReverseChannelsPropagationUp.lift_up_through_zero_port_only(node, reverse_channels) self.assertTrue(keep_moving_up is True) self.assertTrue(len(new_reverses) == 1) self.check_graph_attrs(graph, ['placeholder']) - def test_lift_up_through_pad2(self): graph = build_graph(nodes2, [*connect('placeholder', '0:mul'), *connect('mul_const', '1:mul'), *connect('mul', '0:pad'), *connect('pad_const_1', '1:pad'), @@ -91,12 +104,11 @@ def test_lift_up_through_pad2(self): node = Node(graph, 'pad') reverse_channels = Node(graph, 'reverse_channels') - keep_moving_up, new_reverses = ReverseChannelsPropagationUp.lift_up_through_pad(node, reverse_channels) + keep_moving_up, new_reverses = ReverseChannelsPropagationUp.lift_up_through_zero_port_only(node, reverse_channels) self.assertTrue(keep_moving_up is True) self.assertTrue(len(new_reverses) == 1) self.check_graph_attrs(graph, ['placeholder']) - def test_pass_rc_through(self): graph = build_graph(nodes2, [*connect('placeholder', '0:mul'), *connect('mul_const', '1:mul'), *connect('mul', 'reverse_channels'), *connect('reverse_channels', '0:pad'), @@ -107,5 +119,114 @@ def test_pass_rc_through(self): node = Node(graph, 'pad') reverse_channels = Node(graph, 'reverse_channels') - ReverseChannelsPropagationDown.pass_rc_through(node, reverse_channels) + ReverseChannelsPropagationDown.pass_rc_through_zero_port_only(node, reverse_channels) + self.check_graph_attrs(graph, ['placeholder']) + + def test_lift_up_through_transpose(self): + graph = build_graph(nodes3, [*connect('placeholder', '0:transpose'), *connect('transpose_order', '1:transpose'), + *connect('transpose', 'reverse_channels_down'), + *connect('reverse_channels_down', 'result')]) + graph_ref = build_graph(nodes3, [*connect('placeholder', 'reverse_channels_down'), + *connect('transpose_order', '1:transpose'), + *connect('reverse_channels_down', 'transpose'), + *connect('transpose', 'result')]) + self.set_graph_attrs(graph, ['placeholder']) + + node = Node(graph, 'transpose') + reverse_channels = Node(graph, 'reverse_channels_down') + + keep_moving_up, new_reverses = ReverseChannelsPropagationUp.lift_up_through_transpose(node, reverse_channels) + self.assertTrue(keep_moving_up is True) + self.assertTrue(len(new_reverses) == 1) + self.check_graph_attrs(graph, ['placeholder']) + (flag, resp) = compare_graphs(graph, graph_ref, 'result') + self.assertTrue(flag, resp) + + reverse_channels = Node(graph, 'reverse_channels_down') + self.assertTrue(reverse_channels.axis == 3) + + def test_lift_down_through_transpose(self): + graph = build_graph(nodes3, [*connect('placeholder', 'reverse_channels_up'), + *connect('transpose_order', '1:transpose'), + *connect('reverse_channels_up', '0:transpose'), + *connect('transpose', 'result')]) + graph_ref = build_graph(nodes3, [*connect('placeholder', '0:transpose'), + *connect('transpose_order', '1:transpose'), + *connect('transpose', 'reverse_channels_up'), + *connect('reverse_channels_up', '0:result')]) + self.set_graph_attrs(graph, ['placeholder']) + + node = Node(graph, 'transpose') + reverse_channels = Node(graph, 'reverse_channels_up') + + keep_moving_down = ReverseChannelsPropagationDown.pass_rc_through_transpose(node, reverse_channels) + + self.assertTrue(keep_moving_down is True) self.check_graph_attrs(graph, ['placeholder']) + (flag, resp) = compare_graphs(graph, graph_ref, 'result') + self.assertTrue(flag, resp) + + reverse_channels = Node(graph, 'reverse_channels_down') + self.assertTrue(reverse_channels.axis == 1) + + def test_lift_up_through_transpose_negative_axis(self): + graph = build_graph(nodes3, [*connect('placeholder', '0:transpose'), *connect('transpose_order', '1:transpose'), + *connect('transpose', 'reverse_channels_down'), + *connect('reverse_channels_down', 'result')]) + graph_ref = build_graph(nodes3, [*connect('placeholder', 'reverse_channels_down'), + *connect('transpose_order', '1:transpose'), + *connect('reverse_channels_down', 'transpose'), + *connect('transpose', 'result')]) + self.set_graph_attrs(graph, ['placeholder']) + + node = Node(graph, 'transpose') + reverse_channels = Node(graph, 'reverse_channels_down') + reverse_channels.axis = -3 + + keep_moving_up, new_reverses = ReverseChannelsPropagationUp.lift_up_through_transpose(node, reverse_channels) + self.assertTrue(keep_moving_up is True) + self.assertTrue(len(new_reverses) == 1) + self.check_graph_attrs(graph, ['placeholder']) + (flag, resp) = compare_graphs(graph, graph_ref, 'result') + self.assertTrue(flag, resp) + + reverse_channels = Node(graph, 'reverse_channels_down') + self.assertTrue(reverse_channels.axis == 3) + + def test_lift_down_through_transpose_negative_axis(self): + graph = build_graph(nodes3, [*connect('placeholder', 'reverse_channels_up'), + *connect('transpose_order', '1:transpose'), + *connect('reverse_channels_up', '0:transpose'), + *connect('transpose', 'result')]) + graph_ref = build_graph(nodes3, [*connect('placeholder', '0:transpose'), + *connect('transpose_order', '1:transpose'), + *connect('transpose', 'reverse_channels_up'), + *connect('reverse_channels_up', '0:result')]) + self.set_graph_attrs(graph, ['placeholder']) + + node = Node(graph, 'transpose') + reverse_channels = Node(graph, 'reverse_channels_up') + reverse_channels.axis = -1 + + keep_moving_down = ReverseChannelsPropagationDown.pass_rc_through_transpose(node, reverse_channels) + + self.assertTrue(keep_moving_down is True) + self.check_graph_attrs(graph, ['placeholder']) + (flag, resp) = compare_graphs(graph, graph_ref, 'result') + self.assertTrue(flag, resp) + + reverse_channels = Node(graph, 'reverse_channels_down') + self.assertTrue(reverse_channels.axis == 1) + + def test_get_fw_index(self): + graph = build_graph(nodes, [*connect('placeholder1', 'result')]) + node = Node(graph, 'placeholder1') + old_api_map = OldAPIMap(version=0) + node.rt_info.info[('old_api_map', old_api_map.get_version())] = old_api_map + node.rt_info.info[('old_api_map', old_api_map.get_version())].old_api_transpose_parameter([0, 2, 3, 1]) + self.assertTrue(InsertReverseChannels.get_fw_index(node, 0) == 0) + self.assertTrue(InsertReverseChannels.get_fw_index(node, 1) == 3) + self.assertTrue(InsertReverseChannels.get_fw_index(node, 2) == 1) + self.assertTrue(InsertReverseChannels.get_fw_index(node, 3) == 2) + self.assertTrue(InsertReverseChannels.get_fw_index(node, -2) == 1) + diff --git a/model-optimizer/unit_tests/extensions/back/add_outputs_recursive_test.py b/model-optimizer/unit_tests/extensions/back/add_outputs_recursive_test.py new file mode 100644 index 00000000000000..3073ed1e8bc3f4 --- /dev/null +++ b/model-optimizer/unit_tests/extensions/back/add_outputs_recursive_test.py @@ -0,0 +1,760 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +import numpy as np +import unittest + +from extensions.back.add_outputs_recursive import AddOutputRecursive +from extensions.ops.If import If +from extensions.ops.loop import Loop +from extensions.ops.tensor_iterator import TensorIterator +from mo.front.common.partial_infer.elemental import copy_shape_infer +from mo.front.common.partial_infer.utils import int64_array, dynamic_dimension_value, shape_array +from mo.graph.graph import Node +from unit_tests.utils.graph import build_graph, regular_op_with_empty_data, result, connect, shaped_parameter, \ + valued_const_with_data, shaped_const_with_data, regular_op_with_shaped_data + +# test for Loop +main_graph_nodes = { + **shaped_parameter("IN_1", [1, 4, 64, 54]), + **shaped_parameter("IN_2", [1, 4, 64, 54]), + **valued_const_with_data("M", int64_array([5])), + **valued_const_with_data("cond", int64_array([1])), + **regular_op_with_empty_data("Loop", {'op': "Loop", 'type': 'Loop', 'sub_graphs': ['body'], "body": None, + 'input_port_map': [{'external_port_id': 1, 'internal_layer_id': 2, + 'axis': None}, + {'external_port_id': 2, 'internal_layer_id': 0, + 'axis': None}, + {'external_port_id': 3, 'internal_layer_id': 1, + 'axis': None}], + 'output_port_map': [{'external_port_id': 0, 'internal_layer_id': 4, + 'axis': None}, + {'external_port_id': -1, 'internal_layer_id': 5, + 'axis': None, 'purpose': "execution_condition"}], + 'back_edges': [{'from_layer': 8, 'to_layer': 7}, + {'from_layer': 10, 'to_layer': 9}], + 'infer': Loop.infer}), + **result("OUT_1") +} + +sub_graph_1_nodes = { + **shaped_parameter("IN_2", int64_array([1, 4, 64, 54]), {'internal_layer_id': 0}), + **valued_const_with_data("M_2", int64_array([10])), + **valued_const_with_data("cond_2", int64_array([1])), + **regular_op_with_empty_data("Loop_2", {'op': "Loop", 'type': 'Loop', 'sub_graphs': ['body'], "body": None, + 'input_port_map': [{'external_port_id': 1, 'internal_layer_id': 0, + 'axis': None}, + {'external_port_id': 2, 'internal_layer_id': 2, + 'axis': None}], + 'output_port_map': [{'external_port_id': 0, 'internal_layer_id': 7, + 'axis': None}, + {'external_port_id': -1, 'internal_layer_id': 6, + 'axis': None, + 'purpose': "execution_condition"}], + 'back_edges': [{'from_layer': 1, 'to_layer': 0}, + {'from_layer': 8, 'to_layer': 2}], + 'infer': Loop.infer}), + **regular_op_with_empty_data('Loop_2_out', {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, + 'internal_layer_id': 3}), + **shaped_parameter("in_1_int", int64_array([1, 4, 64, 54]), {'internal_layer_id': 1}), + **regular_op_with_empty_data("in_1_int_out", + {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, 'internal_layer_id': 4}), + **shaped_parameter("cond_1_int", int64_array([1]), {'internal_layer_id': 2}), + **regular_op_with_empty_data("cond_1_int_out", {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, + 'internal_layer_id': 5}), +} + +sub_graph_2_nodes = { + **shaped_parameter('cond_2_int', [1, 4, 64, 54], {'internal_layer_id': 0}), + **result("cond_2_int_out"), + **shaped_parameter('in_2_int', [1, 4, 64, 54], {'internal_layer_id': 1}), + **shaped_const_with_data('ones', int64_array([1, 4, 64, 54])), + **regular_op_with_shaped_data('OUT_2', int64_array([1, 4, 64, 54]), {'op': "Add", 'infer': copy_shape_infer}), + **regular_op_with_empty_data('OUT_2_out', + {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, 'internal_layer_id': 7}), + **regular_op_with_shaped_data('in_2_int_out', int64_array([1, 4, 64, 54]), + {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, 'internal_layer_id': 6}) +} + + +class AddOutputRecursiveTest(unittest.TestCase): + + def test_add_output_1(self): + sub_graph_2 = build_graph(nodes_attrs=sub_graph_2_nodes, + edges=[*connect('cond_2_int', 'cond_2_int_out'), + *connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out'), + *connect('in_2_int', 'in_2_int_out')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=sub_graph_1_nodes, + edges=[*connect('M_2', '0:Loop_2'), + *connect('cond_2', '1:Loop_2'), + *connect('IN_2', '2:Loop_2'), + *connect('Loop_2:0', 'Loop_2_out'), + *connect('in_1_int', 'in_1_int_out'), + *connect('cond_1_int', 'cond_1_int_out')], + nodes_with_edges_only=True) + loop_node_1 = Node(sub_graph_1, 'Loop_2') + loop_node_1.body = sub_graph_2 + + main_graph = build_graph(nodes_attrs=main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + main_graph.graph['additional_outputs'] = ['Loop', 'Loop_2'] + loop_node_output_port_map_len = len(loop_node.output_port_map) + loop_node_out_ports_len = len(loop_node.out_ports()) + loop_2_out_ports_len = len(loop_node_1.out_ports()) + max_layer_id = 5 + + + AddOutputRecursive().find_and_replace_pattern(main_graph) + + loop_node = Node(main_graph, 'Loop') + self.assertEqual(len(loop_node.output_port_map), loop_node_output_port_map_len + 1) + self.assertEqual(len(loop_node.out_ports()), loop_node_out_ports_len + 1) + self.assertEqual(loop_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(loop_node.out_port(1).data.get_shape() == int64_array([5, 10, 4, 64, 54]))) + last_node = Node(sub_graph_1, 'Loop_2') + self.assertEqual(len(last_node.out_ports()), loop_2_out_ports_len) + unsq_node = last_node.out_port(0).get_destinations()[1].node + self.assertEqual(unsq_node.op, 'Unsqueeze') + self.assertEqual(unsq_node.out_port(0).get_destination().node.op, 'Result') + self.assertEqual(unsq_node.out_port(0).get_destination().node.internal_layer_id, max_layer_id + 3) + self.assertTrue(np.all(unsq_node.out_port(0).data.get_shape() == int64_array([1, 10, 4, 64, 54]))) + + +# test for TensorIterator +ti_main_graph_nodes = { + **shaped_parameter("IN_1", [1, 4, 64, 54]), + **shaped_parameter("IN_2", [1, 4, 64, 54]), + **valued_const_with_data("M", int64_array([5])), + **valued_const_with_data("cond", int64_array([1])), + **regular_op_with_empty_data("Loop", {'op': "TensorIterator", 'type': 'TensorIterator', + 'sub_graphs': ['body'], "body": None, + 'input_port_map': [{'external_port_id': 1, 'internal_layer_id': 2, 'axis': None}, + {'external_port_id': 2, 'internal_layer_id': 0, 'axis': None}, + {'external_port_id': 3, 'internal_layer_id': 1, 'axis': None}], + 'output_port_map': [{'external_port_id': 4, 'internal_layer_id': 4, 'axis': None}], + 'back_edges': [{'from_layer': 8, 'to_layer': 7}, + {'from_layer': 10, 'to_layer': 9}], + 'infer': TensorIterator.infer}), + **result("OUT_1") +} + +ti_sub_graph_1_nodes = { + **shaped_parameter("IN_2", int64_array([1, 4, 64, 54]), {'internal_layer_id': 0}), + **valued_const_with_data("cond_2", int64_array([1])), + **regular_op_with_empty_data("Loop_2", {'op': "TensorIterator", 'type': 'TensorIterator', + 'sub_graphs': ['body'], "body": None, + 'input_port_map': [{'external_port_id': 1, 'internal_layer_id': 0, 'axis': None}, + {'external_port_id': 0, 'internal_layer_id': 1, 'axis': 0}], + 'output_port_map': [{'external_port_id': 2, 'internal_layer_id': 7, + 'axis': None}, + ], + 'back_edges': [{'from_layer': 1, 'to_layer': 0}, + {'from_layer': 8, 'to_layer': 2}], + 'infer': TensorIterator.infer}), + **regular_op_with_empty_data('Loop_2_out', {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, + 'internal_layer_id': 3}), + **shaped_parameter("in_1_int", int64_array([1, 4, 64, 54]), {'internal_layer_id': 1}), + **regular_op_with_empty_data("in_1_int_out", {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, + 'internal_layer_id': 4}), + **shaped_parameter("cond_1_int", int64_array([1]), {'internal_layer_id': 2}), + **regular_op_with_empty_data("cond_1_int_out", {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, + 'internal_layer_id': 5}), +} + +ti_sub_graph_2_nodes = { + **shaped_parameter('cond_2_int', [1, 4, 64, 54], {'internal_layer_id': 0}), + **result("cond_2_int_out"), + **shaped_parameter('in_2_int', [1, 4, 64, 54], {'internal_layer_id': 1}), + **shaped_const_with_data('ones', int64_array([1, 4, 64, 54])), + **regular_op_with_shaped_data('OUT_2', int64_array([1, 4, 64, 54]), + {'op': "Add", 'infer': copy_shape_infer}), + **regular_op_with_empty_data('OUT_2_out', {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, + 'internal_layer_id': 7}), + **regular_op_with_empty_data('in_2_int_out', {'op': 'Result', 'type': 'Result', 'infer': lambda x: None, + 'internal_layer_id': 6}) +} + + +class TI_AddOutputRecursiveTest(unittest.TestCase): + + def test_add_output_1(self): + sub_graph_2 = build_graph(nodes_attrs=ti_sub_graph_2_nodes, + edges=[*connect('cond_2_int', 'cond_2_int_out'), + *connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out'), + *connect('in_2_int', 'in_2_int_out')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=ti_sub_graph_1_nodes, + edges=[*connect('cond_2', '1:Loop_2'), + *connect('IN_2', '0:Loop_2'), + *connect('Loop_2:0', 'Loop_2_out'), + *connect('in_1_int', 'in_1_int_out'), + *connect('cond_1_int', 'cond_1_int_out')], + nodes_with_edges_only=True) + loop_node_1 = Node(sub_graph_1, 'Loop_2') + loop_node_1.body = sub_graph_2 + loop_node_1.in_edge(0)['external_port_id'] = 0 + loop_node_1.in_edge(1)['external_port_id'] = 1 + loop_node_1.out_edge(0)['external_port_id'] = 2 + + main_graph = build_graph(nodes_attrs=ti_main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + loop_node.in_edge(0)['external_port_id'] = 0 + loop_node.in_edge(1)['external_port_id'] = 1 + loop_node.in_edge(2)['external_port_id'] = 2 + loop_node.in_edge(3)['external_port_id'] = 3 + loop_node.out_edge(0)['external_port_id'] = 4 + loop_node_output_port_map_len = len(loop_node.output_port_map) + loop_node_out_ports_len = len(loop_node.out_ports()) + loop_2_node_out_ports_len = len(loop_node_1.out_ports()) + max_layer_id = 5 + + + main_graph.graph['additional_outputs'] = ['Loop', 'Loop_2'] + + AddOutputRecursive().find_and_replace_pattern(main_graph) + loop_node = Node(main_graph, 'Loop') + self.assertEqual(len(loop_node.output_port_map), loop_node_output_port_map_len + 1) + self.assertEqual(len(loop_node.out_ports()), loop_node_out_ports_len + 1) + self.assertEqual(loop_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(loop_node.out_port(1).data.get_shape() == int64_array([1, 1, 4, 64, 54]))) + last_node = Node(sub_graph_1, 'Loop_2') + self.assertEqual(len(last_node.out_ports()), loop_2_node_out_ports_len) + unsq_node = last_node.out_port(0).get_destinations()[1].node + self.assertEqual(unsq_node.op, 'Unsqueeze') + self.assertEqual(unsq_node.out_port(0).get_destination().node.op, 'Result') + self.assertEqual(unsq_node.out_port(0).get_destination().node.internal_layer_id, max_layer_id + 3) + self.assertTrue(np.all(unsq_node.out_port(0).data.get_shape() == int64_array([1, 1, 4, 64, 54]))) + + def test_add_output_dynamic(self): + sub_graph_2 = build_graph(nodes_attrs=ti_sub_graph_2_nodes, + edges=[*connect('cond_2_int', 'cond_2_int_out'), + *connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out'), + *connect('in_2_int', 'in_2_int_out')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=ti_sub_graph_1_nodes, + edges=[*connect('cond_2', '1:Loop_2'), + *connect('IN_2', '0:Loop_2'), + *connect('Loop_2:0', 'Loop_2_out'), + *connect('in_1_int', 'in_1_int_out'), + *connect('cond_1_int', 'cond_1_int_out')], + nodes_with_edges_only=True) + loop_node_1 = Node(sub_graph_1, 'Loop_2') + loop_node_1.body = sub_graph_2 + loop_node_1.in_edge(0)['external_port_id'] = 0 + loop_node_1.in_edge(1)['external_port_id'] = 1 + loop_node_1.out_edge(0)['external_port_id'] = 2 + + main_graph = build_graph(nodes_attrs=ti_main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + loop_node.in_edge(0)['external_port_id'] = 0 + loop_node.in_edge(1)['external_port_id'] = 1 + loop_node.in_edge(2)['external_port_id'] = 2 + loop_node.in_edge(3)['external_port_id'] = 3 + loop_node.out_edge(0)['external_port_id'] = 4 + loop_node_output_port_map_len = len(loop_node.output_port_map) + loop_node_out_ports_len = len(loop_node.out_ports()) + loop_2_node_out_ports_len = len(loop_node_1.out_ports()) + max_layer_id = 5 + loop_node.input_port_map[2]['axis'] = 1 + loop_node.input_port_map[2]['start'] = 0 + loop_node.input_port_map[2]['end'] = -1 + loop_node.input_port_map[2]['stride'] = 1 + in_1_node = Node(main_graph, 'IN_1') + in_1_node['shape'] = shape_array([1, dynamic_dimension_value, 64, 54]) + + main_graph.graph['additional_outputs'] = ['Loop', 'Loop_2'] + + AddOutputRecursive().find_and_replace_pattern(main_graph) + loop_node = Node(main_graph, 'Loop') + self.assertEqual(len(loop_node.output_port_map), loop_node_output_port_map_len + 1) + self.assertEqual(len(loop_node.out_ports()), loop_node_out_ports_len + 1) + self.assertEqual(loop_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(loop_node.out_port(1).data.get_shape() == + shape_array([dynamic_dimension_value, 1, 4, 64, 54]))) + last_node = Node(sub_graph_1, 'Loop_2') + self.assertEqual(len(last_node.out_ports()), loop_2_node_out_ports_len) + unsq_node = last_node.out_port(0).get_destinations()[1].node + self.assertEqual(unsq_node.op, 'Unsqueeze') + self.assertEqual(unsq_node.out_port(0).get_destination().node.op, 'Result') + self.assertEqual(unsq_node.out_port(0).get_destination().node.internal_layer_id, max_layer_id + 3) + self.assertTrue(np.all(unsq_node.out_port(0).data.get_shape() == int64_array([1, 1, 4, 64, 54]))) + + def test_add_output_several_iterations(self): + sub_graph_2 = build_graph(nodes_attrs=ti_sub_graph_2_nodes, + edges=[*connect('cond_2_int', 'cond_2_int_out'), + *connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out'), + *connect('in_2_int', 'in_2_int_out')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=ti_sub_graph_1_nodes, + edges=[*connect('cond_2', '1:Loop_2'), + *connect('IN_2', '0:Loop_2'), + *connect('Loop_2:0', 'Loop_2_out'), + *connect('in_1_int', 'in_1_int_out'), + *connect('cond_1_int', 'cond_1_int_out')], + nodes_with_edges_only=True) + loop_node_1 = Node(sub_graph_1, 'Loop_2') + loop_node_1.body = sub_graph_2 + loop_node_1.in_edge(0)['external_port_id'] = 0 + loop_node_1.in_edge(1)['external_port_id'] = 1 + loop_node_1.out_edge(0)['external_port_id'] = 2 + + main_graph = build_graph(nodes_attrs=ti_main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + loop_node.in_edge(0)['external_port_id'] = 0 + loop_node.in_edge(1)['external_port_id'] = 1 + loop_node.in_edge(2)['external_port_id'] = 2 + loop_node.in_edge(3)['external_port_id'] = 3 + loop_node.out_edge(0)['external_port_id'] = 4 + loop_node_output_port_map_len = len(loop_node.output_port_map) + loop_node_out_ports_len = len(loop_node.out_ports()) + loop_2_node_out_ports_len = len(loop_node_1.out_ports()) + max_layer_id = 5 + loop_node.input_port_map[2]['axis'] = 1 + loop_node.input_port_map[2]['start'] = 0 + loop_node.input_port_map[2]['end'] = -1 + loop_node.input_port_map[2]['stride'] = 1 + loop_node.output_port_map[0]['axis'] = 1 + loop_node.output_port_map[0]['start'] = 0 + loop_node.output_port_map[0]['end'] = 10 + loop_node.output_port_map[0]['stride'] = 2 + + main_graph.graph['additional_outputs'] = ['Loop', 'Loop_2'] + + AddOutputRecursive().find_and_replace_pattern(main_graph) + loop_node = Node(main_graph, 'Loop') + self.assertEqual(len(loop_node.output_port_map), loop_node_output_port_map_len + 1) + self.assertEqual(len(loop_node.out_ports()), loop_node_out_ports_len + 1) + self.assertEqual(loop_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(loop_node.out_port(1).data.get_shape() == shape_array([4, 1, 4, 64, 54]))) + self.assertTrue(np.all(loop_node.out_port(0).data.get_shape() == shape_array([1, 5, 64, 54]))) + last_node = Node(sub_graph_1, 'Loop_2') + self.assertEqual(len(last_node.out_ports()), loop_2_node_out_ports_len) + unsq_node = last_node.out_port(0).get_destinations()[1].node + self.assertEqual(unsq_node.op, 'Unsqueeze') + self.assertEqual(unsq_node.out_port(0).get_destination().node.op, 'Result') + self.assertEqual(unsq_node.out_port(0).get_destination().node.internal_layer_id, max_layer_id + 3) + self.assertTrue(np.all(unsq_node.out_port(0).data.get_shape() == int64_array([1, 1, 4, 64, 54]))) + + def test_add_output_several_iterations_wo_start_end(self): + sub_graph_2 = build_graph(nodes_attrs=ti_sub_graph_2_nodes, + edges=[*connect('cond_2_int', 'cond_2_int_out'), + *connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out'), + *connect('in_2_int', 'in_2_int_out')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=ti_sub_graph_1_nodes, + edges=[*connect('cond_2', '1:Loop_2'), + *connect('IN_2', '0:Loop_2'), + *connect('Loop_2:0', 'Loop_2_out'), + *connect('in_1_int', 'in_1_int_out'), + *connect('cond_1_int', 'cond_1_int_out')], + nodes_with_edges_only=True) + loop_node_1 = Node(sub_graph_1, 'Loop_2') + loop_node_1.body = sub_graph_2 + loop_node_1.in_edge(0)['external_port_id'] = 0 + loop_node_1.in_edge(1)['external_port_id'] = 1 + loop_node_1.out_edge(0)['external_port_id'] = 2 + + main_graph = build_graph(nodes_attrs=ti_main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + loop_node.in_edge(0)['external_port_id'] = 0 + loop_node.in_edge(1)['external_port_id'] = 1 + loop_node.in_edge(2)['external_port_id'] = 2 + loop_node.in_edge(3)['external_port_id'] = 3 + loop_node.out_edge(0)['external_port_id'] = 4 + loop_node_output_port_map_len = len(loop_node.output_port_map) + loop_node_out_ports_len = len(loop_node.out_ports()) + loop_2_node_out_ports_len = len(loop_node_1.out_ports()) + max_layer_id = 5 + loop_node.input_port_map[2]['axis'] = 1 + loop_node.input_port_map[2]['stride'] = 1 + + main_graph.graph['additional_outputs'] = ['Loop', 'Loop_2'] + + AddOutputRecursive().find_and_replace_pattern(main_graph) + loop_node = Node(main_graph, 'Loop') + self.assertEqual(len(loop_node.output_port_map), loop_node_output_port_map_len + 1) + self.assertEqual(len(loop_node.out_ports()), loop_node_out_ports_len + 1) + self.assertEqual(loop_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(loop_node.out_port(1).data.get_shape() == shape_array([4, 1, 4, 64, 54]))) + last_node = Node(sub_graph_1, 'Loop_2') + self.assertEqual(len(last_node.out_ports()), loop_2_node_out_ports_len) + unsq_node = last_node.out_port(0).get_destinations()[1].node + self.assertEqual(unsq_node.op, 'Unsqueeze') + self.assertEqual(unsq_node.out_port(0).get_destination().node.op, 'Result') + self.assertEqual(unsq_node.out_port(0).get_destination().node.internal_layer_id, max_layer_id + 3) + self.assertTrue(np.all(unsq_node.out_port(0).data.get_shape() == int64_array([1, 1, 4, 64, 54]))) + + def test_add_output_several_iterations_negative_end(self): + sub_graph_2 = build_graph(nodes_attrs=ti_sub_graph_2_nodes, + edges=[*connect('cond_2_int', 'cond_2_int_out'), + *connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out'), + *connect('in_2_int', 'in_2_int_out')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=ti_sub_graph_1_nodes, + edges=[*connect('cond_2', '1:Loop_2'), + *connect('IN_2', '0:Loop_2'), + *connect('Loop_2:0', 'Loop_2_out'), + *connect('in_1_int', 'in_1_int_out'), + *connect('cond_1_int', 'cond_1_int_out')], + nodes_with_edges_only=True) + loop_node_1 = Node(sub_graph_1, 'Loop_2') + loop_node_1.body = sub_graph_2 + loop_node_1.in_edge(0)['external_port_id'] = 0 + loop_node_1.in_edge(1)['external_port_id'] = 1 + loop_node_1.out_edge(0)['external_port_id'] = 2 + + main_graph = build_graph(nodes_attrs=ti_main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + loop_node.in_edge(0)['external_port_id'] = 0 + loop_node.in_edge(1)['external_port_id'] = 1 + loop_node.in_edge(2)['external_port_id'] = 2 + loop_node.in_edge(3)['external_port_id'] = 3 + loop_node.out_edge(0)['external_port_id'] = 4 + loop_node_output_port_map_len = len(loop_node.output_port_map) + loop_node_out_ports_len = len(loop_node.out_ports()) + loop_2_node_out_ports_len = len(loop_node_1.out_ports()) + max_layer_id = 5 + loop_node.input_port_map[2]['axis'] = 1 + loop_node.input_port_map[2]['start'] = 0 + loop_node.input_port_map[2]['end'] = -3 + loop_node.input_port_map[2]['stride'] = 1 + loop_node.output_port_map[0]['axis'] = 1 + loop_node.output_port_map[0]['start'] = 0 + loop_node.output_port_map[0]['end'] = -1 + loop_node.output_port_map[0]['stride'] = 2 + + main_graph.graph['additional_outputs'] = ['Loop', 'Loop_2'] + + AddOutputRecursive().find_and_replace_pattern(main_graph) + loop_node = Node(main_graph, 'Loop') + self.assertEqual(len(loop_node.output_port_map), loop_node_output_port_map_len + 1) + self.assertEqual(len(loop_node.out_ports()), loop_node_out_ports_len + 1) + self.assertEqual(loop_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(loop_node.out_port(1).data.get_shape() == shape_array([2, 1, 4, 64, 54]))) + self.assertTrue(np.all(loop_node.out_port(0).data.get_shape() == shape_array([1, 2, 64, 54]))) + last_node = Node(sub_graph_1, 'Loop_2') + self.assertEqual(len(last_node.out_ports()), loop_2_node_out_ports_len) + unsq_node = last_node.out_port(0).get_destinations()[1].node + self.assertEqual(unsq_node.op, 'Unsqueeze') + self.assertEqual(unsq_node.out_port(0).get_destination().node.op, 'Result') + self.assertEqual(unsq_node.out_port(0).get_destination().node.internal_layer_id, max_layer_id + 3) + self.assertTrue(np.all(unsq_node.out_port(0).data.get_shape() == int64_array([1, 1, 4, 64, 54]))) + + def test_add_output_several_iterations_negative_stride(self): + sub_graph_2 = build_graph(nodes_attrs=ti_sub_graph_2_nodes, + edges=[*connect('cond_2_int', 'cond_2_int_out'), + *connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out'), + *connect('in_2_int', 'in_2_int_out')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=ti_sub_graph_1_nodes, + edges=[*connect('cond_2', '1:Loop_2'), + *connect('IN_2', '0:Loop_2'), + *connect('Loop_2:0', 'Loop_2_out'), + *connect('in_1_int', 'in_1_int_out'), + *connect('cond_1_int', 'cond_1_int_out')], + nodes_with_edges_only=True) + loop_node_1 = Node(sub_graph_1, 'Loop_2') + loop_node_1.body = sub_graph_2 + loop_node_1.in_edge(0)['external_port_id'] = 0 + loop_node_1.in_edge(1)['external_port_id'] = 1 + loop_node_1.out_edge(0)['external_port_id'] = 2 + + main_graph = build_graph(nodes_attrs=ti_main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + loop_node.in_edge(0)['external_port_id'] = 0 + loop_node.in_edge(1)['external_port_id'] = 1 + loop_node.in_edge(2)['external_port_id'] = 2 + loop_node.in_edge(3)['external_port_id'] = 3 + loop_node.out_edge(0)['external_port_id'] = 4 + loop_node_output_port_map_len = len(loop_node.output_port_map) + loop_node_out_ports_len = len(loop_node.out_ports()) + loop_2_node_out_ports_len = len(loop_node_1.out_ports()) + max_layer_id = 5 + loop_node.input_port_map[2]['axis'] = 1 + loop_node.input_port_map[2]['start'] = -1 + loop_node.input_port_map[2]['end'] = 0 + loop_node.input_port_map[2]['stride'] = -2 + loop_node.output_port_map[0]['axis'] = 1 + loop_node.output_port_map[0]['start'] = 0 + loop_node.output_port_map[0]['end'] = -1 + loop_node.output_port_map[0]['stride'] = 2 + + main_graph.graph['additional_outputs'] = ['Loop', 'Loop_2'] + + AddOutputRecursive().find_and_replace_pattern(main_graph) + loop_node = Node(main_graph, 'Loop') + self.assertEqual(len(loop_node.output_port_map), loop_node_output_port_map_len + 1) + self.assertEqual(len(loop_node.out_ports()), loop_node_out_ports_len + 1) + self.assertEqual(loop_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(loop_node.out_port(1).data.get_shape() == shape_array([2, 1, 4, 64, 54]))) + self.assertTrue(np.all(loop_node.out_port(0).data.get_shape() == shape_array([1, 2, 64, 54]))) + last_node = Node(sub_graph_1, 'Loop_2') + self.assertEqual(len(last_node.out_ports()), loop_2_node_out_ports_len) + unsq_node = last_node.out_port(0).get_destinations()[1].node + self.assertEqual(unsq_node.op, 'Unsqueeze') + self.assertEqual(unsq_node.out_port(0).get_destination().node.op, 'Result') + self.assertEqual(unsq_node.out_port(0).get_destination().node.internal_layer_id, max_layer_id + 3) + self.assertTrue(np.all(unsq_node.out_port(0).data.get_shape() == int64_array([1, 1, 4, 64, 54]))) + + + +# test for If +if_main_graph_nodes = { + **shaped_parameter("IN_1", [1, 4, 64, 54]), + **shaped_parameter("IN_2", [1, 4, 64, 54]), + **valued_const_with_data("cond", int64_array([1])), + **regular_op_with_empty_data("If", {'op': "If", 'type': 'If', 'sub_graphs': ['then_graph', 'else_graph'], + "then_graph": None, 'else_graph': None, 'infer': If.infer}), + **result("OUT_1") +} + +if_sub_graph_1_then_nodes = { + **shaped_parameter("IN_2", int64_array([1, 4, 64, 54]), {'input_id': 2}), + **valued_const_with_data("cond_2", int64_array([1])), + **regular_op_with_empty_data("If_2", {'op': "If", 'type': 'If', 'sub_graphs': ['then_graph', 'else_graph'], + "then_graph": None, 'else_graph': None, 'infer': If.infer}), + **regular_op_with_empty_data('If_2_out', {'op': 'Result', 'type': 'Result', 'infer': lambda x: None}), + **shaped_parameter("in_1_int", int64_array([1, 4, 64, 54]), {'input_id': 1}), + **regular_op_with_empty_data("in_1_int_out", {'op': 'Result', 'type': 'Result', 'output_id': 0}) +} + +if_sub_graph_1_else_nodes = { + **shaped_parameter("in_1_int", int64_array([1, 4, 64, 54]), {'input_id': 1}), + **regular_op_with_empty_data("in_1_int_out", {'op': 'Result', 'type': 'Result', 'output_id': 0}) +} + +if_sub_graph_2_then_nodes = { + **shaped_parameter('in_2_int', [1, 4, 64, 54], {'input_id': 1}), + **shaped_const_with_data('ones', int64_array([1, 4, 64, 54])), + **regular_op_with_shaped_data('OUT_2', int64_array([1, 4, 64, 54]), {'op': "Add"}), + **regular_op_with_empty_data('OUT_2_out', {'op': 'Result', 'type': 'Result', 'output_id': 0}), +} + +if_sub_graph_2_else_nodes = { + **shaped_parameter('in_2_int_else', [1, 4, 64, 54], {'input_id': 1}), + **shaped_const_with_data('ones_else', int64_array([1, 4, 64, 54])), + **regular_op_with_shaped_data('OUT_2_else', int64_array([1, 4, 64, 54]), {'op': "Sub"}), + **regular_op_with_empty_data('OUT_2_out_else', {'op': 'Result', 'type': 'Result', 'output_id': 0}), +} + + +class IF_AddOutputRecursiveTest(unittest.TestCase): + + def test_add_output_1(self): + sub_graph_2 = build_graph(nodes_attrs=if_sub_graph_2_then_nodes, + edges=[*connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out')], + nodes_with_edges_only=True) + + sub_graph_2_else = build_graph(nodes_attrs=if_sub_graph_2_else_nodes, + edges=[*connect('in_2_int_else', 'OUT_2_else'), + *connect('ones_else', 'OUT_2_else'), + *connect('OUT_2_else', 'OUT_2_out_else')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=if_sub_graph_1_then_nodes, + edges=[*connect('cond_2', '0:If_2'), + *connect('IN_2', '1:If_2'), + *connect('If_2:0', 'If_2_out'), + *connect('in_1_int', 'in_1_int_out')], + nodes_with_edges_only=True) + if_node_1 = Node(sub_graph_1, 'If_2') + if_node_1.then_graph = sub_graph_2 + if_node_1.else_graph = sub_graph_2_else + + sub_graph_1_else = build_graph(nodes_attrs=if_sub_graph_1_else_nodes, + edges=[*connect('in_1_int', 'in_1_int_out')], + nodes_with_edges_only=True) + + main_graph = build_graph(nodes_attrs=if_main_graph_nodes, + edges=[*connect('cond', '0:If'), + *connect('IN_1', '1:If'), + *connect('IN_2', "2:If"), + *connect('If:0', 'OUT_1')], + nodes_with_edges_only=True) + if_node = Node(main_graph, 'If') + if_node.then_graph = sub_graph_1 + if_node.else_graph = sub_graph_1_else + if_node_out_ports_len = len(if_node.out_ports()) + if_2_node_out_ports_len = len(if_node_1.out_ports()) + + main_graph.graph['additional_outputs'] = ['If', ['If_2', 'in_1_int']] + + AddOutputRecursive().find_and_replace_pattern(main_graph) + if_node = Node(main_graph, 'If') + self.assertEqual(len(if_node.out_ports()), if_node_out_ports_len + 1) + self.assertEqual(if_node.out_port(1).get_destination().node.op, 'Result') + self.assertTrue(np.all(if_node.out_port(1).data.get_shape() == int64_array([1, 4, 64, 54]))) + last_node = Node(sub_graph_1, 'If_2') + self.assertEqual(len(last_node.out_ports()), if_2_node_out_ports_len) + self.assertEqual(last_node.out_port(0).get_destinations()[1].node.op, 'Result') + self.assertTrue(np.all(last_node.out_port(0).data.get_shape() == int64_array([1, 4, 64, 54]))) + + +class SplitUserPathTest(unittest.TestCase): + + @staticmethod + def create_graph(): + sub_graph_2 = build_graph(nodes_attrs=if_sub_graph_2_then_nodes, + edges=[*connect('in_2_int', 'OUT_2'), + *connect('ones', 'OUT_2'), + *connect('OUT_2', 'OUT_2_out')], + nodes_with_edges_only=True) + + sub_graph_2_else = build_graph(nodes_attrs=if_sub_graph_2_else_nodes, + edges=[*connect('in_2_int_else', 'OUT_2_else'), + *connect('ones_else', 'OUT_2_else'), + *connect('OUT_2_else', 'OUT_2_out_else')], + nodes_with_edges_only=True) + + sub_graph_1 = build_graph(nodes_attrs=if_sub_graph_1_then_nodes, + edges=[*connect('cond_2', '0:If_2'), + *connect('IN_2', '1:If_2'), + *connect('If_2:0', 'If_2_out'), + *connect('in_1_int', 'in_1_int_out')], + nodes_with_edges_only=True) + if_node_1 = Node(sub_graph_1, 'If_2') + if_node_1.then_graph = sub_graph_2 + if_node_1.else_graph = sub_graph_2_else + out_node = Node(sub_graph_1, 'If_2_out') + out_node['internal_layer_id'] = 4 + + main_graph = build_graph(nodes_attrs=ti_main_graph_nodes, + edges=[*connect('M', '0:Loop'), + *connect('cond', '1:Loop'), + *connect('IN_2', '2:Loop'), + *connect('IN_1', "3:Loop"), + *connect('Loop:0', 'OUT_1')], + nodes_with_edges_only=True) + loop_node = Node(main_graph, 'Loop') + loop_node.body = sub_graph_1 + loop_node.in_edge(0)['external_port_id'] = 0 + loop_node.in_edge(1)['external_port_id'] = 1 + loop_node.in_edge(2)['external_port_id'] = 2 + loop_node.in_edge(3)['external_port_id'] = 3 + loop_node.out_edge(0)['external_port_id'] = 4 + + return main_graph + + def test_linear_graph_change(self): + graph = self.create_graph() + path = ['Loop', 'in_1_int'] + ref_path = [] + loop_node = Node(graph, 'Loop') + ref_path.append({'node': loop_node, 'graph': graph}) + ref_path.append({'node': Node(loop_node.body, 'in_1_int'), 'graph': loop_node.body}) + + tracks = AddOutputRecursive().split_path_to_simple_tracks(graph, path) + + self.assertTrue(np.all(tracks[0] == ref_path)) + + def test_1_if_graph_change(self): + graph = self.create_graph() + path = ['Loop', 'If_2', ['OUT_2', 'OUT_2_else']] + ref_path = [[]] + loop_node = Node(graph, 'Loop') + ref_path[0].append({'node': loop_node, 'graph': graph}) + if_node = Node(loop_node.body, 'If_2') + ref_path[0].append({'node': if_node, 'graph': loop_node.body}) + ref_path.append([]) + ref_path[1] = ref_path[0][:] + ref_path[0].append({'node': Node(if_node.then_graph, 'OUT_2'), 'graph': if_node.then_graph}) + ref_path[1].append({'node': Node(if_node.else_graph, 'OUT_2_else'), 'graph': if_node.else_graph}) + + tracks = AddOutputRecursive().split_path_to_simple_tracks(graph, path) + + self.assertTrue(np.all(tracks[0] == ref_path[0])) + self.assertTrue(np.all(tracks[1] == ref_path[1])) + + def test_1_if_graph_change_add_output(self): + graph = self.create_graph() + graph.graph['additional_outputs'] = ['Loop', 'If_2', ['OUT_2', 'OUT_2_else']] + + AddOutputRecursive().find_and_replace_pattern(graph) + + loop_node = Node(graph, 'Loop') + if_node = Node(loop_node.body, 'If_2') + left_node = Node(if_node.then_graph, 'OUT_2') + right_node = Node(if_node.else_graph, 'OUT_2_else') + self.assertEqual(len(left_node.out_port(0).get_destinations()), 2) + self.assertEqual(left_node.out_port(0).get_destinations()[1].node.op, 'Result') + + self.assertEqual(len(right_node.out_port(0).get_destinations()), 2) + self.assertEqual(right_node.out_port(0).get_destinations()[1].node.op, 'Result') + + self.assertTrue(len(if_node.out_ports()), 2) + self.assertTrue(if_node.out_port(1).get_destination().node.op, 'Result') + + self.assertTrue(len(loop_node.out_ports()), 2) + self.assertTrue(loop_node.out_port(1).get_destination().node.op, 'Result') diff --git a/model-optimizer/unit_tests/extensions/front/tf/IteratorGetNextCut_test.py b/model-optimizer/unit_tests/extensions/front/tf/IteratorGetNextCut_test.py new file mode 100644 index 00000000000000..165e5189fc7fc1 --- /dev/null +++ b/model-optimizer/unit_tests/extensions/front/tf/IteratorGetNextCut_test.py @@ -0,0 +1,95 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import unittest + +import numpy as np + +from extensions.front.tf.IteratorGetNextCut import IteratorGetNextCut +from mo.front.common.partial_infer.utils import shape_array +from mo.utils.error import Error +from mo.utils.ir_engine.compare_graphs import compare_graphs +from unit_tests.utils.graph import build_graph_with_edge_attrs + + +class IteratorGetNextAnalysisTest(unittest.TestCase): + + def test_one_output(self): + graph = build_graph_with_edge_attrs( + { + 'iter_get_next': {'kind': 'op', 'op': 'IteratorGetNext', 'shapes': shape_array([[2, 2]]), + 'types': [np.int32]}, + 'sub': {'kind': 'op', 'op': 'Sub'}, + }, + [ + ('iter_get_next', 'sub', {'out': 0, 'in': 0}), + ] + ) + + graph_ref = build_graph_with_edge_attrs( + { + 'parameter_1': {'kind': 'op', 'op': 'Parameter', 'shape': shape_array([2, 2]), 'type': np.int32}, + 'sub': {'kind': 'op', 'op': 'Sub'}, + }, + [ + ('parameter_1', 'sub', {'out': 0, 'in': 0}), + ] + ) + + IteratorGetNextCut().find_and_replace_pattern(graph) + + flag, msg = compare_graphs(graph, graph_ref, last_node='sub') + self.assertTrue(flag, msg) + + def test_two_outputs(self): + graph = build_graph_with_edge_attrs( + { + 'iter_get_next': {'kind': 'op', 'op': 'IteratorGetNext', 'shapes': [shape_array([2, 2]), + shape_array([1, 1])], + 'types': [np.int32, np.float32]}, + 'sub': {'kind': 'op', 'op': 'Sub'}, + 'add': {'kind': 'op', 'op': 'Add'}, + 'concat': {'kind': 'op', 'op': 'Concat'} + }, + [ + ('iter_get_next', 'sub', {'out': 0, 'in': 0}), + ('iter_get_next', 'add', {'out': 1, 'in': 0}), + ('sub', 'concat', {'out': 0, 'in': 0}), + ('add', 'concat', {'out': 0, 'in': 1}) + ] + ) + + graph_ref = build_graph_with_edge_attrs( + { + 'parameter_1': {'kind': 'op', 'op': 'Parameter', 'shape': shape_array([2, 2]), 'data_type': np.int32}, + 'parameter_2': {'kind': 'op', 'op': 'Parameter', 'shape': shape_array([1, 1]), 'data_type': np.float32}, + 'sub': {'kind': 'op', 'op': 'Sub'}, + 'add': {'kind': 'op', 'op': 'Add'}, + 'concat': {'kind': 'op', 'op': 'Concat'} + }, + [ + ('parameter_1', 'sub', {'out': 0, 'in': 0}), + ('parameter_2', 'add', {'out': 0, 'in': 0}), + ('sub', 'concat', {'out': 0, 'in': 0}), + ('add', 'concat', {'out': 0, 'in': 1}) + ] + ) + + IteratorGetNextCut().find_and_replace_pattern(graph) + + flag, msg = compare_graphs(graph, graph_ref, last_node='concat', check_op_attrs=True) + self.assertTrue(flag, msg) + + def test_unsupported_data_type(self): + graph = build_graph_with_edge_attrs( + { + 'iter_get_next': {'kind': 'op', 'op': 'IteratorGetNext', 'shapes': shape_array([[2, 2]]), + 'types': [None]}, + 'sub': {'kind': 'op', 'op': 'Sub'}, + }, + [ + ('iter_get_next', 'sub', {'out': 0, 'in': 0}), + ] + ) + + self.assertRaises(Error, IteratorGetNextCut().find_and_replace_pattern, graph) diff --git a/model-optimizer/unit_tests/extensions/ops/gathernd_test.py b/model-optimizer/unit_tests/extensions/ops/gathernd_test.py index 4ad84bf527150c..8ccaad1a3abfb1 100644 --- a/model-optimizer/unit_tests/extensions/ops/gathernd_test.py +++ b/model-optimizer/unit_tests/extensions/ops/gathernd_test.py @@ -14,7 +14,7 @@ 'data_data': {'shape': None, 'value': None, 'kind': 'data'}, 'indices': {'kind': 'op'}, 'indices_data': {'shape': None, 'value': None, 'kind': 'data'}, - 'gathernd_node': {'op': 'GatherNDUpdate', 'kind': 'op', 'batch_dims': 0}, + 'gathernd_node': {'op': 'GatherNDUpdate', 'kind': 'op', 'batch_dims': 0, 'version': 'opset8'}, 'output': {'shape': None, 'value': None, 'kind': 'data'}} # graph 1 @@ -25,17 +25,21 @@ ('gathernd_node', 'output', {'out': 0})] # test data for partial infer: gather elements -inputs1 = {'data_data': {'shape': int64_array([10, 40]), 'value': None}, +inputs = {'data_data': {'shape': int64_array([10, 40]), 'value': None}, 'indices_data': {'shape': int64_array([3, 2]), 'value': None}} # test data for partial infer: gather slices -inputs2 = {'data_data': {'shape': int64_array([10, 40, 30]), 'value': None}, +inputs1 = {'data_data': {'shape': int64_array([10, 40, 30]), 'value': None}, 'indices_data': {'shape': int64_array([3, 2]), 'value': None}} # test data for partial infer: gather slices and batch_dims=2 -inputs3 = {'data_data': {'shape': int64_array([10, 40, 4, 9]), 'value': None}, +inputs2 = {'data_data': {'shape': int64_array([10, 40, 4, 9]), 'value': None}, 'indices_data': {'shape': int64_array([10, 40, 3, 5, 1]), 'value': None}} +# test data for partial infer: gather slices and batch_dims=3 and indices.shape[-1]=len(data.shape)-batch_dims +inputs3 = {'data_data': {'shape': int64_array([1, 64, 64, 320]), 'value': None}, + 'indices_data': {'shape': int64_array([1, 64, 64, 1, 1]), 'value': None}} + # test data for constant folding: gather elements, batch_dims = 0 inputs4 = {'data_data': {'shape': int64_array([2, 2]), 'value': int64_array([[1, 2], [3, 4]])}, @@ -110,6 +114,14 @@ inputs9 = {'data_data': {'shape': shape_array([dynamic_dimension_value, 40, 4, 9]), 'value': None}, 'indices_data': {'shape': shape_array([dynamic_dimension_value, 40, 3, 5, 1]), 'value': None}} +# test data for partial infer: gather slices and batch_dims=2 +inputs10 = {'data_data': {'shape': shape_array([40, dynamic_dimension_value, 4, 9]), 'value': None}, + 'indices_data': {'shape': shape_array([40, dynamic_dimension_value, 3, 5, 1]), 'value': None}} + +# test data for partial infer: gather slices and batch_dims=2 +inputs11 = {'data_data': {'shape': shape_array([dynamic_dimension_value, 40, 4, 9]), 'value': None}, + 'indices_data': {'shape': shape_array([40, dynamic_dimension_value, 3, 5, 1]), 'value': None}} + # invalid test case with incorrect rank for indices inputs_inv1 = {'data_data': {'shape': int64_array([10, 40]), 'value': None}, 'indices_data': {'shape': int64_array([5, 3, 4]), 'value': None}} @@ -123,12 +135,13 @@ 'indices_data': {'shape': int64_array([10, 40, 4]), 'value': None}} -class TestGatherNDUpdate(unittest.TestCase): +class TestGatherND_5(unittest.TestCase): def setUp(self): nodes_attributes['gathernd_node']['batch_dims'] = 0 + nodes_attributes['gathernd_node']['version'] = 'opset5' def test_partial_infer_gather_element(self): - graph = build_graph(nodes_attributes, edges, inputs1) + graph = build_graph(nodes_attributes, edges, inputs) gathernd_node = Node(graph, 'gathernd_node') GatherND.infer(gathernd_node) @@ -142,7 +155,7 @@ def test_partial_infer_gather_element(self): 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) def test_partial_infer_gather_slice(self): - graph = build_graph(nodes_attributes, edges, inputs2) + graph = build_graph(nodes_attributes, edges, inputs1) gathernd_node = Node(graph, 'gathernd_node') GatherND.infer(gathernd_node) @@ -157,7 +170,7 @@ def test_partial_infer_gather_slice(self): def test_partial_infer_gather_slice_batch_dims2(self): nodes_attributes['gathernd_node']['batch_dims'] = 2 - graph = build_graph(nodes_attributes, edges, inputs3) + graph = build_graph(nodes_attributes, edges, inputs2) gathernd_node = Node(graph, 'gathernd_node') GatherND.infer(gathernd_node) @@ -170,7 +183,22 @@ def test_partial_infer_gather_slice_batch_dims2(self): self.assertTrue(np.array_equal(ref_output_shape, res_output_shape), 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) - def test_partial_infer_gather_slice_batch_dims2_dynamic(self): + def test_partial_infer_gather_slice_batch_dims3(self): + nodes_attributes['gathernd_node']['batch_dims'] = 3 + graph = build_graph(nodes_attributes, edges, inputs3) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = int64_array([4096, 1]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(np.array_equal(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + def test_partial_infer_gather_slice_batch_dims2_dynamic1(self): nodes_attributes['gathernd_node']['batch_dims'] = 2 graph = build_graph(nodes_attributes, edges, inputs9) gathernd_node = Node(graph, 'gathernd_node') @@ -185,6 +213,36 @@ def test_partial_infer_gather_slice_batch_dims2_dynamic(self): self.assertTrue(strict_compare_tensors(ref_output_shape, res_output_shape), 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + def test_partial_infer_gather_slice_batch_dims2_dynamic2(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + graph = build_graph(nodes_attributes, edges, inputs10) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = shape_array([dynamic_dimension_value, 3, 5, 9]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(strict_compare_tensors(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + def test_partial_infer_gather_slice_batch_dims2_dynamic3(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + graph = build_graph(nodes_attributes, edges, inputs11) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = shape_array([dynamic_dimension_value, 3, 5, 9]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(strict_compare_tensors(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + def test_infer4(self): graph = build_graph(nodes_attributes, edges, inputs4) gathernd_node = Node(graph, 'gathernd_node') @@ -205,7 +263,7 @@ def test_infer5(self): res_output_value = graph.node['output']['value'] self.assertTrue(np.array_equal(output5, res_output_value), - 'values do not match expected: {} and given: {}'.format(output4, res_output_value)) + 'values do not match expected: {} and given: {}'.format(output5, res_output_value)) def test_infer6(self): nodes_attributes['gathernd_node']['batch_dims'] = 1 @@ -217,7 +275,7 @@ def test_infer6(self): res_output_value = graph.node['output']['value'] self.assertTrue(np.array_equal(output6, res_output_value), - 'values do not match expected: {} and given: {}'.format(output4, res_output_value)) + 'values do not match expected: {} and given: {}'.format(output6, res_output_value)) def test_infer7(self): nodes_attributes['gathernd_node']['batch_dims'] = 2 @@ -228,8 +286,9 @@ def test_infer7(self): # get the result res_output_value = graph.node['output']['value'] - self.assertTrue(np.array_equal(output7, res_output_value), - 'values do not match expected: {} and given: {}'.format(output4, res_output_value)) + output = output7.reshape([6, 1]) + self.assertTrue(np.array_equal(output, res_output_value), + 'values do not match expected: {} and given: {}'.format(output, res_output_value)) def test_infer8(self): nodes_attributes['gathernd_node']['batch_dims'] = 2 @@ -241,7 +300,32 @@ def test_infer8(self): res_output_value = graph.node['output']['value'] self.assertTrue(np.array_equal(output8, res_output_value), - 'values do not match expected: {} and given: {}'.format(output4, res_output_value)) + 'values do not match expected: {} and given: {}'.format(output8, res_output_value)) + + def test_infer9(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + graph = build_graph(nodes_attributes, edges, inputs8) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # get the result + res_output_value = graph.node['output']['value'] + + self.assertTrue(np.array_equal(output8, res_output_value), + 'values do not match expected: {} and given: {}'.format(output8, res_output_value)) + + def test_infer9_opset_5(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + graph = build_graph(nodes_attributes, edges, inputs8) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # get the result + res_output_value = graph.node['output']['value'] + + output = output8.reshape([6, 3]) + self.assertTrue(np.array_equal(output, res_output_value), + 'values do not match expected: {} and given: {}'.format(output, res_output_value)) def test_infer_invalid1(self): graph = build_graph(nodes_attributes, edges, inputs_inv1) @@ -259,3 +343,114 @@ def test_infer_invalid3(self): graph = build_graph(nodes_attributes, edges, inputs_inv3) gathernd_node = Node(graph, 'gathernd_node') self.assertRaises(AssertionError, GatherND.infer, gathernd_node) + + + def test_partial_infer_gather_slice_batch_dims2_opset8(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + nodes_attributes['gathernd_node']['version'] = 'opset8' + graph = build_graph(nodes_attributes, edges, inputs2) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = int64_array([10, 40, 3, 5, 9]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(np.array_equal(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + def test_partial_infer_gather_slice_batch_dims3_opset8(self): + nodes_attributes['gathernd_node']['batch_dims'] = 3 + nodes_attributes['gathernd_node']['version'] = 'opset8' + graph = build_graph(nodes_attributes, edges, inputs3) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = int64_array([1, 64, 64, 1]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(np.array_equal(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + def test_partial_infer_gather_slice_batch_dims2_dynamic1_opset8(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + nodes_attributes['gathernd_node']['version'] = 'opset8' + graph = build_graph(nodes_attributes, edges, inputs9) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = shape_array([dynamic_dimension_value, 40, 3, 5, 9]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(strict_compare_tensors(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + def test_partial_infer_gather_slice_batch_dims2_dynamic2_opset8(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + nodes_attributes['gathernd_node']['version'] = 'opset8' + graph = build_graph(nodes_attributes, edges, inputs10) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = shape_array([40, dynamic_dimension_value, 3, 5, 9]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(strict_compare_tensors(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + def test_partial_infer_gather_slice_batch_dims2_dynamic3_opset8(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + nodes_attributes['gathernd_node']['version'] = 'opset8' + graph = build_graph(nodes_attributes, edges, inputs11) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # prepare reference results + ref_output_shape = shape_array([40, 40, 3, 5, 9]) + + # get the result + res_output_shape = graph.node['output']['shape'] + + self.assertTrue(strict_compare_tensors(ref_output_shape, res_output_shape), + 'values do not match expected: {} and given: {}'.format(ref_output_shape, res_output_shape)) + + def test_infer7_opset8(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + nodes_attributes['gathernd_node']['version'] = 'opset8' + graph = build_graph(nodes_attributes, edges, inputs7) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # get the result + res_output_value = graph.node['output']['value'] + + output = output7.reshape([2, 3, 1]) + + self.assertTrue(np.array_equal(output, res_output_value), + 'values do not match expected: {} and given: {}'.format(output, res_output_value)) + + def test_infer8_opset8(self): + nodes_attributes['gathernd_node']['batch_dims'] = 2 + nodes_attributes['gathernd_node']['version'] = 'opset8' + graph = build_graph(nodes_attributes, edges, inputs8) + gathernd_node = Node(graph, 'gathernd_node') + GatherND.infer(gathernd_node) + + # get the result + res_output_value = graph.node['output']['value'] + + output = output8.reshape([2, 3, 3]) + + self.assertTrue(np.array_equal(output, res_output_value), + 'values do not match expected: {} and given: {}'.format(output, res_output_value)) diff --git a/model-optimizer/unit_tests/mo/bom_test.py b/model-optimizer/unit_tests/mo/bom_test.py index 454be1912c93d5..11511deaf6c557 100644 --- a/model-optimizer/unit_tests/mo/bom_test.py +++ b/model-optimizer/unit_tests/mo/bom_test.py @@ -28,13 +28,15 @@ class TestBOMFile(unittest.TestCase): def setUpClass(cls): cls.existing_files = [] cur_path = os.path.join(os.path.realpath(__file__), os.pardir) - cls.output_dir = os.path.abspath(os.path.join(cur_path, os.pardir, os.pardir)) - with open(os.path.join(cls.output_dir, 'automation', 'package_BOM.txt'), 'r') as bom_file: + mo_path = os.path.abspath(os.path.join(cur_path, os.pardir, os.pardir)) + with open(os.path.join(mo_path, 'automation', 'package_BOM.txt'), 'r') as bom_file: if platform.system() == 'Windows': cls.existing_files = [name.rstrip().replace('/', '\\') for name in bom_file.readlines()] else: cls.existing_files = [name.rstrip() for name in bom_file.readlines()] + # output_dir is the model_optimizer directory that is located in 'pkg/tools' + cls.output_dir = mo_path.replace('tests', 'tools') cls.expected_header = [re.compile(pattern) for pattern in [ r'^# Copyright \([cC]\) [0-9\-]+ Intel Corporation$', r'^# SPDX-License-Identifier: Apache-2.0$', diff --git a/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.cpp b/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.cpp index 17c647e35b5801..c8af6f81f6ea10 100644 --- a/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.cpp +++ b/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.cpp @@ -8,7 +8,7 @@ #include "ngraph/visibility.hpp" using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov::frontend; FeStat FrontEndMockPy::m_stat = {}; ModelStat InputModelMockPy::m_stat = {}; @@ -33,4 +33,4 @@ extern "C" MOCK_API void* GetFrontEndData() res->m_creator = []() { return std::make_shared(); }; return res; -} \ No newline at end of file +} diff --git a/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.hpp b/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.hpp index 72f533da2de3ca..fd831af203720c 100644 --- a/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.hpp +++ b/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_ngraph_frontend/mock_mo_frontend.hpp @@ -18,7 +18,7 @@ // OK to have 'using' in mock header using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov::frontend; //////////////////////////////// /// \brief This structure holds number static setup values diff --git a/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_python_api/mock_mo_python_api.cpp b/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_python_api/mock_mo_python_api.cpp index b0ebc36d51747c..3742c9e5d290bd 100644 --- a/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_python_api/mock_mo_python_api.cpp +++ b/model-optimizer/unit_tests/mock_mo_frontend/mock_mo_python_api/mock_mo_python_api.cpp @@ -9,7 +9,7 @@ namespace py = pybind11; using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov::frontend; static void register_mock_frontend_stat(py::module m) { diff --git a/ngraph/CMakeLists.txt b/ngraph/CMakeLists.txt index 163c395842735b..9681640b96b5ac 100644 --- a/ngraph/CMakeLists.txt +++ b/ngraph/CMakeLists.txt @@ -27,4 +27,5 @@ add_definitions(-DPROJECT_ROOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}") add_subdirectory(core) add_subdirectory(frontend) + add_subdirectory(test) diff --git a/ngraph/core/CMakeLists.txt b/ngraph/core/CMakeLists.txt index f93cdfd83bd065..0caa99e50c076a 100644 --- a/ngraph/core/CMakeLists.txt +++ b/ngraph/core/CMakeLists.txt @@ -17,7 +17,6 @@ add_subdirectory(reference) add_subdirectory(shape_inference) # WA for Tensor implementation via ie::Blob::Ptr -set(IE_SRC_ROOT "${IE_MAIN_SOURCE_DIR}/src/inference_engine/src") set(IE_SHARED_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/ie_legacy/blob_factory.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/ie_legacy/ie_blob_common.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/ie_legacy/ie_layouts.cpp" @@ -28,7 +27,7 @@ set(MIXED_SRC ${IE_SHARED_SRCS} set_property(SOURCE ${MIXED_SRC} APPEND PROPERTY INCLUDE_DIRECTORIES - ${IE_SRC_ROOT} + $/src $ $) @@ -77,7 +76,7 @@ if(NOT BUILD_SHARED_LIBS) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - # ngraph is linked against ngraph_builders, ngraph_reference static libraries + # ngraph is linked against ngraph_builders, ngraph_reference, ov_shape_inference static libraries # which include ngraph headers with dllimport attribute. Linker complains about it # but no way to fix this: linking with no attribute defaults to dllexport and we have # multiple defitions for ngraph symbols. @@ -85,7 +84,13 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # The possible way is to use object libraries for ngraph_builders, ngraph_reference # but it's not convinient since these libraries are exported from build tree # and it's better to use them as static libraries in 3rd party projects - set_target_properties(ngraph PROPERTIES LINK_FLAGS "/IGNORE:4217,4286") + if(BUILD_SHARED_LIBS) + set(link_type PRIVATE) + else() + set(link_type PUBLIC) + endif() + + target_link_options(ngraph ${link_type} "/IGNORE:4217,4286") endif() # some sources are located in ngraph, while headers are in inference_engine_transformations diff --git a/ngraph/core/builder/CMakeLists.txt b/ngraph/core/builder/CMakeLists.txt index b5953a6f1709db..b6c2fb0c0cc45d 100644 --- a/ngraph/core/builder/CMakeLists.txt +++ b/ngraph/core/builder/CMakeLists.txt @@ -15,7 +15,7 @@ set(BUILDER_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/) source_group("src" FILES ${LIBRARY_SRC}) source_group("include" FILES ${PUBLIC_HEADERS}) -# Create shared library +# Create static library add_library(${TARGET_NAME} STATIC ${LIBRARY_SRC} ${PUBLIC_HEADERS}) if(COMMAND ie_faster_build) @@ -25,14 +25,21 @@ if(COMMAND ie_faster_build) ) endif() -# Defines macro in C++ to load backend plugin -target_include_directories(${TARGET_NAME} PUBLIC ${BUILDER_INCLUDE_DIR} ${NGRAPH_INCLUDE_PATH}) +target_include_directories(${TARGET_NAME} PUBLIC + $ + $) + +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(${TARGET_NAME} PUBLIC OPENVINO_STATIC_LIBRARY) +endif() add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) # Add an alias so that library can be used inside the build tree, e.g. when testing add_library(ngraph::builder ALIAS ${TARGET_NAME}) +ov_install_static_lib(ngraph_builders ngraph) + # developer package openvino_developer_export_targets(COMPONENT ngraph TARGETS ngraph::builder) diff --git a/ngraph/core/include/ngraph/dimension.hpp b/ngraph/core/include/ngraph/dimension.hpp index 9d748b26b30c94..762d4e430436b5 100644 --- a/ngraph/core/include/ngraph/dimension.hpp +++ b/ngraph/core/include/ngraph/dimension.hpp @@ -4,6 +4,7 @@ #pragma once +#include "ngraph/attribute_adapter.hpp" #include "ngraph/interval.hpp" #include "openvino/core/dimension.hpp" diff --git a/ngraph/core/include/ngraph/op/gather_nd.hpp b/ngraph/core/include/ngraph/op/gather_nd.hpp index 9689be8b854b0b..4a5bf1e50ff630 100644 --- a/ngraph/core/include/ngraph/op/gather_nd.hpp +++ b/ngraph/core/include/ngraph/op/gather_nd.hpp @@ -12,5 +12,8 @@ namespace op { namespace v5 { using ov::op::v5::GatherND; } // namespace v5 +namespace v8 { +using ov::op::v8::GatherND; +} // namespace v8 } // namespace op } // namespace ngraph diff --git a/ngraph/core/include/ngraph/op/util/gather_nd_base.hpp b/ngraph/core/include/ngraph/op/util/gather_nd_base.hpp new file mode 100644 index 00000000000000..6585dac61bb401 --- /dev/null +++ b/ngraph/core/include/ngraph/op/util/gather_nd_base.hpp @@ -0,0 +1,16 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/op/op.hpp" +#include "openvino/op/util/gather_nd_base.hpp" + +namespace ngraph { +namespace op { +namespace util { +using ov::op::util::GatherNDBase; +} // namespace util +} // namespace op +} // namespace ngraph diff --git a/ngraph/core/include/ngraph/validation_util.hpp b/ngraph/core/include/ngraph/validation_util.hpp index e52b6096c5d340..37607e91764355 100644 --- a/ngraph/core/include/ngraph/validation_util.hpp +++ b/ngraph/core/include/ngraph/validation_util.hpp @@ -216,6 +216,9 @@ NGRAPH_API std::shared_ptr get_constant_max_of_type(element::Type_ /// \brief Returns a Constant storing scalar value equal to std::numeric_limits::min() NGRAPH_API std::shared_ptr get_constant_min_of_type(element::Type_t t); +/// \brief Returns a Constant storing scalar value equal to std::numeric_limits::lowest() +NGRAPH_API std::shared_ptr get_constant_lowest_of_type(element::Type_t t); + /// \brief Checks if size of HostTensorVector is the same as passed size attribute. Then checks /// that all the HostTensorPtrs are not equal to nullptr NGRAPH_API bool validate_host_tensor_vector(const HostTensorVector& v, const size_t& size); diff --git a/ngraph/core/include/openvino/core/descriptor/tensor.hpp b/ngraph/core/include/openvino/core/descriptor/tensor.hpp index 4418468625c6dc..0f9f7f970c8705 100644 --- a/ngraph/core/include/openvino/core/descriptor/tensor.hpp +++ b/ngraph/core/include/openvino/core/descriptor/tensor.hpp @@ -45,8 +45,14 @@ class OPENVINO_API Tensor { const std::unordered_set& get_names() const; void set_names(const std::unordered_set& names); void add_names(const std::unordered_set& names); + + OPENVINO_DEPRECATED("set_tensor_type() is deprecated. To change Tensor type please change the Parameter type") void set_tensor_type(const element::Type& element_type, const PartialShape& pshape); + OPENVINO_DEPRECATED( + "set_element_type() is deprecated. To change Tensor element type please change the Parameter type") void set_element_type(const element::Type& elemenet_type); + OPENVINO_DEPRECATED( + "set_partial_shape() is deprecated. To change Tensor partial shape please change the Parameter partial shape") void set_partial_shape(const PartialShape& partial_shape); /// \brief sets lower bound value description diff --git a/ngraph/core/include/openvino/core/dimension.hpp b/ngraph/core/include/openvino/core/dimension.hpp index e54232677540fd..7f013791b7be67 100644 --- a/ngraph/core/include/openvino/core/dimension.hpp +++ b/ngraph/core/include/openvino/core/dimension.hpp @@ -8,6 +8,7 @@ #include #include +#include "openvino/core/attribute_adapter.hpp" #include "openvino/core/core_visibility.hpp" #include "openvino/core/interval.hpp" @@ -27,7 +28,7 @@ class OPENVINO_API Dimension { /// \brief Construct a dynamic dimension with bounded range /// \param min_dimension The lower inclusive limit for the dimension - /// \param mas_dimension The upper inclusive limit for the dimension + /// \param max_dimension The upper inclusive limit for the dimension Dimension(value_type min_dimension, value_type max_dimension); /// \brief Construct a dynamic dimension with range [0, ...] @@ -169,4 +170,23 @@ class OPENVINO_API Dimension { /// Inserts the string `?` if `dimension` is dynamic; else inserts `dimension.get_length()`. OPENVINO_API std::ostream& operator<<(std::ostream& str, const Dimension& dimension); + +template <> +class OPENVINO_API AttributeAdapter : public ValueAccessor { +public: + AttributeAdapter(ov::Dimension& value) : m_ref(value) {} + + const int64_t& get() override; + void set(const int64_t& value) override; + operator ov::Dimension&() { + return m_ref; + } + + OPENVINO_RTTI("AttributeAdapter"); + +protected: + ov::Dimension& m_ref; + int64_t m_buffer{0}; + bool m_buffer_valid{false}; +}; } // namespace ov diff --git a/ngraph/core/include/openvino/core/extension.hpp b/ngraph/core/include/openvino/core/extension.hpp index 9e997336ac985e..6b8860387706bc 100644 --- a/ngraph/core/include/openvino/core/extension.hpp +++ b/ngraph/core/include/openvino/core/extension.hpp @@ -16,8 +16,8 @@ # define OPENVINO_EXTENSION_C_API OPENVINO_EXTERN_C OPENVINO_CORE_EXPORTS # define OPENVINO_EXTENSION_API OPENVINO_CORE_EXPORTS #else -# define OPENVINO_EXTENSION_C_API OPENVINO_EXTERN_C OPENVINO_API -# define OPENVINO_EXTENSION_API OPENVINO_API +# define OPENVINO_EXTENSION_C_API OPENVINO_EXTERN_C OPENVINO_CORE_EXPORTS +# define OPENVINO_EXTENSION_API OPENVINO_CORE_EXPORTS #endif namespace ov { @@ -27,7 +27,7 @@ class Extension; /** * @brief The class provides the base interface for OpenVINO extensions */ -class OPENVINO_API Extension : public std::enable_shared_from_this { +class OPENVINO_API Extension { public: using Ptr = std::shared_ptr; diff --git a/ngraph/core/include/openvino/core/function.hpp b/ngraph/core/include/openvino/core/function.hpp index f8eed3450b1f75..a94cdfd66df5ab 100644 --- a/ngraph/core/include/openvino/core/function.hpp +++ b/ngraph/core/include/openvino/core/function.hpp @@ -27,10 +27,15 @@ namespace ov { /// A user-defined function. class OPENVINO_API Function : public std::enable_shared_from_this { public: - static constexpr ov::DiscreteTypeInfo type_info{"Function", 0}; - const ov::DiscreteTypeInfo& get_type_info() const { + static const ::ov::DiscreteTypeInfo& get_type_info_static() { + static const ::ov::DiscreteTypeInfo type_info{"Function", 0}; return type_info; } + const ::ov::DiscreteTypeInfo& get_type_info() const { + return get_type_info_static(); + } + OPENVINO_DEPRECATED("This member was deprecated. Please use ::get_type_info_static() instead.") + static const ov::DiscreteTypeInfo type_info; Function(const ov::NodeVector& results, const ov::ParameterVector& parameters, const std::string& name = ""); Function(const ov::OutputVector& results, const ov::ParameterVector& parameters, const std::string& name = ""); diff --git a/ngraph/core/include/openvino/core/layout.hpp b/ngraph/core/include/openvino/core/layout.hpp index 4f7a998c5af220..cf358babd4d751 100644 --- a/ngraph/core/include/openvino/core/layout.hpp +++ b/ngraph/core/include/openvino/core/layout.hpp @@ -147,14 +147,11 @@ OPENVINO_API std::int64_t width_idx(const Layout& layout); template <> class OPENVINO_API AttributeAdapter : public ValueAccessor { public: + OPENVINO_RTTI("AttributeAdapter"); explicit AttributeAdapter(Layout& value) : m_ref(value) {} const std::string& get() override; void set(const std::string& value) override; - static constexpr DiscreteTypeInfo type_info{"AttributeAdapter", 0}; - const DiscreteTypeInfo& get_type_info() const override { - return type_info; - } explicit operator Layout&() { return m_ref; } diff --git a/ngraph/core/include/openvino/core/op_extension.hpp b/ngraph/core/include/openvino/core/op_extension.hpp index 735d2dba358877..4f9a2cf5cbe736 100644 --- a/ngraph/core/include/openvino/core/op_extension.hpp +++ b/ngraph/core/include/openvino/core/op_extension.hpp @@ -14,7 +14,7 @@ namespace ov { /** * @brief The base interface for OpenVINO operation extensions */ -class OPENVINO_EXTENSION_API BaseOpExtension : public Extension { +class OPENVINO_API BaseOpExtension : public Extension { public: using Ptr = std::shared_ptr; /** diff --git a/ngraph/core/include/openvino/core/partial_shape.hpp b/ngraph/core/include/openvino/core/partial_shape.hpp index 8ad68c66de7746..e2810e6d274e1b 100644 --- a/ngraph/core/include/openvino/core/partial_shape.hpp +++ b/ngraph/core/include/openvino/core/partial_shape.hpp @@ -224,6 +224,7 @@ class OPENVINO_API PartialShape { /// element in the shape. Iteration is done in ordinary /// element order. iterator begin() noexcept { + m_shape_type = ShapeType::SHAPE_IS_UPDATED; return m_dimensions.begin(); } /// \brief Returns a read-only (constant) iterator that points to the @@ -236,6 +237,7 @@ class OPENVINO_API PartialShape { /// element in the shape. Iteration is done in ordinary /// element order. iterator end() noexcept { + m_shape_type = ShapeType::SHAPE_IS_UPDATED; return m_dimensions.end(); } /// \brief Returns a read-only (constant) iterator that points one past @@ -248,6 +250,7 @@ class OPENVINO_API PartialShape { /// last element in the shape. Iteration is done in reverse /// element order. reverse_iterator rbegin() noexcept { + m_shape_type = ShapeType::SHAPE_IS_UPDATED; return m_dimensions.rbegin(); } /// \brief Returns a read-only (constant) reverse iterator that points @@ -260,6 +263,7 @@ class OPENVINO_API PartialShape { /// before the first element in the shape. Iteration is done /// in reverse element order. reverse_iterator rend() noexcept { + m_shape_type = ShapeType::SHAPE_IS_UPDATED; return m_dimensions.rend(); } /// \brief Returns a read-only (constant) reverse iterator that points diff --git a/ngraph/core/include/openvino/core/preprocess/input_info.hpp b/ngraph/core/include/openvino/core/preprocess/input_info.hpp index 2c3ae8408815c0..61a67afc624341 100644 --- a/ngraph/core/include/openvino/core/preprocess/input_info.hpp +++ b/ngraph/core/include/openvino/core/preprocess/input_info.hpp @@ -18,10 +18,6 @@ namespace preprocess { /// - Preprocessing steps applied to user's input (InputInfo::preprocess) /// - Network's input info, which is a final info after preprocessing (InputInfo::network) /// -/// API has Builder-like style to allow chaining calls in client's code, like -/// \code{.cpp} -/// auto proc = PrePostProcessor().input(InputInfo().tensor(...).preprocess(...).network(...); -/// \endcode class OPENVINO_API InputInfo final { class InputInfoImpl; std::unique_ptr m_impl; @@ -29,15 +25,21 @@ class OPENVINO_API InputInfo final { public: /// \brief Empty constructor. Should be used only if network will have only one input + /// + /// \todo Consider remove it (don't allow user to create standalone objects) InputInfo(); /// \brief Constructor for particular input index of model /// + /// \todo Consider remove it (don't allow user to create standalone objects) + /// /// \param input_index Index to address specified input parameter of model explicit InputInfo(size_t input_index); /// \brief Constructor for particular output of model addressed by it's input name /// + /// \todo Consider remove it (don't allow user to create standalone objects) + /// /// \param input_tensor_name Name of input tensor name explicit InputInfo(const std::string& input_tensor_name); @@ -50,8 +52,25 @@ class OPENVINO_API InputInfo final { /// \brief Default destructor ~InputInfo(); + /// \brief Get current input tensor information with ability to change specific data + /// + /// \return Reference to current input tensor structure + InputTensorInfo& tensor(); + + /// \brief Get current input preprocess information with ability to add more preprocessing steps + /// + /// \return Reference to current preprocess steps structure + PreProcessSteps& preprocess(); + + /// \brief Get current input network/model information with ability to change original network's input data + /// + /// \return Reference to current network's input information structure + InputNetworkInfo& network(); + /// \brief Set input tensor information for input - Lvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Input tensor information. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -59,6 +78,8 @@ class OPENVINO_API InputInfo final { /// \brief Set input tensor information for input - Rvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Input tensor information. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner @@ -66,6 +87,8 @@ class OPENVINO_API InputInfo final { /// \brief Set preprocessing operations for input - Lvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Preprocessing operations. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -73,6 +96,8 @@ class OPENVINO_API InputInfo final { /// \brief Set preprocessing operations for input - Rvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Preprocessing operations. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner @@ -81,6 +106,8 @@ class OPENVINO_API InputInfo final { /// \brief Set network's tensor information for input - Lvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Input network tensor information. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -88,6 +115,8 @@ class OPENVINO_API InputInfo final { /// \brief Set input tensor information for input - Rvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Input network tensor information. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner diff --git a/ngraph/core/include/openvino/core/preprocess/input_network_info.hpp b/ngraph/core/include/openvino/core/preprocess/input_network_info.hpp index b6ef577f40e13b..a61b6a138ac8e6 100644 --- a/ngraph/core/include/openvino/core/preprocess/input_network_info.hpp +++ b/ngraph/core/include/openvino/core/preprocess/input_network_info.hpp @@ -21,7 +21,7 @@ namespace preprocess { /// \code{.cpp} /// /// auto proc = -/// PrePostProcessor() +/// PrePostProcessor(function) /// .input(InputInfo() /// .tensor() /// .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) diff --git a/ngraph/core/include/openvino/core/preprocess/input_tensor_info.hpp b/ngraph/core/include/openvino/core/preprocess/input_tensor_info.hpp index ea73d7fae2db34..40c7e5ae46fc00 100644 --- a/ngraph/core/include/openvino/core/preprocess/input_tensor_info.hpp +++ b/ngraph/core/include/openvino/core/preprocess/input_tensor_info.hpp @@ -18,7 +18,7 @@ namespace preprocess { /// /// \code{.cpp} /// auto proc = -/// PrePostProcessor() +/// PrePostProcessor(function) /// .input(InputInfo() /// .tensor(InputTensorInfo() /// .set_element_type(ov::element::u8)) diff --git a/ngraph/core/include/openvino/core/preprocess/output_info.hpp b/ngraph/core/include/openvino/core/preprocess/output_info.hpp index 879875d16ef808..a0fe39d10a6e5c 100644 --- a/ngraph/core/include/openvino/core/preprocess/output_info.hpp +++ b/ngraph/core/include/openvino/core/preprocess/output_info.hpp @@ -17,11 +17,6 @@ namespace preprocess { /// - Network's output info, (OutputInfo::network) /// - Postprocessing steps applied to user's input (OutputInfo::postprocess) /// - User's desired output parameter information, which is a final one after preprocessing (OutputInfo::tensor) -/// -/// API has Builder-like style to allow chaining calls in client's code, like -/// \code{.cpp} -/// auto proc = PrePostProcessor().output(InputInfo().network(...).preprocess(...).tensor(...); -/// \endcode class OPENVINO_API OutputInfo final { class OutputInfoImpl; std::unique_ptr m_impl; @@ -29,15 +24,21 @@ class OPENVINO_API OutputInfo final { public: /// \brief Empty constructor. Should be used only if network has exactly one output + /// + /// \todo Consider making this private to not allow user to create standalone object OutputInfo(); /// \brief Constructor for particular output index of model /// + /// \todo Consider remove it (don't allow user to create standalone objects) + /// /// \param output_index Index to address specified output parameter of model explicit OutputInfo(size_t output_index); /// \brief Constructor for particular output of model addressed by it's output name /// + /// \todo Consider remove it (don't allow user to create standalone objects) + /// /// \param output_tensor_name Name of output tensor name explicit OutputInfo(const std::string& output_tensor_name); @@ -50,8 +51,25 @@ class OPENVINO_API OutputInfo final { /// \brief Default destructor ~OutputInfo(); + /// \brief Get current output network/model information with ability to change original network's output data + /// + /// \return Reference to current network's output information structure + OutputNetworkInfo& network(); + + /// \brief Get current output post-process information with ability to add more post-processing steps + /// + /// \return Reference to current preprocess steps structure + PostProcessSteps& postprocess(); + + /// \brief Get current output tensor information with ability to change specific data + /// + /// \return Reference to current output tensor structure + OutputTensorInfo& tensor(); + /// \brief Set network's tensor information for output - Lvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Output network tensor information. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -59,6 +77,8 @@ class OPENVINO_API OutputInfo final { /// \brief Set network's tensor information for output - Rvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Output network tensor information. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner @@ -66,6 +86,8 @@ class OPENVINO_API OutputInfo final { /// \brief Set postprocessing operations for output - Lvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Postprocessing operations. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -73,6 +95,8 @@ class OPENVINO_API OutputInfo final { /// \brief Set postprocessing operations for output - Rvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Postprocessing operations. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner @@ -81,6 +105,8 @@ class OPENVINO_API OutputInfo final { /// \brief Set final output tensor information for output after postprocessing - Lvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Output tensor information. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -88,6 +114,8 @@ class OPENVINO_API OutputInfo final { /// \brief Set final output tensor information for output after postprocessing - Rvalue version /// + /// \todo Consider removing it in future + /// /// \param builder Output tensor information. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner diff --git a/ngraph/core/include/openvino/core/preprocess/output_network_info.hpp b/ngraph/core/include/openvino/core/preprocess/output_network_info.hpp index b32c2181ae122f..b0a96c8274385f 100644 --- a/ngraph/core/include/openvino/core/preprocess/output_network_info.hpp +++ b/ngraph/core/include/openvino/core/preprocess/output_network_info.hpp @@ -14,17 +14,15 @@ namespace preprocess { /// info may not be needed. However it can be set to specify additional information about network, like 'layout'. /// /// Example of usage of network 'layout': -/// Support network has output parameter with shape {1, 3, 224, 224} and `NHWC` layout. User may need to transpose +/// Support network has output result with shape {1, 3, 224, 224} and `NHWC` layout. User may need to transpose /// output picture to interleaved format {1, 224, 224, 3}. This can be done with the following code /// /// \code{.cpp} -/// -/// auto proc = -/// PrePostProcessor() -/// .output(OutputInfo() -/// .network(OutputNetworkInfo().set_layout("NCHW") -/// .preprocess(PostProcessSteps().convert_layout("NHWC"))) -/// ); +/// +/// auto proc = PrePostProcessor(function); +/// proc.output().network().set_layout("NCHW"); +/// proc.output().postprocess().convert_layout("NHWC"); +/// function = proc.build(); /// \endcode class OPENVINO_API OutputNetworkInfo final { class OutputNetworkInfoImpl; diff --git a/ngraph/core/include/openvino/core/preprocess/output_tensor_info.hpp b/ngraph/core/include/openvino/core/preprocess/output_tensor_info.hpp index 385a47d729898e..77045b899d45ee 100644 --- a/ngraph/core/include/openvino/core/preprocess/output_tensor_info.hpp +++ b/ngraph/core/include/openvino/core/preprocess/output_tensor_info.hpp @@ -16,13 +16,11 @@ namespace preprocess { /// 'element_type') according to application's data and specify appropriate conversions in post-processing steps /// /// \code{.cpp} -/// auto proc = -/// PrePostProcessor() -/// .output(OutputInfo() -/// .postprocess() -/// .tensor(OutputTensorInfo() -/// .set_element_type(ov::element::u8)) -/// ); +/// auto proc = PrePostProcessor(function); +/// auto& output = proc.output(); +/// output.postprocess().; +/// output.tensor().set_element_type(ov::element::u8); +/// function = proc.build(); /// \endcode class OPENVINO_API OutputTensorInfo final { class OutputTensorInfoImpl; @@ -31,6 +29,8 @@ class OPENVINO_API OutputTensorInfo final { public: /// \brief Default empty constructor + /// + /// \todo Consider making this private to not allow user to create standalone object OutputTensorInfo(); /// \brief Default move constructor diff --git a/ngraph/core/include/openvino/core/preprocess/postprocess_steps.hpp b/ngraph/core/include/openvino/core/preprocess/postprocess_steps.hpp index d318b8684c95ce..8d0e47db47ba4d 100644 --- a/ngraph/core/include/openvino/core/preprocess/postprocess_steps.hpp +++ b/ngraph/core/include/openvino/core/preprocess/postprocess_steps.hpp @@ -17,11 +17,9 @@ namespace preprocess { /// \brief Postprocessing steps. Each step typically intends adding of some operation to output parameter /// User application can specify sequence of postprocessing steps in a builder-like manner /// \code{.cpp} -/// auto proc = PrePostProcessor() -/// .output(OutputInfo() -/// .postprocess(PostProcessSteps() -/// .convert_element_type(element::u8))) -/// ); +/// auto proc = PrePostProcessor(function); +/// proc.output().postprocess().convert_element_type(element::u8); +/// function = proc.build(); /// \endcode class OPENVINO_API PostProcessSteps final { class PostProcessStepsImpl; @@ -30,6 +28,8 @@ class OPENVINO_API PostProcessSteps final { public: /// \brief Default empty constructor + /// + /// \todo Consider remove it (don't allow user to create standalone objects) PostProcessSteps(); /// \brief Default move constructor @@ -64,7 +64,7 @@ class OPENVINO_API PostProcessSteps final { /// interleaved output image ('NHWC', [1, 224, 224, 3]). Post-processing may look like this: /// /// \code{.cpp} auto proc = - /// PrePostProcessor() + /// PrePostProcessor(function) /// .output(OutputInfo() /// .network(OutputTensorInfo().set_layout("NCHW")) // Network output is NCHW /// .postprocess(PostProcessSteps() @@ -92,7 +92,7 @@ class OPENVINO_API PostProcessSteps final { /// interleaved output image [1, 480, 640, 3]. Post-processing may look like this: /// /// \code{.cpp} auto proc = - /// PrePostProcessor() + /// PrePostProcessor(function) /// .output(OutputInfo() /// .postprocess(PostProcessSteps() /// .convert_layout({0, 2, 3, 1}) diff --git a/ngraph/core/include/openvino/core/preprocess/pre_post_process.hpp b/ngraph/core/include/openvino/core/preprocess/pre_post_process.hpp index 54ac8b5ab4d423..18913b828f9c85 100644 --- a/ngraph/core/include/openvino/core/preprocess/pre_post_process.hpp +++ b/ngraph/core/include/openvino/core/preprocess/pre_post_process.hpp @@ -17,7 +17,7 @@ namespace preprocess { /// \brief Main class for adding pre- and post- processing steps to existing ov::Function /// API has Builder-like style to allow chaining calls in client's code, like /// \code{.cpp} -/// auto proc = PrePostProcessor().input().input(); +/// auto proc = PrePostProcessor(function).input().input(); /// \endcode /// /// This is a helper class for writing easy pre- and post- processing operations on ov::Function object assuming that @@ -32,7 +32,9 @@ class OPENVINO_API PrePostProcessor final { public: /// \brief Default constructor - PrePostProcessor(); + /// + /// \param function Existing function representing loaded model + explicit PrePostProcessor(const std::shared_ptr& function); /// \brief Default move constructor PrePostProcessor(PrePostProcessor&&) noexcept; @@ -43,8 +45,62 @@ class OPENVINO_API PrePostProcessor final { /// \brief Default destructor ~PrePostProcessor(); + /// \brief Gets input pre-processing data structure. Should be used only if network/function has only one input + /// Using returned structure application's code is able to set user's tensor data (e.g layout), preprocess steps, + /// target model's data + /// + /// \return Reference to network's input information structure + InputInfo& input(); + + /// \brief Gets input pre-processing data structure for input identified by it's tensor name + /// + /// \param tensor_name Tensor name of specific input. Throws if tensor name is not associated with any input in a + /// model + /// + /// \return Reference to network's input information structure + InputInfo& input(const std::string& tensor_name); + + /// \brief Gets input pre-processing data structure for input identified by it's order in a model + /// + /// \param input_index Input index of specific input. Throws if input index is out of range for associated function + /// + /// \return Reference to network's input information structure + InputInfo& input(size_t input_index); + + /// \brief Gets output post-processing data structure. Should be used only if network/function has only one output + /// Using returned structure application's code is able to set model's output data, post-process steps, user's + /// tensor data (e.g layout) + /// + /// \return Reference to network's output information structure + OutputInfo& output(); + + /// \brief Gets output post-processing data structure for output identified by it's tensor name + /// + /// \param tensor_name Tensor name of specific output. Throws if tensor name is not associated with any input in a + /// model + /// + /// \return Reference to network's output information structure + OutputInfo& output(const std::string& tensor_name); + + /// \brief Gets output post-processing data structure for output identified by it's order in a model + /// + /// \param output_index Output index of specific output. Throws if output index is out of range for associated + /// function + /// + /// \return Reference to network's output information structure + OutputInfo& output(size_t output_index); + + /// \brief Adds pre/post-processing operations to function passed in constructor + /// + /// \return Function with added pre/post-processing operations + std::shared_ptr build(); + + //------------------ TODO: consider removal of rest -------- + /// \brief Adds pre-processing information and steps to input of model. /// + /// \todo TODO: Consider remove this in sake of `InputInfo& input(...)` version + /// /// \param builder Pre-processing data for input tensor of model. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -52,6 +108,8 @@ class OPENVINO_API PrePostProcessor final { /// \brief Adds pre-processing information and steps to input of model - Rvalue version. /// + /// \todo TODO: Consider remove this in sake of `InputInfo& input(...)` version + /// /// \param builder Pre-processing data for input tensor of model. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner @@ -59,6 +117,8 @@ class OPENVINO_API PrePostProcessor final { /// \brief Adds post-processing information and steps to output of model. /// + /// \todo TODO: Consider remove this in sake of `OutputInfo& output(...)` version + /// /// \param builder Post-processing data for output tensor of model. /// /// \return Reference to 'this' to allow chaining with other calls in a builder-like manner @@ -66,17 +126,12 @@ class OPENVINO_API PrePostProcessor final { /// \brief Adds pre-processing information and steps to input of model - Rvalue version. /// + /// \todo TODO: Consider remove this in sake of `OutputInfo& output(...)` version + /// /// \param builder Post-processing data for output tensor of model. /// /// \return Rvalue reference to 'this' to allow chaining with other calls in a builder-like manner PrePostProcessor&& output(OutputInfo&& builder) &&; - - /// \brief Adds pre/post-processing operations to existing function - /// - /// \param function Existing function representing loaded model - /// - /// \return Function with added pre/post-processing operations - std::shared_ptr build(const std::shared_ptr& function); }; } // namespace preprocess diff --git a/ngraph/core/include/openvino/core/preprocess/preprocess_steps.hpp b/ngraph/core/include/openvino/core/preprocess/preprocess_steps.hpp index 6f331dd72d267a..5c85489ec29968 100644 --- a/ngraph/core/include/openvino/core/preprocess/preprocess_steps.hpp +++ b/ngraph/core/include/openvino/core/preprocess/preprocess_steps.hpp @@ -18,7 +18,7 @@ namespace preprocess { /// \brief Preprocessing steps. Each step typically intends adding of some operation to input parameter /// User application can specify sequence of preprocessing steps in a builder-like manner /// \code{.cpp} -/// auto proc = PrePostProcessor() +/// auto proc = PrePostProcessor(function) /// .input(InputInfo() /// .preprocess(PreProcessSteps() /// .mean(0.2f) // Subtract 0.2 from each element @@ -207,7 +207,7 @@ class OPENVINO_API PreProcessSteps final { /// planar input image ('NCHW', [1, 3, 224, 224]). Preprocessing may look like this: /// /// \code{.cpp} auto proc = - /// PrePostProcessor() + /// PrePostProcessor(function) /// .input(InputInfo() /// .tensor(InputTensorInfo().set_layout("NHWC")) // User data is NHWC /// .preprocess(PreProcessSteps() @@ -228,7 +228,7 @@ class OPENVINO_API PreProcessSteps final { /// planar input image ('NCHW', [1, 3, 480, 640]). Preprocessing may look like this: /// /// \code{.cpp} auto proc = - /// PrePostProcessor() + /// PrePostProcessor(function) /// .input(InputInfo() /// .preprocess(PreProcessSteps() /// .convert_layout({0, 3, 1, 2}) @@ -249,7 +249,7 @@ class OPENVINO_API PreProcessSteps final { /// BGR planes order. Preprocessing may look like this: /// /// \code{.cpp} auto proc = - /// PrePostProcessor() + /// PrePostProcessor(function) /// .input(InputInfo() /// .tensor(InputTensorInfo().set_layout("NCHW")) // User data is NCHW /// .preprocess(PreProcessSteps() diff --git a/ngraph/core/include/openvino/core/rtti.hpp b/ngraph/core/include/openvino/core/rtti.hpp index a39b37833b6e44..80064b985ba447 100644 --- a/ngraph/core/include/openvino/core/rtti.hpp +++ b/ngraph/core/include/openvino/core/rtti.hpp @@ -11,13 +11,14 @@ #define _OPENVINO_RTTI_WITH_TYPE(TYPE_NAME) _OPENVINO_RTTI_WITH_TYPE_VERSION(TYPE_NAME, "util") -#define _OPENVINO_RTTI_WITH_TYPE_VERSION(TYPE_NAME, VERSION_NAME) \ - static const ::ov::DiscreteTypeInfo& get_type_info_static() { \ - static const ::ov::DiscreteTypeInfo type_info{TYPE_NAME, 0, VERSION_NAME}; \ - return type_info; \ - } \ - const ::ov::DiscreteTypeInfo& get_type_info() const override { \ - return get_type_info_static(); \ +#define _OPENVINO_RTTI_WITH_TYPE_VERSION(TYPE_NAME, VERSION_NAME) \ + static const ::ov::DiscreteTypeInfo& get_type_info_static() { \ + static ::ov::DiscreteTypeInfo type_info{TYPE_NAME, 0, VERSION_NAME}; \ + type_info.hash(); \ + return type_info; \ + } \ + const ::ov::DiscreteTypeInfo& get_type_info() const override { \ + return get_type_info_static(); \ } #define _OPENVINO_RTTI_WITH_TYPE_VERSION_PARENT(TYPE_NAME, VERSION_NAME, PARENT_CLASS) \ @@ -25,10 +26,11 @@ #define _OPENVINO_RTTI_WITH_TYPE_VERSIONS_PARENT(TYPE_NAME, VERSION_NAME, PARENT_CLASS, OLD_VERSION) \ static const ::ov::DiscreteTypeInfo& get_type_info_static() { \ - static const ::ov::DiscreteTypeInfo type_info{TYPE_NAME, \ - OLD_VERSION, \ - VERSION_NAME, \ - &PARENT_CLASS::get_type_info_static()}; \ + static ::ov::DiscreteTypeInfo type_info{TYPE_NAME, \ + OLD_VERSION, \ + VERSION_NAME, \ + &PARENT_CLASS::get_type_info_static()}; \ + type_info.hash(); \ return type_info; \ } \ const ::ov::DiscreteTypeInfo& get_type_info() const override { \ diff --git a/ngraph/core/include/openvino/core/type.hpp b/ngraph/core/include/openvino/core/type.hpp index 63f850e4199ca5..08eb5c240704e3 100644 --- a/ngraph/core/include/openvino/core/type.hpp +++ b/ngraph/core/include/openvino/core/type.hpp @@ -39,7 +39,8 @@ struct OPENVINO_API DiscreteTypeInfo { : name(_name), version(_version), version_id(nullptr), - parent(_parent) {} + parent(_parent), + hash_value(0) {} constexpr DiscreteTypeInfo(const char* _name, uint64_t _version, @@ -48,22 +49,12 @@ struct OPENVINO_API DiscreteTypeInfo { : name(_name), version(_version), version_id(_version_id), - parent(_parent) {} + parent(_parent), + hash_value(0) {} - bool is_castable(const DiscreteTypeInfo& target_type) const { - return *this == target_type || (parent && parent->is_castable(target_type)); - } + bool is_castable(const DiscreteTypeInfo& target_type) const; - std::string get_version() const { - if (version_id) { - return std::string(version_id); - } - return std::to_string(version); - } - - operator std::string() const { - return std::string(name) + "_" + get_version(); - } + std::string get_version() const; // For use as a key bool operator<(const DiscreteTypeInfo& b) const; @@ -72,6 +63,14 @@ struct OPENVINO_API DiscreteTypeInfo { bool operator>=(const DiscreteTypeInfo& b) const; bool operator==(const DiscreteTypeInfo& b) const; bool operator!=(const DiscreteTypeInfo& b) const; + + operator std::string() const; + + size_t hash() const; + size_t hash(); + +private: + size_t hash_value; }; OPENVINO_API diff --git a/ngraph/core/include/openvino/core/variant.hpp b/ngraph/core/include/openvino/core/variant.hpp index 2337f0639901ab..5802fe14f9f649 100644 --- a/ngraph/core/include/openvino/core/variant.hpp +++ b/ngraph/core/include/openvino/core/variant.hpp @@ -58,6 +58,14 @@ class VariantImpl : public Variant { value_type m_value; }; +template <> +class VariantImpl : public Variant { +public: + using value_type = void; + + VariantImpl() = default; +}; + extern template class OPENVINO_API VariantImpl; extern template class OPENVINO_API VariantImpl; extern template class OPENVINO_API VariantImpl; diff --git a/ngraph/core/include/openvino/core/version.hpp b/ngraph/core/include/openvino/core/version.hpp index 97f82366f9705c..368398ba129352 100644 --- a/ngraph/core/include/openvino/core/version.hpp +++ b/ngraph/core/include/openvino/core/version.hpp @@ -1,7 +1,6 @@ // Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // - #pragma once #include "openvino/core/core_visibility.hpp" diff --git a/ngraph/core/include/openvino/op/embeddingbag_offsets_sum.hpp b/ngraph/core/include/openvino/op/embeddingbag_offsets_sum.hpp index 42f74822bd543f..afe4386a0a5b22 100644 --- a/ngraph/core/include/openvino/op/embeddingbag_offsets_sum.hpp +++ b/ngraph/core/include/openvino/op/embeddingbag_offsets_sum.hpp @@ -26,7 +26,7 @@ class OPENVINO_API EmbeddingBagOffsetsSum : public util::EmbeddingBagOffsetsBase /// /// \param emb_table tensor containing the embedding lookup table of the module of /// shape [num_emb, emb_dim1, emb_dim2, ...] and of type T - /// \param tensor of shape [num_indices] and of type T_IND. Required + /// \param indices tensor of shape [num_indices] and of type T_IND. Required /// \param offsets tensor of shape [batch] and of type T_IND containing the starting /// index positions of each "bag" in indices. Required. /// \param default_index scalar of type T_IND containing default index in embedding diff --git a/ngraph/core/include/openvino/op/gather_nd.hpp b/ngraph/core/include/openvino/op/gather_nd.hpp index 36f23d8970c930..5ec88f331e6017 100644 --- a/ngraph/core/include/openvino/op/gather_nd.hpp +++ b/ngraph/core/include/openvino/op/gather_nd.hpp @@ -4,16 +4,15 @@ #pragma once -#include "openvino/op/op.hpp" +#include "openvino/op/util/gather_nd_base.hpp" namespace ov { namespace op { namespace v5 { /// \brief GatherND operation -/// -class OPENVINO_API GatherND : public Op { +class OPENVINO_API GatherND : public op::util::GatherNDBase { public: - OPENVINO_OP("GatherND", "opset5", op::Op, 5); + OPENVINO_OP("GatherND", "opset5", op::util::GatherNDBase, 5); BWDCMP_RTTI_DECLARATION; GatherND() = default; @@ -26,16 +25,30 @@ class OPENVINO_API GatherND : public Op { GatherND(const Output& data, const Output& indices, const size_t batch_dims = 0); void validate_and_infer_types() override; - bool visit_attributes(AttributeVisitor& visitor) override; std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; +}; +} // namespace v5 - size_t get_batch_dims() const { - return m_batch_dims; - } +namespace v8 { +/// \brief GatherND operation +/// +class OPENVINO_API GatherND : public op::util::GatherNDBase { +public: + OPENVINO_OP("GatherND", "opset8", op::util::GatherNDBase); + BWDCMP_RTTI_DECLARATION; + GatherND() = default; -private: - size_t m_batch_dims; + /// \brief Constructs a GatherND operation. + /// + /// \param data Node producing data that are gathered + /// \param indices Node producing indices by which the operation gathers elements + /// or slices from data + /// \param batch_dims Specifies a number of batch dimensions + GatherND(const Output& data, const Output& indices, const size_t batch_dims = 0); + + void validate_and_infer_types() override; + std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; }; -} // namespace v5 +} // namespace v8 } // namespace op } // namespace ov diff --git a/ngraph/core/include/openvino/op/matmul.hpp b/ngraph/core/include/openvino/op/matmul.hpp index c14f2a366adc74..5026ebbc365595 100644 --- a/ngraph/core/include/openvino/op/matmul.hpp +++ b/ngraph/core/include/openvino/op/matmul.hpp @@ -50,8 +50,8 @@ class OPENVINO_API MatMul : public Op { } private: - bool m_transpose_a; - bool m_transpose_b; + bool m_transpose_a{false}; + bool m_transpose_b{false}; }; } // namespace v0 } // namespace op diff --git a/ngraph/core/include/openvino/op/op.hpp b/ngraph/core/include/openvino/op/op.hpp index c7920537c8a0e8..d1bae6d12fd283 100644 --- a/ngraph/core/include/openvino/op/op.hpp +++ b/ngraph/core/include/openvino/op/op.hpp @@ -31,7 +31,8 @@ class OPENVINO_API Op : public Node { public: static const ::ov::Node::type_info_t& get_type_info_static() { - static const ::ov::Node::type_info_t info{"Op", 0, "util"}; + static ::ov::Node::type_info_t info{"Op", 0, "util"}; + info.hash(); return info; } const ::ov::Node::type_info_t& get_type_info() const override { diff --git a/ngraph/core/include/openvino/op/shuffle_channels.hpp b/ngraph/core/include/openvino/op/shuffle_channels.hpp index f8318d2bce5020..3a231a9c266fed 100644 --- a/ngraph/core/include/openvino/op/shuffle_channels.hpp +++ b/ngraph/core/include/openvino/op/shuffle_channels.hpp @@ -49,8 +49,8 @@ class OPENVINO_API ShuffleChannels : public Op { private: bool evaluate_shuffle_channels(const HostTensorVector& outputs, const HostTensorVector& inputs) const; - int64_t m_axis; - int64_t m_group; + int64_t m_axis{1}; + int64_t m_group{1}; }; } // namespace v0 } // namespace op diff --git a/ngraph/core/include/openvino/op/slice.hpp b/ngraph/core/include/openvino/op/slice.hpp index f35cd715982c6b..caa5d365781329 100644 --- a/ngraph/core/include/openvino/op/slice.hpp +++ b/ngraph/core/include/openvino/op/slice.hpp @@ -32,6 +32,7 @@ class OPENVINO_API Slice : public Op { std::shared_ptr clone_with_new_inputs(const OutputVector& new_args) const override; + std::shared_ptr get_default_const_axes(const Output& start) const; PartialShape calculate_output_shape(const std::vector& starts, const std::vector& stops, const std::vector& steps, diff --git a/ngraph/core/include/openvino/op/util/embeddingbag_offsets_base.hpp b/ngraph/core/include/openvino/op/util/embeddingbag_offsets_base.hpp index 9c86232c5f005c..25a3fc86910909 100644 --- a/ngraph/core/include/openvino/op/util/embeddingbag_offsets_base.hpp +++ b/ngraph/core/include/openvino/op/util/embeddingbag_offsets_base.hpp @@ -26,7 +26,7 @@ class OPENVINO_API EmbeddingBagOffsetsBase : public Op { /// /// \param emb_table tensor containing the embedding lookup table of the module of /// shape [num_emb, emb_dim1, emb_dim2, ...] and of type T - /// \param tensor of shape [num_indices] and of type T_IND. Required + /// \param indices tensor of shape [num_indices] and of type T_IND. Required /// \param offsets tensor of shape [batch] and of type T_IND containing the starting /// index positions of each "bag" in indices. Required. /// \param per_sample_weigths tensor of the same shape as indices and of type T. diff --git a/ngraph/core/include/openvino/op/util/gather_nd_base.hpp b/ngraph/core/include/openvino/op/util/gather_nd_base.hpp new file mode 100644 index 00000000000000..2048ac06af28de --- /dev/null +++ b/ngraph/core/include/openvino/op/util/gather_nd_base.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "openvino/op/op.hpp" + +namespace ov { +namespace op { +namespace util { +/// \brief GatherNDBase basic class for GatherND v5 and v8 +class OPENVINO_API GatherNDBase : public Op { +public: + OPENVINO_OP("GatherNDBase", "util"); + BWDCMP_RTTI_DECLARATION; + GatherNDBase() = default; + + /// \brief Constructs a GatherND operation. + /// + /// \param data Node producing data that are gathered + /// \param indices Node producing indices by which the operation gathers elements + /// or slices from data + /// \param batch_dims Specifies a leading number of dimensions representing the batches + GatherNDBase(const Output& data, const Output& indices, const size_t batch_dims = 0); + + size_t get_batch_dims() const { + return m_batch_dims; + } + + void validate_inputs_and_infer_shape(); + + bool visit_attributes(AttributeVisitor& visitor) override; + +protected: + size_t m_batch_dims = 0; +}; +} // namespace util +} // namespace op +} // namespace ov diff --git a/ngraph/core/include/openvino/op/util/precision_sensitive_attribute.hpp b/ngraph/core/include/openvino/op/util/precision_sensitive_attribute.hpp new file mode 100644 index 00000000000000..eb0f7308d4b0d7 --- /dev/null +++ b/ngraph/core/include/openvino/op/util/precision_sensitive_attribute.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "openvino/core/core_visibility.hpp" +#include "openvino/core/node.hpp" +#include "openvino/core/variant.hpp" + +namespace ov { + +void OPENVINO_API mark_as_precision_sensitive(ov::Input node_input); + +void OPENVINO_API unmark_as_precision_sensitive(ov::Input node_input); + +bool OPENVINO_API is_precision_sensitive(const ov::Input& node_input); + +/** + * @brief PrecisionSensitive class represents runtime info attribute that marks + * input to an operation as a precision sensitive and disables compression to FP16 + * of the subgraph before this input. + */ +class OPENVINO_API PrecisionSensitive : public VariantImpl { +public: + OPENVINO_RTTI("precision_sensitive", "0"); + + PrecisionSensitive() = default; + + bool is_copyable() const override { + return false; + } +}; + +} // namespace ov diff --git a/ngraph/core/include/openvino/opsets/opset8_tbl.hpp b/ngraph/core/include/openvino/opsets/opset8_tbl.hpp index 0c686bdab09213..e3e9c0a5f8383e 100644 --- a/ngraph/core/include/openvino/opsets/opset8_tbl.hpp +++ b/ngraph/core/include/openvino/opsets/opset8_tbl.hpp @@ -144,7 +144,6 @@ _OPENVINO_OP_REG(SoftPlus, ov::op::v4) _OPENVINO_OP_REG(Swish, ov::op::v4) // New operations added in opset5 -_OPENVINO_OP_REG(GatherND, ov::op::v5) _OPENVINO_OP_REG(GRUSequence, ov::op::v5) _OPENVINO_OP_REG(HSigmoid, ov::op::v5) _OPENVINO_OP_REG(LogSoftmax, ov::op::v5) @@ -175,6 +174,7 @@ _OPENVINO_OP_REG(Roll, ov::op::v7) // New operations added in opset8 _OPENVINO_OP_REG(Gather, ov::op::v8) +_OPENVINO_OP_REG(GatherND, ov::op::v8) _OPENVINO_OP_REG(AdaptiveAvgPool, ov::op::v8) _OPENVINO_OP_REG(AdaptiveMaxPool, ov::op::v8) _OPENVINO_OP_REG(DeformableConvolution, ov::op::v8) diff --git a/ngraph/core/include/openvino/pass/serialize.hpp b/ngraph/core/include/openvino/pass/serialize.hpp index c964d74c5f21fa..67909afe80efaa 100644 --- a/ngraph/core/include/openvino/pass/serialize.hpp +++ b/ngraph/core/include/openvino/pass/serialize.hpp @@ -33,12 +33,14 @@ class OPENVINO_API Serialize : public ov::pass::FunctionPass { }; bool run_on_function(std::shared_ptr f) override; + OPENVINO_DEPRECATED("This constructor is deprecated. Please use new extension API") Serialize(std::ostream& xmlFile, std::ostream& binFile, std::map custom_opsets, Version version = Version::UNSPECIFIED); Serialize(std::ostream& xmlFile, std::ostream& binFile, Version version = Version::UNSPECIFIED); + OPENVINO_DEPRECATED("This constructor is deprecated. Please use new extension API") Serialize(const std::string& xmlPath, const std::string& binPath, std::map custom_opsets, @@ -74,10 +76,14 @@ class OPENVINO_API StreamSerialize : public ov::pass::FunctionPass { bool run_on_function(std::shared_ptr f) override; + OPENVINO_DEPRECATED("This constructor is deprecated. Please use new extension API") StreamSerialize(std::ostream& stream, std::map&& custom_opsets = {}, const std::function& custom_data_serializer = {}, Serialize::Version version = Serialize::Version::UNSPECIFIED); + StreamSerialize(std::ostream& stream, + const std::function& custom_data_serializer = {}, + Serialize::Version version = Serialize::Version::UNSPECIFIED); private: std::ostream& m_stream; diff --git a/ngraph/core/reference/CMakeLists.txt b/ngraph/core/reference/CMakeLists.txt index 99c82bf32bbb93..e7b1d1bb20bb3f 100644 --- a/ngraph/core/reference/CMakeLists.txt +++ b/ngraph/core/reference/CMakeLists.txt @@ -15,7 +15,7 @@ set(REF_IMPL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include") source_group("src" FILES ${LIBRARY_SRC}) source_group("include" FILES ${PUBLIC_HEADERS}) -# Create shared library +# Create static library add_library(${TARGET_NAME} STATIC ${LIBRARY_SRC} ${PUBLIC_HEADERS}) if(COMMAND ie_faster_build) @@ -31,8 +31,13 @@ endif() target_compile_definitions(${TARGET_NAME} PRIVATE XBYAK_NO_OP_NAMES XBYAK64) -# Defines macro in C++ to load backend plugin -target_include_directories(${TARGET_NAME} PUBLIC ${REF_IMPL_INCLUDE_DIR} ${NGRAPH_INCLUDE_PATH}) +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(${TARGET_NAME} PUBLIC OPENVINO_STATIC_LIBRARY) +endif() + +target_include_directories(${TARGET_NAME} PUBLIC + $ + $) link_system_libraries(${TARGET_NAME} PRIVATE xbyak) @@ -41,5 +46,7 @@ add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) # Add an alias so that library can be used inside the build tree, e.g. when testing add_library(ngraph::reference ALIAS ${TARGET_NAME}) +ov_install_static_lib(${TARGET_NAME} ngraph) + # developer package openvino_developer_export_targets(COMPONENT ngraph TARGETS ngraph::reference) diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/gather_nd.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/gather_nd.hpp index 40e921e67a297e..b3681adad4c1a3 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/gather_nd.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/gather_nd.hpp @@ -56,11 +56,6 @@ void gather_nd(const T* const params, const Shape batch_shape(begin(params_shape), next(begin(params_shape), batch_dims)); const auto batch_size = shape_size(batch_shape); - if (batch_dims && batch_size != out_shape.front()) { - throw std::domain_error{"out_shape should have on first dim multiplication of batch number of first" - "dimensions of shape "}; - } - if (!std::equal(begin(params_shape), next(begin(params_shape), batch_dims), begin(indices_shape))) { throw std::domain_error{"dimensions in params and indices have to be equal on batch dimensions"}; } diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp index 74c0261112b653..72c1f2230b2ae9 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/max_pool.hpp @@ -142,12 +142,7 @@ void validate_max_pool_kernel_params(const size_t dims, /// but at the same time it can represent pixel offsets in the filter itself (dilated or non-dilated) template struct Coord : public std::vector { - Coord(const Shape& pads_begin) { - std::vector::reserve(pads_begin.size()); - for (const auto axis_padding : pads_begin) { - std::vector::push_back(0 - axis_padding); - } - } + Coord() = default; Coord(std::initializer_list&& values) : std::vector{std::move(values)} {} }; @@ -165,47 +160,15 @@ bool elem_in_padding_area(const Coord& kernel_position, return false; } -template -Coord next_kernel_position_2D(Coord kernel_position, - const Shape& kernel, - const Strides& kernel_strides, - const Strides& kernel_dilations, - const Shape& data_shape, - const Shape& pads_begin, - const Shape& pads_end) { - // move the kernel horizontally one stride to the right - kernel_position[1] += kernel_strides[1]; - - // if the top-right corner of the kernel is outside of the padding area, - // move it back to the left and one stride down - if (kernel_position[1] + (kernel[1] - 1) * kernel_dilations[1] >= data_shape[3] + pads_end[1]) { - kernel_position[1] = 0 - pads_begin[1]; - kernel_position[0] += kernel_strides[0]; - } - - return kernel_position; -} - -template -Coord next_kernel_position_3D(Coord kernel_position, - const Shape& kernel, - const Strides& kernel_strides, - const Strides& kernel_dilations, - const Shape& data_shape, - const Shape& pads_begin, - const Shape& pads_end) { - kernel_position[2] += kernel_strides[2]; - - if (kernel_position[2] + (kernel[2] - 1) * kernel_dilations[2] >= data_shape[4] + pads_end[2]) { - kernel_position[2] = 0 - pads_begin[2]; - kernel_position[1] += kernel_strides[1]; - if (kernel_position[1] + (kernel[1] - 1) * kernel_dilations[1] >= data_shape[3] + pads_end[1]) { - kernel_position[1] = 0 - pads_begin[1]; - kernel_position[0] += kernel_strides[0]; - } +Coord calculate_kernel_position(const Coord& out_elem_coord, + const Strides& kernel_strides, + const Shape& pads_begin) { + Coord top_left_corner; + top_left_corner.reserve(out_elem_coord.size()); + for (size_t i = 0u; i < out_elem_coord.size(); ++i) { + top_left_corner.emplace_back(out_elem_coord[i] * kernel_strides[i] - pads_begin[i]); } - - return kernel_position; + return top_left_corner; } namespace kernel { @@ -255,43 +218,44 @@ void max_pool_2d(const Values_t* data, const size_t indices_offset) { validate_max_pool_kernel_params(2, kernel, kernel_strides, kernel_dilations, pads_begin, pads_end); - Coord kernel_position{pads_begin}; + // helper constants(axes) denoting dimensions in the input data shape and kernel shape + constexpr size_t data_H = 2, data_W = 3; + constexpr size_t kernel_H = 0, kernel_W = 1; // select max elem and its index for each "placeholder" in the out buffer (pointed to by out_idx) - for (size_t out_idx = 0; out_idx < out_shape[2] * out_shape[3]; ++out_idx) { - Values_t max_elem = std::numeric_limits::lowest(); - Indices_t max_elem_idx = Indices_t{0}; + size_t out_idx = 0u; + for (size_t out_row = 0u; out_row < out_shape[data_H]; ++out_row) { + for (size_t out_col = 0u; out_col < out_shape[data_W]; ++out_col) { + Values_t max_elem = std::numeric_limits::lowest(); + Indices_t max_elem_idx = Indices_t{0}; + + const auto kernel_position = calculate_kernel_position({out_row, out_col}, kernel_strides, pads_begin); + // find the max element in the area covered by a current position of the kernel + for (size_t kernel_row = 0; kernel_row < kernel[kernel_H]; ++kernel_row) { + for (size_t kernel_col = 0; kernel_col < kernel[kernel_W]; ++kernel_col) { + // offset from the top-left corner of the kernel for a given row and col + const Coord kernel_offset{kernel_row * kernel_dilations[kernel_H], + kernel_col * kernel_dilations[kernel_W]}; - // find the max element in the area covered by a current position of the kernel - for (size_t kernel_row = 0; kernel_row < kernel[0]; ++kernel_row) { - for (size_t kernel_col = 0; kernel_col < kernel[1]; ++kernel_col) { - // offset from the top-left corner of the kernel for a given row and col - const Coord kernel_offset{kernel_row * kernel_dilations[0], kernel_col * kernel_dilations[1]}; - - // ignore the elements in the padding area - if (!elem_in_padding_area(kernel_position, kernel_offset, data_shape)) { - // index of the flattened tensor element under the current row & column of the kernel - const size_t data_elem_index = - data_shape[2] * (kernel_offset[0] + kernel_position[0]) + kernel_offset[1] + kernel_position[1]; - - if (data[data_elem_index] > max_elem) { - max_elem = data[data_elem_index]; - max_elem_idx = data_elem_index; + // ignore the elements in the padding area + if (!elem_in_padding_area(kernel_position, kernel_offset, data_shape)) { + // index of the flattened tensor element under the current row & column of the kernel + const size_t data_elem_index = + data_shape[data_W] * (kernel_offset[kernel_H] + kernel_position[kernel_H]) + + kernel_offset[kernel_W] + kernel_position[kernel_W]; + + if (data[data_elem_index] > max_elem) { + max_elem = data[data_elem_index]; + max_elem_idx = data_elem_index; + } } } } - } - - values[out_idx] = max_elem; - indices[out_idx] = max_elem_idx + indices_offset; - kernel_position = next_kernel_position_2D(kernel_position, - kernel, - kernel_strides, - kernel_dilations, - data_shape, - pads_begin, - pads_end); + values[out_idx] = max_elem; + indices[out_idx] = max_elem_idx + indices_offset; + ++out_idx; + } } } @@ -309,49 +273,51 @@ void max_pool_3d(const Values_t* data, const size_t indices_offset) { validate_max_pool_kernel_params(3, kernel, kernel_strides, kernel_dilations, pads_begin, pads_end); - Coord kernel_position{pads_begin}; - - const size_t out_elems = shape_size(std::begin(out_shape) + 2, std::end(out_shape)); + // helper constants(axes) denoting dimensions in the input data shape and kernel shape + constexpr size_t data_D = 2, data_H = 3, data_W = 4; + constexpr size_t kernel_D = 0, kernel_H = 1, kernel_W = 2; // select max elem and its index for each "placeholder" in the out buffer (pointed to by out_idx) - for (size_t out_idx = 0; out_idx < out_elems; ++out_idx) { - Values_t max_elem = std::numeric_limits::lowest(); - Indices_t max_elem_idx = Indices_t{0}; - - for (size_t kernel_channel = 0; kernel_channel < kernel[0]; ++kernel_channel) { - for (size_t kernel_row = 0; kernel_row < kernel[1]; ++kernel_row) { - for (size_t kernel_col = 0; kernel_col < kernel[2]; ++kernel_col) { - // offset from the top-left corner of the kernel for a given row and col - const Coord kernel_offset{kernel_channel * kernel_dilations[0], - kernel_row * kernel_dilations[1], - kernel_col * kernel_dilations[2]}; - - // ignore the elements in the padding area - if (!elem_in_padding_area(kernel_position, kernel_offset, data_shape)) { - // index of the flattened tensor element under the current row & column of the kernel - const size_t data_elem_index = - data_shape[2] * data_shape[3] * (kernel_offset[0] + kernel_position[0]) + - data_shape[3] * (kernel_offset[1] + kernel_position[1]) + kernel_offset[2] + - kernel_position[2]; - - if (data[data_elem_index] > max_elem) { - max_elem = data[data_elem_index]; - max_elem_idx = data_elem_index; + size_t out_idx = 0u; + for (size_t out_channel = 0u; out_channel < out_shape[data_D]; ++out_channel) { + for (size_t out_row = 0u; out_row < out_shape[data_H]; ++out_row) { + for (size_t out_col = 0u; out_col < out_shape[data_W]; ++out_col) { + Values_t max_elem = std::numeric_limits::lowest(); + Indices_t max_elem_idx = Indices_t{0}; + + const auto kernel_position = + calculate_kernel_position({out_channel, out_row, out_col}, kernel_strides, pads_begin); + + for (size_t kernel_channel = 0; kernel_channel < kernel[kernel_D]; ++kernel_channel) { + for (size_t kernel_row = 0; kernel_row < kernel[kernel_H]; ++kernel_row) { + for (size_t kernel_col = 0; kernel_col < kernel[kernel_W]; ++kernel_col) { + // offset from the top-left corner of the kernel for a given row and col + const Coord kernel_offset{kernel_channel * kernel_dilations[kernel_D], + kernel_row * kernel_dilations[kernel_H], + kernel_col * kernel_dilations[kernel_W]}; + + // ignore the elements in the padding area + if (!elem_in_padding_area(kernel_position, kernel_offset, data_shape)) { + // index of the flattened tensor element under the current row & column of the kernel + const size_t data_elem_index = + data_shape[data_H] * data_shape[data_W] * + (kernel_offset[kernel_D] + kernel_position[kernel_D]) + + data_shape[data_W] * (kernel_offset[kernel_H] + kernel_position[kernel_H]) + + kernel_offset[kernel_W] + kernel_position[kernel_W]; + + if (data[data_elem_index] > max_elem) { + max_elem = data[data_elem_index]; + max_elem_idx = data_elem_index; + } + } } } } + values[out_idx] = max_elem; + indices[out_idx] = max_elem_idx + indices_offset; + ++out_idx; } } - values[out_idx] = max_elem; - indices[out_idx] = max_elem_idx + indices_offset; - - kernel_position = next_kernel_position_3D(kernel_position, - kernel, - kernel_strides, - kernel_dilations, - data_shape, - pads_begin, - pads_end); } } } // namespace kernel diff --git a/ngraph/core/reference/src/runtime/reference/pad.cpp b/ngraph/core/reference/src/runtime/reference/pad.cpp index cb42847a8e6093..b261c0e35fd20c 100644 --- a/ngraph/core/reference/src/runtime/reference/pad.cpp +++ b/ngraph/core/reference/src/runtime/reference/pad.cpp @@ -95,7 +95,7 @@ struct ConstPad : PadBase { for (size_t i = 0; i != coord.size(); ++i) { const auto sc = static_cast(out_coord[i]); - const auto cc = sc - padding_begin[i]; + const auto cc = sc - padding_begin.at(i); if (0 <= cc && cc < static_cast(data_shape[i])) { coord[i] = cc; } else { @@ -115,7 +115,7 @@ struct EdgePad : PadBase { for (size_t i = 0; i != coord.size(); ++i) { const auto sc = static_cast(out_coord[i]); - const auto cc = sc - padding_begin[i]; + const auto cc = sc - padding_begin.at(i); coord[i] = clamp(cc, 0, data_shape[i] - 1); } return std::addressof(coord); @@ -142,7 +142,7 @@ struct SymmetricAndReflectPad : PadBase { const auto shape_dim = static_cast(data_shape[i]); const auto sc = static_cast(out_coord[i]); - const auto cc = sc - padding_begin[i]; + const auto cc = sc - padding_begin.at(i); const auto rollfront_cc = cc >= 0 ? cc : -cc - axis_correction; const auto rollback_cc = shape_dim - (rollfront_cc + 2 - shape_dim) + axis_correction; coord[i] = rollfront_cc < shape_dim ? rollfront_cc : rollback_cc; @@ -154,9 +154,9 @@ struct SymmetricAndReflectPad : PadBase { void check_inputs() const override { for (size_t i = 0; i != padding_begin.size(); ++i) { const auto axis_size = static_cast(data_shape[i]); - NGRAPH_CHECK(padding_begin[i] - axis_correction < axis_size, + NGRAPH_CHECK(padding_begin.at(i) - axis_correction < axis_size, "padding below should be less than data shape"); - NGRAPH_CHECK(padding_end[i] - axis_correction < axis_size, "padding should be less than data shape"); + NGRAPH_CHECK(padding_end.at(i) - axis_correction < axis_size, "padding should be less than data shape"); } } diff --git a/ngraph/core/shape_inference/CMakeLists.txt b/ngraph/core/shape_inference/CMakeLists.txt index 23897095fce754..f769ae59d3ef76 100644 --- a/ngraph/core/shape_inference/CMakeLists.txt +++ b/ngraph/core/shape_inference/CMakeLists.txt @@ -15,11 +15,18 @@ set(SHAPE_INFER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include") source_group("src" FILES ${LIBRARY_SRC}) source_group("include" FILES ${PUBLIC_HEADERS}) -# Create shared library +# Create static library add_library(${TARGET_NAME} STATIC ${LIBRARY_SRC} ${PUBLIC_HEADERS}) -# Defines macro in C++ to load backend plugin -target_include_directories(${TARGET_NAME} PUBLIC ${SHAPE_INFER_INCLUDE_DIR} ${NGRAPH_INCLUDE_PATH}) +target_include_directories(${TARGET_NAME} PUBLIC + $ + $) + +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(${TARGET_NAME} PUBLIC OPENVINO_STATIC_LIBRARY) +endif() + +ov_install_static_lib(${TARGET_NAME} ngraph) # developer package openvino_developer_export_targets(COMPONENT ngraph TARGETS ${TARGET_NAME}) diff --git a/ngraph/core/src/descriptor/tensor.cpp b/ngraph/core/src/descriptor/tensor.cpp index 2cf21ef978df65..c798bfd00c72f2 100644 --- a/ngraph/core/src/descriptor/tensor.cpp +++ b/ngraph/core/src/descriptor/tensor.cpp @@ -23,6 +23,7 @@ ov::descriptor::Tensor::Tensor(const element::Type& element_type, m_partial_shape(pshape), m_shape_changed(true) {} +OPENVINO_SUPPRESS_DEPRECATED_START void ov::descriptor::Tensor::set_tensor_type(const element::Type& element_type, const PartialShape& pshape) { set_element_type(element_type); set_partial_shape(pshape); @@ -36,6 +37,7 @@ void ov::descriptor::Tensor::set_partial_shape(const PartialShape& partial_shape m_partial_shape = partial_shape; m_shape_changed = true; } +OPENVINO_SUPPRESS_DEPRECATED_END void ov::descriptor::Tensor::invalidate_values() { m_upper_value = nullptr; diff --git a/ngraph/core/src/dimension.cpp b/ngraph/core/src/dimension.cpp index 84b156ae7b4da3..1e04c40dbdd70c 100644 --- a/ngraph/core/src/dimension.cpp +++ b/ngraph/core/src/dimension.cpp @@ -105,3 +105,16 @@ Dimension::value_type Dimension::get_max_length() const { Dimension::value_type Dimension::get_min_length() const { return dimension_length(m_dimension.get_min_val()); } + +const int64_t& ov::AttributeAdapter::get() { + if (!m_buffer_valid) { + m_buffer = m_ref.is_dynamic() ? -1 : m_ref.get_length(); + m_buffer_valid = true; + } + return m_buffer; +} + +void ov::AttributeAdapter::set(const int64_t& value) { + m_ref = value == -1 ? ov::Dimension::dynamic() : Dimension(value); + m_buffer_valid = false; +} diff --git a/ngraph/core/src/function.cpp b/ngraph/core/src/function.cpp index 396a68f04edcaf..1732d0f4352909 100644 --- a/ngraph/core/src/function.cpp +++ b/ngraph/core/src/function.cpp @@ -87,6 +87,10 @@ ngraph::ParameterVector auto_detect_parameters(const std::vector::type_info; - const std::string& AttributeAdapter::get() { m_dump = m_ref.to_string(); return m_dump; @@ -364,4 +362,4 @@ bool LayoutAttribute::visit_attributes(AttributeVisitor& visitor) { return true; } -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/ngraph/core/src/node.cpp b/ngraph/core/src/node.cpp index 7f7c3a6cb8bbb9..2786cc6609437e 100644 --- a/ngraph/core/src/node.cpp +++ b/ngraph/core/src/node.cpp @@ -222,7 +222,9 @@ void ov::Node::set_input_is_relevant_to_value(size_t i, bool relevant) { } void ov::Node::set_output_type(size_t i, const element::Type& element_type, const PartialShape& pshape) { + OPENVINO_SUPPRESS_DEPRECATED_START get_output_descriptor(i).get_tensor_ptr()->set_tensor_type(element_type, pshape); + OPENVINO_SUPPRESS_DEPRECATED_END } std::string ov::Node::description() const { diff --git a/ngraph/core/src/op/batch_to_space.cpp b/ngraph/core/src/op/batch_to_space.cpp index 763a37db8cd5cb..3cee1ba4f42f59 100644 --- a/ngraph/core/src/op/batch_to_space.cpp +++ b/ngraph/core/src/op/batch_to_space.cpp @@ -19,6 +19,7 @@ #include "ngraph/runtime/reference/strided_slice.hpp" #include "ngraph/shape.hpp" #include "ngraph/slice_plan.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -30,6 +31,9 @@ ngraph::op::v1::BatchToSpace::BatchToSpace(const ngraph::Output& d const ngraph::Output& crops_begin, const ngraph::Output& crops_end) : Op({data, block_shape, crops_begin, crops_end}) { + ov::mark_as_precision_sensitive(input(1)); + ov::mark_as_precision_sensitive(input(2)); + ov::mark_as_precision_sensitive(input(3)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/constant.cpp b/ngraph/core/src/op/constant.cpp index 2688d2296b4c2b..8fd55284055ad2 100644 --- a/ngraph/core/src/op/constant.cpp +++ b/ngraph/core/src/op/constant.cpp @@ -469,6 +469,7 @@ template static bool test_bitwise_identical(const T* data, const size_t size) { bool data_is_constant = true; if (size > 0) { + OPENVINO_ASSERT(data != nullptr); const T compare = data[0]; for (size_t i = 1; i < size; i++) { if (data[i] != compare) { diff --git a/ngraph/core/src/op/convolution.cpp b/ngraph/core/src/op/convolution.cpp index d4fdc345ccf4d3..a66c88ee81fdff 100644 --- a/ngraph/core/src/op/convolution.cpp +++ b/ngraph/core/src/op/convolution.cpp @@ -12,6 +12,7 @@ #include "ngraph/op/reshape.hpp" #include "ngraph/util.hpp" #include "ngraph/validation_util.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -117,6 +118,7 @@ op::v1::ConvolutionBackpropData::ConvolutionBackpropData(const Output& dat m_pads_end(pads_end), m_auto_pad(auto_pad), m_output_padding(output_padding) { + ov::mark_as_precision_sensitive(input(2)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/gather_nd.cpp b/ngraph/core/src/op/gather_nd.cpp index d4c54e5066e3d9..ceac01e68c8e30 100644 --- a/ngraph/core/src/op/gather_nd.cpp +++ b/ngraph/core/src/op/gather_nd.cpp @@ -15,110 +15,67 @@ using namespace ngraph; BWDCMP_RTTI_DEFINITION(op::v5::GatherND); op::v5::GatherND::GatherND(const Output& data, const Output& indices, const size_t batch_dims) - : Op({data, indices}), - m_batch_dims(batch_dims) { + : GatherNDBase(data, indices, batch_dims) { constructor_validate_and_infer_types(); } void op::v5::GatherND::validate_and_infer_types() { NGRAPH_OP_SCOPE(v5_GatherND_validate_and_infer_types); - // check types of input tensors - const auto& data_type = get_input_element_type(0); - const auto& indices_type = get_input_element_type(1); + validate_inputs_and_infer_shape(); - NODE_VALIDATION_CHECK(this, - indices_type.is_integral_number(), - "The indices type is expected to be an integer type. Got: ", - indices_type); + // If we have m_batch_dims > 1 we need to fuse batch dimensions of output + if (m_batch_dims > 1) { + const auto& output_pshape = get_output_partial_shape(0); + const auto& data_type = get_input_element_type(0); - // check ranks of input tensors - const auto& data_pshape = get_input_partial_shape(0); - const auto& indices_pshape = get_input_partial_shape(1); - - if (data_pshape.rank().is_static()) { - NODE_VALIDATION_CHECK(this, data_pshape.rank().get_length() > 0, "Data rank must be at least 1."); - - NODE_VALIDATION_CHECK(this, - data_pshape.rank().get_length() > static_cast(m_batch_dims), - "Number of batch dimensions must not exceed a rank of data."); - } - - if (indices_pshape.rank().is_static()) { - NODE_VALIDATION_CHECK(this, indices_pshape.rank().get_length() > 0, "Indices rank must be at least 1."); - - NODE_VALIDATION_CHECK(this, - indices_pshape.rank().get_length() > static_cast(m_batch_dims), - "Number of batch dimensions must not exceed a rank of indices."); - } - - if (data_pshape.rank().is_static() && indices_pshape.rank().is_static()) { - // check that batch dimensions of data and indices are the same - for (size_t batch_dim = 0; batch_dim < m_batch_dims; batch_dim++) { - if (data_pshape[batch_dim].is_static() && indices_pshape[batch_dim].is_static()) { - NODE_VALIDATION_CHECK(this, - data_pshape[batch_dim].get_length() == indices_pshape[batch_dim].get_length(), - "Batch dimensions of data and indices must be the same."); - } - } - - if (indices_pshape[indices_pshape.rank().get_length() - 1].is_static()) { - NODE_VALIDATION_CHECK( - this, - static_cast(indices_pshape[indices_pshape.rank().get_length() - 1].get_length() + - m_batch_dims) <= data_pshape.rank().get_length(), - "Length of a tuple with indices must not exceed a rank of data tensor " - "excluding " - "batch dimensions."); - } - } - - // set output shape - set_output_size(1); - if (data_pshape.rank().is_static() && indices_pshape.rank().is_static() && - indices_pshape[indices_pshape.rank().get_length() - 1].is_static()) { - auto indices_tuple_length = indices_pshape[indices_pshape.rank().get_length() - 1].get_length(); - int64_t slice_length = data_pshape.rank().get_length() - indices_tuple_length - m_batch_dims; - int64_t output_indices_length = indices_pshape.rank().get_length() - m_batch_dims - 1; - auto output_rank = output_indices_length + slice_length; - size_t delta_output_rank = 0; - if (m_batch_dims > 0) { - delta_output_rank = 1; - } - std::vector output_shape(output_rank + delta_output_rank); - if (m_batch_dims > 0) { + if (output_pshape.rank().is_static()) { + const auto& out_size = output_pshape.size(); + std::vector output_shape(out_size - m_batch_dims + 1); output_shape[0] = 1; for (size_t dim = 0; dim < m_batch_dims; dim++) { - if (data_pshape[dim].is_static()) { - output_shape[0] *= data_pshape[dim].get_length(); - } else if (indices_pshape[dim].is_static()) { - output_shape[0] *= indices_pshape[dim].get_length(); + if (output_pshape[dim].is_static()) { + output_shape[0] *= output_pshape[dim].get_length(); } else { output_shape[0] = Dimension::dynamic(); break; } } + size_t ind = 1; + for (size_t dim = m_batch_dims; dim < out_size; dim++) { + if (output_pshape[dim].is_static()) { + output_shape[ind] = output_pshape[dim].get_length(); + } else { + output_shape[ind] = Dimension::dynamic(); + } + ind++; + } + + set_output_type(0, data_type, ov::PartialShape(output_shape)); } - for (int64_t dim = 0; dim < output_indices_length; dim++) { - output_shape[dim + delta_output_rank] = indices_pshape[dim + m_batch_dims]; - } - for (int64_t dim = 0; dim < slice_length; dim++) { - output_shape[output_indices_length + dim + delta_output_rank] = - data_pshape[m_batch_dims + indices_tuple_length + dim]; - } - set_output_type(0, data_type, ov::PartialShape(output_shape)); - } else { - set_output_type(0, data_type, ov::PartialShape::dynamic()); } } -bool op::v5::GatherND::visit_attributes(AttributeVisitor& visitor) { - NGRAPH_OP_SCOPE(v5_GatherND_visit_attributes); - visitor.on_attribute("batch_dims", m_batch_dims); - return true; -} - shared_ptr op::v5::GatherND::clone_with_new_inputs(const OutputVector& new_args) const { NGRAPH_OP_SCOPE(v5_GatherND_clone_with_new_inputs); check_new_args_count(this, new_args); return make_shared(new_args.at(0), new_args.at(1), m_batch_dims); } + +// ------------------------------ V8 ------------------------------ +BWDCMP_RTTI_DEFINITION(op::v8::GatherND); + +op::v8::GatherND::GatherND(const Output& data, const Output& indices, const size_t batch_dims) + : GatherNDBase(data, indices, batch_dims) { + constructor_validate_and_infer_types(); +} + +void op::v8::GatherND::validate_and_infer_types() { + NGRAPH_OP_SCOPE(v8_GatherND_validate_and_infer_types); + validate_inputs_and_infer_shape(); +} + +shared_ptr op::v8::GatherND::clone_with_new_inputs(const OutputVector& new_args) const { + NGRAPH_OP_SCOPE(v8_GatherND_clone_with_new_inputs); + check_new_args_count(this, new_args); + return make_shared(new_args.at(0), new_args.at(1), m_batch_dims); +} diff --git a/ngraph/core/src/op/group_conv.cpp b/ngraph/core/src/op/group_conv.cpp index 850d8f0038d979..625110cabef0fa 100644 --- a/ngraph/core/src/op/group_conv.cpp +++ b/ngraph/core/src/op/group_conv.cpp @@ -14,6 +14,7 @@ #include "ngraph/op/convolution.hpp" #include "ngraph/op/reshape.hpp" #include "ngraph/validation_util.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -277,6 +278,7 @@ op::v1::GroupConvolutionBackpropData::GroupConvolutionBackpropData(const Output< m_pads_end(pads_end), m_auto_pad(auto_pad), m_output_padding(output_padding) { + ov::mark_as_precision_sensitive(input(2)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/interpolate.cpp b/ngraph/core/src/op/interpolate.cpp index d244f265b426c1..2aed5f92af7e9d 100644 --- a/ngraph/core/src/op/interpolate.cpp +++ b/ngraph/core/src/op/interpolate.cpp @@ -13,6 +13,7 @@ #include "itt.hpp" #include "ngraph/op/constant.hpp" #include "ngraph/runtime/reference/interpolate.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -22,6 +23,7 @@ BWDCMP_RTTI_DEFINITION(op::v0::Interpolate); op::v0::Interpolate::Interpolate(const Output& image, const Output& output_shape, const Attributes& attrs) : Op({image, output_shape}), m_attrs(attrs) { + ov::mark_as_precision_sensitive(input(1)); constructor_validate_and_infer_types(); } @@ -99,6 +101,8 @@ op::v4::Interpolate::Interpolate(const Output& image, const op::v4::Interpolate::InterpolateAttrs& attrs) : Op({image, output_shape, scales, axes}), m_attrs(attrs) { + ov::mark_as_precision_sensitive(input(1)); + ov::mark_as_precision_sensitive(input(2)); constructor_validate_and_infer_types(); } @@ -294,9 +298,20 @@ std::vector get_axes_vector(const HostTensorVector& args) { std::vector axes; if (num_of_inputs == max_num_of_ports) { - int64_t* axes_data_ptr = args[axes_port]->get_data_ptr(); + auto axes_arg = args[axes_port]; size_t num_of_axes = args[axes_port]->get_shape()[0]; - axes.insert(axes.end(), axes_data_ptr, axes_data_ptr + num_of_axes); + axes.reserve(num_of_axes); + + if (axes_arg->get_element_type() == ngraph::element::i64) { + int64_t* axes_ptr = axes_arg->get_data_ptr(); + axes.insert(axes.end(), axes_ptr, axes_ptr + num_of_axes); + } else if (axes_arg->get_element_type() == ngraph::element::i32) { + int32_t* axes_ptr = axes_arg->get_data_ptr(); + for (size_t i = 0; i < num_of_axes; ++i) + axes.push_back(axes_ptr[i]); + } else { + OPENVINO_ASSERT(false, "Failed to process ", axes_arg->get_element_type()); + } } else { for (size_t i = 0; i < input_rank; ++i) { axes.push_back(i); @@ -308,9 +323,19 @@ std::vector get_axes_vector(const HostTensorVector& args) { std::vector get_target_shape_vector(const HostTensorVector& args, size_t num_of_axes) { std::vector target_shape; - - int64_t* target_shape_ptr = args[target_shape_port]->get_data_ptr(); - target_shape.insert(target_shape.end(), target_shape_ptr, target_shape_ptr + num_of_axes); + target_shape.reserve(num_of_axes); + + auto target_shape_arg = args[target_shape_port]; + if (target_shape_arg->get_element_type() == ngraph::element::i64) { + int64_t* target_shape_ptr = target_shape_arg->get_data_ptr(); + target_shape.insert(target_shape.end(), target_shape_ptr, target_shape_ptr + num_of_axes); + } else if (target_shape_arg->get_element_type() == ngraph::element::i32) { + int32_t* target_shape_ptr = target_shape_arg->get_data_ptr(); + for (size_t i = 0; i < num_of_axes; ++i) + target_shape.push_back(target_shape_ptr[i]); + } else { + OPENVINO_ASSERT(false, "Failed to process ", target_shape_arg->get_element_type()); + } return target_shape; } diff --git a/ngraph/core/src/op/lstm_sequence.cpp b/ngraph/core/src/op/lstm_sequence.cpp index c5a60507aa91c7..579f5c02f6a232 100644 --- a/ngraph/core/src/op/lstm_sequence.cpp +++ b/ngraph/core/src/op/lstm_sequence.cpp @@ -538,6 +538,23 @@ void op::v5::LSTMSequence::validate_and_infer_types() { Dimension::merge(merged_num_directions, merged_num_directions, b_pshape[0]), "Parameter num_directions not matched in LSTMSequence."); + auto check_direction_valid = [](const ov::PartialShape& pshape, size_t index) -> bool { + if (pshape[index].is_static()) + return static_cast(pshape[index].get_length()) == direction::FORWARD || + static_cast(pshape[index].get_length()) == direction::REVERSE || + static_cast(pshape[index].get_length()) == direction::BIDIRECTIONAL; + return true; + }; + + NODE_VALIDATION_CHECK(this, + check_direction_valid(ht_pshape, 1), + "Parameter direction must be Forward or Reverse or Bidirectional."); + + NODE_VALIDATION_CHECK(this, + m_direction == direction::FORWARD || m_direction == direction::REVERSE || + m_direction == direction::BIDIRECTIONAL, + "Parameter direction must be Forward or Reverse or Bidirectional."); + // Validate hidden_size value for W, R, B inputs if (merged_hidden_size.is_static()) { if (w_pshape[1].is_static()) { diff --git a/ngraph/core/src/op/max_pool.cpp b/ngraph/core/src/op/max_pool.cpp index afb78c6fe3bd3c..ed9775c1d0c929 100644 --- a/ngraph/core/src/op/max_pool.cpp +++ b/ngraph/core/src/op/max_pool.cpp @@ -220,8 +220,10 @@ bool evaluate_maxpool(const HostTensorPtr& data, switch (indices->get_element_type()) { case element::Type_t::i32: { switch (data->get_element_type()) { + EVAL_MAX_POOL_8(i8, i32); EVAL_MAX_POOL_8(i32, i32); EVAL_MAX_POOL_8(i64, i32); + EVAL_MAX_POOL_8(u8, i32); EVAL_MAX_POOL_8(u32, i32); EVAL_MAX_POOL_8(u64, i32); EVAL_MAX_POOL_8(f16, i32); @@ -233,8 +235,10 @@ bool evaluate_maxpool(const HostTensorPtr& data, } break; case element::Type_t::i64: { switch (data->get_element_type()) { + EVAL_MAX_POOL_8(i8, i64); EVAL_MAX_POOL_8(i32, i64); EVAL_MAX_POOL_8(i64, i64); + EVAL_MAX_POOL_8(u8, i64); EVAL_MAX_POOL_8(u32, i64); EVAL_MAX_POOL_8(u64, i64); EVAL_MAX_POOL_8(f16, i64); @@ -319,8 +323,10 @@ shared_ptr op::v8::MaxPool::clone_with_new_inputs(const OutputVector& new_ bool op::v8::MaxPool::has_evaluate() const { NGRAPH_OP_SCOPE(v8_MaxPool_has_evaluate); switch (get_input_element_type(0)) { + case ngraph::element::i8: case ngraph::element::i32: case ngraph::element::i64: + case ngraph::element::u8: case ngraph::element::u32: case ngraph::element::u64: case ngraph::element::f16: diff --git a/ngraph/core/src/op/one_hot.cpp b/ngraph/core/src/op/one_hot.cpp index 64f42cfef6feb7..e256070dbddc83 100644 --- a/ngraph/core/src/op/one_hot.cpp +++ b/ngraph/core/src/op/one_hot.cpp @@ -9,6 +9,7 @@ #include "ngraph/op/util/op_types.hpp" #include "ngraph/runtime/reference/one_hot.hpp" #include "ngraph/validation_util.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -22,6 +23,7 @@ op::v1::OneHot::OneHot(const Output& indices, int64_t axis) : Op({indices, depth, on_value, off_value}), m_axis(axis) { + ov::mark_as_precision_sensitive(input(1)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/pad.cpp b/ngraph/core/src/op/pad.cpp index e06e83e17e2fdd..a033f74587e0bb 100644 --- a/ngraph/core/src/op/pad.cpp +++ b/ngraph/core/src/op/pad.cpp @@ -13,6 +13,7 @@ #include "ngraph/op/constant.hpp" #include "ngraph/op/util/op_types.hpp" #include "ngraph/runtime/reference/pad.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -26,6 +27,8 @@ op::v1::Pad::Pad(const Output& arg, PadMode pad_mode) : Op({arg, pads_begin, pads_end, arg_pad_value}), m_pad_mode{pad_mode} { + ov::mark_as_precision_sensitive(input(1)); + ov::mark_as_precision_sensitive(input(2)); constructor_validate_and_infer_types(); } @@ -35,6 +38,8 @@ op::v1::Pad::Pad(const Output& arg, PadMode pad_mode) : Op({arg, pads_begin, pads_end, op::v0::Constant::create(arg.get_element_type(), ov::Shape{}, {0})}), m_pad_mode{pad_mode} { + ov::mark_as_precision_sensitive(input(1)); + ov::mark_as_precision_sensitive(input(2)); constructor_validate_and_infer_types(); } @@ -154,6 +159,18 @@ void op::v1::Pad::validate_and_infer_types() { "of at least 2 at each " "spatial axis."); } + NODE_VALIDATION_CHECK( + this, + m_pad_mode != op::PadMode::REFLECT || (pads_begin_coord[i] < arg_shape[i].get_length() && + pads_end_coord[i] < arg_shape[i].get_length()), + "REFLECT padding mode requires that 'pads_begin[D]' and 'pads_end[D]' " + "must be not greater than 'data_shape[D] - 1'."); + NODE_VALIDATION_CHECK( + this, + m_pad_mode != op::PadMode::SYMMETRIC || (pads_begin_coord[i] <= arg_shape[i].get_length() && + pads_end_coord[i] <= arg_shape[i].get_length()), + "SYMMETRIC padding mode requires that 'pads_begin[D]' and 'pads_end[D]' " + "must be not greater than 'data_shape[D]'."); } } set_output_type(0, get_input_element_type(0), result_dims); diff --git a/ngraph/core/src/op/reshape.cpp b/ngraph/core/src/op/reshape.cpp index e13718a812ac5e..ed2c6e5363ecc4 100644 --- a/ngraph/core/src/op/reshape.cpp +++ b/ngraph/core/src/op/reshape.cpp @@ -11,6 +11,7 @@ #include "ngraph/op/constant.hpp" #include "ngraph/runtime/opt_kernel/reshape.hpp" #include "ngraph/runtime/reference/reshape.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -44,6 +45,7 @@ BWDCMP_RTTI_DEFINITION(op::v1::Reshape); op::v1::Reshape::Reshape(const Output& arg, const Output& shape_pattern, bool zero_flag) : Op({arg, shape_pattern}), m_special_zero(zero_flag) { + ov::mark_as_precision_sensitive(input(1)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/slice.cpp b/ngraph/core/src/op/slice.cpp index 0c4c9de122f79e..0488b1acee2bda 100644 --- a/ngraph/core/src/op/slice.cpp +++ b/ngraph/core/src/op/slice.cpp @@ -10,6 +10,7 @@ #include "ngraph/attribute_visitor.hpp" #include "ngraph/graph_util.hpp" #include "ngraph/op/constant.hpp" +#include "ngraph/runtime/reference/slice.hpp" #include "ngraph/validation_util.hpp" using namespace std; @@ -34,19 +35,6 @@ op::v8::Slice::Slice(const Output& data, namespace { -std::shared_ptr get_default_const_axes(const Output& start) { - const auto start_pshape = start.get_partial_shape(); - // Static case - if (start_pshape.rank().is_static() && start_pshape.rank().get_length() == 1 && start_pshape[0].is_static()) { - size_t axes_length = start_pshape[0].get_length(); - std::vector axes(axes_length); - std::iota(axes.begin(), axes.end(), 0); - return op::v0::Constant::create(element::i64, Shape{axes_length}, axes); - } - // Dynamic case - return nullptr; -} - int64_t get_sliced_dim_size(int64_t start, int64_t stop, int64_t step, int64_t dim_size) { // Normalize index start = start < 0 ? dim_size + start : start; @@ -64,7 +52,9 @@ int64_t get_sliced_dim_size(int64_t start, int64_t stop, int64_t step, int64_t d // Clip max stop index (last element exclusively) elements_in_range = std::max(int64_t(0), std::min(dim_size, stop) - start); } - const int64_t sliced_dim_size = std::ceil(elements_in_range / std::fabs(step)); + const int64_t rest = elements_in_range % std::abs(step); + const int64_t integer_div = elements_in_range / std::abs(step); + const int64_t sliced_dim_size = !rest ? integer_div : integer_div + 1; return sliced_dim_size; } @@ -75,6 +65,19 @@ bool op::v8::Slice::visit_attributes(AttributeVisitor& visitor) { return true; } +std::shared_ptr op::v8::Slice::get_default_const_axes(const Output& start) const { + const auto start_pshape = start.get_partial_shape(); + // Static case + if (start_pshape.rank().is_static() && start_pshape.rank().get_length() == 1 && start_pshape[0].is_static()) { + size_t axes_length = start_pshape[0].get_length(); + std::vector axes(axes_length); + std::iota(axes.begin(), axes.end(), 0); + return op::v0::Constant::create(element::i64, Shape{axes_length}, axes); + } + // Dynamic case + return nullptr; +} + void op::v8::Slice::validate_and_infer_types() { NGRAPH_OP_SCOPE(v8_Slice_validate_and_infer_types); diff --git a/ngraph/core/src/op/space_to_batch.cpp b/ngraph/core/src/op/space_to_batch.cpp index 3a3498d60c40fb..cd11e09bd73f45 100644 --- a/ngraph/core/src/op/space_to_batch.cpp +++ b/ngraph/core/src/op/space_to_batch.cpp @@ -17,6 +17,7 @@ #include "ngraph/runtime/opt_kernel/reshape.hpp" #include "ngraph/runtime/reference/pad.hpp" #include "ngraph/shape.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -28,6 +29,9 @@ ngraph::op::v1::SpaceToBatch::SpaceToBatch(const ngraph::Output& d const ngraph::Output& pads_begin, const ngraph::Output& pads_end) : Op({data, block_shape, pads_begin, pads_end}) { + ov::mark_as_precision_sensitive(input(1)); + ov::mark_as_precision_sensitive(input(2)); + ov::mark_as_precision_sensitive(input(3)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/strided_slice.cpp b/ngraph/core/src/op/strided_slice.cpp index 003f909d9e7bd8..1cb0e93ee20354 100644 --- a/ngraph/core/src/op/strided_slice.cpp +++ b/ngraph/core/src/op/strided_slice.cpp @@ -19,6 +19,7 @@ #include "ngraph/type/element_type_traits.hpp" #include "ngraph/util.hpp" #include "ngraph/validation_util.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -40,6 +41,9 @@ op::v1::StridedSlice::StridedSlice(const Output& data, m_new_axis_mask{new_axis_mask}, m_shrink_axis_mask{shrink_axis_mask}, m_ellipsis_mask{ellipsis_mask} { + ov::mark_as_precision_sensitive(input(1)); + ov::mark_as_precision_sensitive(input(2)); + ov::mark_as_precision_sensitive(input(3)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/tile.cpp b/ngraph/core/src/op/tile.cpp index a77ae182fc02db..1f6d95fd650bb3 100644 --- a/ngraph/core/src/op/tile.cpp +++ b/ngraph/core/src/op/tile.cpp @@ -9,6 +9,7 @@ #include "itt.hpp" #include "ngraph/op/constant.hpp" #include "ngraph/runtime/reference/tile.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -16,6 +17,7 @@ using namespace ngraph; BWDCMP_RTTI_DEFINITION(op::v0::Tile); op::v0::Tile::Tile(const Output& data, const Output& repeats) : Op({data, repeats}) { + ov::mark_as_precision_sensitive(input(1)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/topk.cpp b/ngraph/core/src/op/topk.cpp index 93bc14a17bee8f..ef7b46f7290aaf 100644 --- a/ngraph/core/src/op/topk.cpp +++ b/ngraph/core/src/op/topk.cpp @@ -15,6 +15,7 @@ #include "ngraph/runtime/reference/topk.hpp" #include "ngraph/shape.hpp" #include "ngraph/validation_util.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; using namespace ngraph; @@ -154,6 +155,7 @@ op::v1::TopK::TopK(const Output& data, m_mode{as_enum(mode)}, m_sort{as_enum(sort)}, m_index_element_type{index_element_type} { + ov::mark_as_precision_sensitive(input(1)); constructor_validate_and_infer_types(); } @@ -169,6 +171,7 @@ op::v1::TopK::TopK(const Output& data, m_mode{mode}, m_sort{sort}, m_index_element_type{index_element_type} { + ov::mark_as_precision_sensitive(input(1)); constructor_validate_and_infer_types(); } diff --git a/ngraph/core/src/op/unsqueeze.cpp b/ngraph/core/src/op/unsqueeze.cpp index ffafec5a2b3c9f..4e78f53670e094 100644 --- a/ngraph/core/src/op/unsqueeze.cpp +++ b/ngraph/core/src/op/unsqueeze.cpp @@ -89,8 +89,8 @@ bool evaluate_unsqueeze(const HostTensorPtr& arg0, const HostTensorPtr& arg1, co auto data_shape = arg0->get_shape(); int64_t data_rank = static_cast(data_shape.size()); auto axes_shape = arg1->get_shape(); - NGRAPH_CHECK(axes_shape.size() == 1, "Axes to add must be a vector."); - NGRAPH_CHECK(axes_shape[0] > 0, "Axes cannot be empty."); + NGRAPH_CHECK(axes_shape.size() == 1 || axes_shape.empty(), + "Axes to add must be a scalar or 1D tensor with 1 element"); auto out_shape = data_shape; int64_t out_rank = data_rank + static_cast(shape_size(axes_shape)); diff --git a/ngraph/core/src/op/util/broadcast_base.cpp b/ngraph/core/src/op/util/broadcast_base.cpp index 47d40d21c3c98e..8c094c739e0e87 100644 --- a/ngraph/core/src/op/util/broadcast_base.cpp +++ b/ngraph/core/src/op/util/broadcast_base.cpp @@ -14,6 +14,7 @@ #include "ngraph/op/util/op_types.hpp" #include "ngraph/partial_shape.hpp" #include "ngraph/runtime/reference/broadcast.hpp" +#include "openvino/op/util/precision_sensitive_attribute.hpp" using namespace std; @@ -24,13 +25,17 @@ ov::op::util::BroadcastBase::BroadcastBase(const Output& arg, const Output& axes_mapping, const BroadcastModeSpec& broadcast_mode) : Op({arg, target_shape, axes_mapping}), - m_mode{broadcast_mode} {} + m_mode{broadcast_mode} { + ov::mark_as_precision_sensitive(input(1)); +} ov::op::util::BroadcastBase::BroadcastBase(const Output& arg, const Output& target_shape, const BroadcastModeSpec& broadcast_mode) : Op({arg, target_shape}), - m_mode{broadcast_mode} {} + m_mode{broadcast_mode} { + ov::mark_as_precision_sensitive(input(1)); +} ov::PartialShape ov::op::util::BroadcastBase::get_result_shape_pdpd(const PartialShape& arg0_shape, const PartialShape& target_pshape, diff --git a/ngraph/core/src/op/util/gather_nd_base.cpp b/ngraph/core/src/op/util/gather_nd_base.cpp new file mode 100644 index 00000000000000..96dac95f8ac523 --- /dev/null +++ b/ngraph/core/src/op/util/gather_nd_base.cpp @@ -0,0 +1,114 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ngraph/op/util/gather_nd_base.hpp" + +#include + +#include "ngraph/op/concat.hpp" +#include "ngraph/op/constant.hpp" +#include "ngraph/op/squeeze.hpp" +#include "ngraph/runtime/host_tensor.hpp" +#include "ngraph/shape.hpp" + +using namespace std; + +BWDCMP_RTTI_DEFINITION(ov::op::util::GatherNDBase); + +ov::op::util::GatherNDBase::GatherNDBase(const Output& data, const Output& indices, const size_t batch_dims) + : Op({data, indices}), + m_batch_dims(batch_dims) { + constructor_validate_and_infer_types(); +} + +void ov::op::util::GatherNDBase::validate_inputs_and_infer_shape() { + // check types of input tensors + const auto& data_type = get_input_element_type(0); + const auto& indices_type = get_input_element_type(1); + + NODE_VALIDATION_CHECK(this, + indices_type.is_integral_number(), + "The indices type is expected to be an integer type. Got: ", + indices_type); + + // check ranks of input tensors + const auto& data_pshape = get_input_partial_shape(0); + const auto& indices_pshape = get_input_partial_shape(1); + + if (data_pshape.rank().is_static()) { + NODE_VALIDATION_CHECK(this, data_pshape.rank().get_length() > 0, "Data rank must be at least 1."); + + NODE_VALIDATION_CHECK(this, + data_pshape.rank().get_length() > static_cast(m_batch_dims), + "Number of batch dimensions must not exceed a rank of data."); + } + + if (indices_pshape.rank().is_static()) { + NODE_VALIDATION_CHECK(this, indices_pshape.rank().get_length() > 0, "Indices rank must be at least 1."); + + NODE_VALIDATION_CHECK(this, + indices_pshape.rank().get_length() > static_cast(m_batch_dims), + "Number of batch dimensions must not exceed a rank of indices."); + } + + if (data_pshape.rank().is_static() && indices_pshape.rank().is_static()) { + // check that batch dimensions of data and indices are the same + for (size_t batch_dim = 0; batch_dim < m_batch_dims; batch_dim++) { + if (data_pshape[batch_dim].is_static() && indices_pshape[batch_dim].is_static()) { + NODE_VALIDATION_CHECK(this, + data_pshape[batch_dim].get_length() == indices_pshape[batch_dim].get_length(), + "Batch dimensions of data and indices must be the same."); + } + } + + if (indices_pshape[indices_pshape.rank().get_length() - 1].is_static()) { + NODE_VALIDATION_CHECK( + this, + static_cast(indices_pshape[indices_pshape.rank().get_length() - 1].get_length() + + m_batch_dims) <= data_pshape.rank().get_length(), + "Length of a tuple with indices must not exceed a rank of data tensor " + "excluding " + "batch dimensions."); + } + } + + // set output shape + set_output_size(1); + if (data_pshape.rank().is_static() && indices_pshape.rank().is_static() && + indices_pshape[indices_pshape.rank().get_length() - 1].is_static()) { + auto indices_tuple_length = indices_pshape[indices_pshape.rank().get_length() - 1].get_length(); + int64_t slice_length = data_pshape.rank().get_length() - indices_tuple_length - m_batch_dims; + int64_t output_indices_length = indices_pshape.rank().get_length() - m_batch_dims - 1; + auto output_rank = output_indices_length + slice_length; + size_t delta_output_rank = 0; + delta_output_rank = m_batch_dims; + std::vector output_shape(output_rank + delta_output_rank); + for (size_t dim = 0; dim < m_batch_dims; dim++) { + output_shape[dim] = 1; + if (data_pshape[dim].is_static()) { + output_shape[dim] = data_pshape[dim].get_length(); + } else if (indices_pshape[dim].is_static()) { + output_shape[dim] = indices_pshape[dim].get_length(); + } else { + output_shape[dim] = Dimension::dynamic(); + break; + } + } + for (int64_t dim = 0; dim < output_indices_length; dim++) { + output_shape[dim + delta_output_rank] = indices_pshape[dim + m_batch_dims]; + } + for (int64_t dim = 0; dim < slice_length; dim++) { + output_shape[output_indices_length + dim + delta_output_rank] = + data_pshape[m_batch_dims + indices_tuple_length + dim]; + } + set_output_type(0, data_type, ov::PartialShape(output_shape)); + } else { + set_output_type(0, data_type, ov::PartialShape::dynamic()); + } +} + +bool ov::op::util::GatherNDBase::visit_attributes(AttributeVisitor& visitor) { + visitor.on_attribute("batch_dims", m_batch_dims); + return true; +} diff --git a/ngraph/core/src/op/util/precision_sensitive_attribute.cpp b/ngraph/core/src/op/util/precision_sensitive_attribute.cpp new file mode 100644 index 00000000000000..6591699a341702 --- /dev/null +++ b/ngraph/core/src/op/util/precision_sensitive_attribute.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "openvino/op/util/precision_sensitive_attribute.hpp" + +void ov::mark_as_precision_sensitive(ov::Input node_input) { + auto& rt_info = node_input.get_rt_info(); + rt_info[PrecisionSensitive::get_type_info_static()] = std::make_shared(); +} + +void ov::unmark_as_precision_sensitive(ov::Input node_input) { + auto& rt_info = node_input.get_rt_info(); + rt_info.erase(PrecisionSensitive::get_type_info_static()); +} + +bool ov::is_precision_sensitive(const ov::Input& node_input) { + const auto& rt_info = node_input.get_rt_info(); + return rt_info.count(PrecisionSensitive::get_type_info_static()); +} diff --git a/ngraph/core/src/pass/convert_precision.cpp b/ngraph/core/src/pass/convert_precision.cpp index 41793842b4d8e8..b11ee9fe029f2f 100644 --- a/ngraph/core/src/pass/convert_precision.cpp +++ b/ngraph/core/src/pass/convert_precision.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,7 @@ bool fuse_type_to_nms3(const std::shared_ptr& node, ngraph::elemen bool fuse_type_to_nms4(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); bool fuse_type_to_nms5(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); bool fuse_type_to_topk(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); +bool fuse_type_to_maxpool(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); bool fuse_type_to_nonzero(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); bool fuse_type_to_bucketize(const std::shared_ptr& node, ngraph::element::Type to, size_t idx); bool fuse_type_to_ctc_greedy_decoder_seq_len(const std::shared_ptr& node, @@ -253,6 +255,7 @@ bool ngraph::pass::ConvertPrecision::run_on_function(std::shared_ptr}, @@ -392,6 +395,16 @@ bool fuse_type_to_topk(const std::shared_ptr& node, ngraph::elemen return false; } +bool fuse_type_to_maxpool(const std::shared_ptr& node, ngraph::element::Type to, size_t idx) { + if (auto maxpool = ov::as_type_ptr(node)) { + if (idx == 1 && (to == element::i32 || to == element::i64)) { + maxpool->set_index_element_type(to); + return true; + } + } + return false; +} + bool fuse_type_to_ctc_greedy_decoder_seq_len(const std::shared_ptr& node, ngraph::element::Type to, size_t idx) { diff --git a/ngraph/core/src/pass/serialize.cpp b/ngraph/core/src/pass/serialize.cpp index acacdb26a20796..08becb27c50085 100644 --- a/ngraph/core/src/pass/serialize.cpp +++ b/ngraph/core/src/pass/serialize.cpp @@ -125,21 +125,6 @@ void ngfunction_2_ir(pugi::xml_node& node, int64_t version, bool deterministic); -// Some of the operators were added to wrong opsets. This is a mapping -// that allows such operators to be serialized with proper opsets. -// If new operators are discovered that have the same problem, the mapping -// needs to be updated here. The keys contain op name and version in NodeTypeInfo. -const std::unordered_map special_operator_to_opset_assignments = { - {ngraph::Node::type_info_t("ShuffleChannels", 0), "opset3"}}; - -std::string get_special_opset_for_op(const ngraph::Node::type_info_t& type_info) { - auto found = special_operator_to_opset_assignments.find(type_info); - if (found != end(special_operator_to_opset_assignments)) { - return found->second; - } - return ""; -} - namespace rt_info { const std::vector list_of_names{ "PrimitivesPriority", @@ -287,8 +272,6 @@ class XmlSerializer : public ngraph::AttributeVisitor { const std::vector& result_mapping, pugi::xml_node& port_map, const std::string& portmap_name) { - NGRAPH_CHECK(!parameter_mapping.empty(), "No parameters found in body Function."); - if (!m_xml_node.parent().child(portmap_name.c_str())) { port_map = m_xml_node.parent().insert_child_before(portmap_name.c_str(), m_xml_node.parent().first_child()); } @@ -415,9 +398,8 @@ class XmlSerializer : public ngraph::AttributeVisitor { map_type_from_body(m_xml_node.parent(), "Parameter", m_version, body_name); pugi::xml_node port_map = m_xml_node.parent().child(portmap_name.c_str()); - - NGRAPH_CHECK(!parameter_mapping.empty() || !result_mapping.empty(), - "No parameters or results found in body Function."); + // Bodies can be without parameters(dependig on constants), but can not be without results + NGRAPH_CHECK(!result_mapping.empty(), "No results found in body Function."); // TI, Loop do not have attributtes as regular ops, it is necessary to append "port_map" and // "back_edges" to layer above (m_xml_node.parent()) as in ngfunction_2_ir() layer (here "m_xml_node") // with empty attributes is removed. @@ -574,6 +556,10 @@ const std::vector create_edge_mapping(const std::unordered_map& custom_opsets) { + OPENVINO_ASSERT(n != nullptr); + if (n->get_type_info().version_id != nullptr) { + return n->get_type_info().version_id; + } // Try to find opset name from RT info auto opset_it = n->get_rt_info().find("opset"); if (opset_it != n->get_rt_info().end()) { @@ -585,26 +571,6 @@ std::string get_opset_name(const ngraph::Node* n, const std::map, 8>{ngraph::get_opset1(), - ngraph::get_opset2(), - ngraph::get_opset3(), - ngraph::get_opset4(), - ngraph::get_opset5(), - ngraph::get_opset6(), - ngraph::get_opset7(), - ngraph::get_opset8()}; - - auto special_opset = get_special_opset_for_op(n->get_type_info()); - if (!special_opset.empty()) { - return special_opset; - } - // return the oldest opset name where node type is present - for (size_t idx = 0; idx < opsets.size(); idx++) { - if (opsets[idx].get().contains_op_type(n)) { - return "opset" + std::to_string(idx + 1); - } - } - for (const auto& custom_opset : custom_opsets) { std::string name = custom_opset.first; ngraph::OpSet opset = custom_opset.second; @@ -1137,6 +1103,7 @@ bool pass::Serialize::run_on_function(std::shared_ptr f) { return false; } +OPENVINO_SUPPRESS_DEPRECATED_START pass::Serialize::Serialize(std::ostream& xmlFile, std::ostream& binFile, std::map custom_opsets, @@ -1147,6 +1114,7 @@ pass::Serialize::Serialize(std::ostream& xmlFile, m_binPath{}, m_version{version}, m_custom_opsets{custom_opsets} {} + pass::Serialize::Serialize(std::ostream& xmlFile, std::ostream& binFile, pass::Serialize::Version version) : pass::Serialize::Serialize(xmlFile, binFile, std::map{}, version) {} @@ -1162,7 +1130,9 @@ pass::Serialize::Serialize(const std::string& xmlPath, pass::Serialize::Serialize(const std::string& xmlPath, const std::string& binPath, pass::Serialize::Version version) : pass::Serialize::Serialize(xmlPath, binPath, std::map{}, version) {} +OPENVINO_SUPPRESS_DEPRECATED_END +OPENVINO_SUPPRESS_DEPRECATED_START pass::StreamSerialize::StreamSerialize(std::ostream& stream, std::map&& custom_opsets, const std::function& custom_data_serializer, @@ -1177,6 +1147,12 @@ pass::StreamSerialize::StreamSerialize(std::ostream& stream, } } +pass::StreamSerialize::StreamSerialize(std::ostream& stream, + const std::function& custom_data_serializer, + Serialize::Version version) + : StreamSerialize(stream, {}, custom_data_serializer, version) {} +OPENVINO_SUPPRESS_DEPRECATED_END + bool pass::StreamSerialize::run_on_function(std::shared_ptr f) { /* Format: diff --git a/ngraph/core/src/preprocess/pre_post_process.cpp b/ngraph/core/src/preprocess/pre_post_process.cpp index bccc934df671b1..678a1a31f3877e 100644 --- a/ngraph/core/src/preprocess/pre_post_process.cpp +++ b/ngraph/core/src/preprocess/pre_post_process.cpp @@ -165,20 +165,25 @@ struct InputInfo::InputInfoImpl { return m_has_name; } - void create_tensor_data(const element::Type& type, const Layout& layout) { - auto data = std::unique_ptr(new InputTensorInfo::InputTensorInfoImpl()); - data->set_layout(layout); - data->set_element_type(type); - m_tensor_data = std::move(data); + std::unique_ptr& get_tensor_data() { + return m_tensor_info.m_impl; + } + + std::unique_ptr& get_preprocess() { + return m_preprocess.m_impl; + } + + std::unique_ptr& get_network() { + return m_network_data.m_impl; } bool m_has_index = false; size_t m_index = 0; bool m_has_name = false; std::string m_name; - std::unique_ptr m_tensor_data; - std::unique_ptr m_preprocess; - std::unique_ptr m_network_data; + InputTensorInfo m_tensor_info; + PreProcessSteps m_preprocess; + InputNetworkInfo m_network_data; std::shared_ptr m_resolved_param; }; @@ -196,18 +201,25 @@ struct OutputInfo::OutputInfoImpl { return m_has_name; } - void create_tensor_data() { - m_tensor_data = - std::unique_ptr(new OutputTensorInfo::OutputTensorInfoImpl()); + std::unique_ptr& get_tensor_data() { + return m_tensor_info.m_impl; + } + + std::unique_ptr& get_postprocess() { + return m_postprocess.m_impl; + } + + std::unique_ptr& get_network_data() { + return m_network_info.m_impl; } bool m_has_index = false; size_t m_index = 0; bool m_has_name = false; std::string m_name; - std::unique_ptr m_tensor_data; - std::unique_ptr m_postprocess; - std::unique_ptr m_network_data; + OutputTensorInfo m_tensor_info; + PostProcessSteps m_postprocess; + OutputNetworkInfo m_network_info; }; //-------------- InputInfo ------------------ @@ -220,32 +232,44 @@ InputInfo& InputInfo::operator=(InputInfo&&) noexcept = default; InputInfo::~InputInfo() = default; InputInfo& InputInfo::tensor(InputTensorInfo&& builder) & { - m_impl->m_tensor_data = std::move(builder.m_impl); + m_impl->m_tensor_info = std::move(builder); return *this; } +InputTensorInfo& InputInfo::tensor() { + return m_impl->m_tensor_info; +} + +PreProcessSteps& InputInfo::preprocess() { + return m_impl->m_preprocess; +} + +InputNetworkInfo& InputInfo::network() { + return m_impl->m_network_data; +} + InputInfo&& InputInfo::tensor(InputTensorInfo&& builder) && { - m_impl->m_tensor_data = std::move(builder.m_impl); + m_impl->m_tensor_info = std::move(builder); return std::move(*this); } InputInfo&& InputInfo::preprocess(PreProcessSteps&& builder) && { - m_impl->m_preprocess = std::move(builder.m_impl); + m_impl->m_preprocess = std::move(builder); return std::move(*this); } InputInfo& InputInfo::preprocess(PreProcessSteps&& builder) & { - m_impl->m_preprocess = std::move(builder.m_impl); + m_impl->m_preprocess = std::move(builder); return *this; } InputInfo& InputInfo::network(InputNetworkInfo&& builder) & { - m_impl->m_network_data = std::move(builder.m_impl); + m_impl->m_network_data = std::move(builder); return *this; } InputInfo&& InputInfo::network(InputNetworkInfo&& builder) && { - m_impl->m_network_data = std::move(builder.m_impl); + m_impl->m_network_data = std::move(builder); return std::move(*this); } @@ -260,73 +284,202 @@ OutputInfo::OutputInfo(OutputInfo&&) noexcept = default; OutputInfo& OutputInfo::operator=(OutputInfo&&) noexcept = default; OutputInfo::~OutputInfo() = default; +OutputNetworkInfo& OutputInfo::network() { + return m_impl->m_network_info; +} + +PostProcessSteps& OutputInfo::postprocess() { + return m_impl->m_postprocess; +} + +OutputTensorInfo& OutputInfo::tensor() { + return m_impl->m_tensor_info; +} + +// TODO: remove this in future OutputInfo& OutputInfo::tensor(OutputTensorInfo&& builder) & { - m_impl->m_tensor_data = std::move(builder.m_impl); + m_impl->m_tensor_info = std::move(builder); return *this; } +// TODO: remove this in future OutputInfo&& OutputInfo::tensor(OutputTensorInfo&& builder) && { - m_impl->m_tensor_data = std::move(builder.m_impl); + m_impl->m_tensor_info = std::move(builder); return std::move(*this); } +// TODO: remove this in future OutputInfo&& OutputInfo::postprocess(PostProcessSteps&& builder) && { - m_impl->m_postprocess = std::move(builder.m_impl); + m_impl->m_postprocess = std::move(builder); return std::move(*this); } +// TODO: remove this in future OutputInfo& OutputInfo::postprocess(PostProcessSteps&& builder) & { - m_impl->m_postprocess = std::move(builder.m_impl); + m_impl->m_postprocess = std::move(builder); return *this; } +// TODO: remove this in future OutputInfo& OutputInfo::network(OutputNetworkInfo&& builder) & { - m_impl->m_network_data = std::move(builder.m_impl); + m_impl->m_network_info = std::move(builder); return *this; } +// TODO: remove this in future OutputInfo&& OutputInfo::network(OutputNetworkInfo&& builder) && { - m_impl->m_network_data = std::move(builder.m_impl); + m_impl->m_network_info = std::move(builder); return std::move(*this); } // ------------------------ PrePostProcessor -------------------- struct PrePostProcessor::PrePostProcessorImpl { public: - std::list> in_contexts; - std::list> out_contexts; + PrePostProcessorImpl() = default; + explicit PrePostProcessorImpl(const std::shared_ptr& f) : m_function(f) { + OPENVINO_ASSERT(f, "Function can't be nullptr for PrePostProcessor"); + m_inputs.reserve(m_function->inputs().size()); + for (size_t i = 0; i < m_function->inputs().size(); i++) { + m_inputs.emplace_back(i); + } + + m_outputs.reserve(m_function->outputs().size()); + for (size_t i = 0; i < m_function->outputs().size(); i++) { + m_outputs.emplace_back(i); + } + } + size_t find_input_index(const std::string& tensor_name) { + size_t index; + for (index = 0; index < m_function->inputs().size(); index++) { + if (m_function->input(index).get_names().count(tensor_name)) { + break; + } + } + OPENVINO_ASSERT(index < m_inputs.size(), "Function doesn't have input with name ", tensor_name); + return index; + } + size_t find_output_index(const std::string& tensor_name) { + size_t index; + for (index = 0; index < m_function->outputs().size(); index++) { + if (m_function->output(index).get_names().count(tensor_name)) { + break; + } + } + OPENVINO_ASSERT(index < m_outputs.size(), "Function doesn't have output with name ", tensor_name); + return index; + } + + // TODO: this is created for compatibility, consider to remove + void add_input_info(InputInfo&& builder) { + if (builder.m_impl->m_has_index) { + OPENVINO_ASSERT(builder.m_impl->m_index < m_inputs.size(), "Index is out of range"); + m_inputs[builder.m_impl->m_index] = std::move(builder); + } else if (builder.m_impl->m_has_name) { + size_t index = find_input_index(builder.m_impl->m_name); + m_inputs[index] = std::move(builder); + } else { + OPENVINO_ASSERT(1 == m_inputs.size(), "Function shall have only one input"); + m_inputs[0] = std::move(builder); + } + } + + // TODO: this is created for compatibility, consider to remove + void add_output_info(OutputInfo&& builder) { + if (builder.m_impl->m_has_index) { + OPENVINO_ASSERT(builder.m_impl->m_index < m_inputs.size(), "Output index is out of range"); + m_outputs[builder.m_impl->m_index] = std::move(builder); + } else if (builder.m_impl->m_has_name) { + size_t index = find_output_index(builder.m_impl->m_name); + m_outputs[index] = std::move(builder); + } else { + OPENVINO_ASSERT(1 == m_inputs.size(), "Function shall have only one output"); + m_outputs[0] = std::move(builder); + } + } + std::vector m_inputs; + std::vector m_outputs; + std::shared_ptr m_function = nullptr; }; -PrePostProcessor::PrePostProcessor() : m_impl(std::unique_ptr(new PrePostProcessorImpl())) {} +PrePostProcessor::PrePostProcessor(const std::shared_ptr& function) + : m_impl(std::unique_ptr(new PrePostProcessorImpl(function))) {} PrePostProcessor::PrePostProcessor(PrePostProcessor&&) noexcept = default; PrePostProcessor& PrePostProcessor::operator=(PrePostProcessor&&) noexcept = default; PrePostProcessor::~PrePostProcessor() = default; +InputInfo& PrePostProcessor::input() { + OPENVINO_ASSERT(m_impl->m_inputs.size() == 1, + "PrePostProcessor::input() - function must have exactly one input, got ", + m_impl->m_inputs.size()); + return m_impl->m_inputs.front(); +} + +InputInfo& PrePostProcessor::input(size_t input_index) { + OPENVINO_ASSERT(m_impl->m_inputs.size() > input_index, + "PrePostProcessor::input(size_t) - function doesn't have input with index ", + input_index, + ". Total number of inputs is ", + m_impl->m_inputs.size()); + return m_impl->m_inputs[input_index]; +} + +InputInfo& PrePostProcessor::input(const std::string& tensor_name) { + size_t index = m_impl->find_input_index(tensor_name); + return m_impl->m_inputs[index]; +} + +OutputInfo& PrePostProcessor::output() { + OPENVINO_ASSERT(m_impl->m_outputs.size() == 1, + "PrePostProcessor::output() - function must have exactly one output, got ", + m_impl->m_outputs.size()); + return m_impl->m_outputs.front(); +} + +OutputInfo& PrePostProcessor::output(size_t output_index) { + OPENVINO_ASSERT(m_impl->m_outputs.size() > output_index, + "PrePostProcessor::output(size_t) - function doesn't have input with index ", + output_index, + ". Total number of inputs is ", + m_impl->m_inputs.size()); + return m_impl->m_outputs[output_index]; +} + +OutputInfo& PrePostProcessor::output(const std::string& tensor_name) { + size_t index = m_impl->find_output_index(tensor_name); + return m_impl->m_outputs[index]; +} + +// TODO: consider to remove PrePostProcessor& PrePostProcessor::input(InputInfo&& builder) & { - m_impl->in_contexts.push_back(std::move(builder.m_impl)); + m_impl->add_input_info(std::move(builder)); return *this; } +// TODO: consider to remove PrePostProcessor&& PrePostProcessor::input(InputInfo&& builder) && { - m_impl->in_contexts.push_back(std::move(builder.m_impl)); + m_impl->add_input_info(std::move(builder)); return std::move(*this); } +// TODO: consider remove PrePostProcessor& PrePostProcessor::output(OutputInfo&& builder) & { - m_impl->out_contexts.push_back(std::move(builder.m_impl)); + m_impl->add_output_info(std::move(builder)); return *this; } +// TODO: consider remove PrePostProcessor&& PrePostProcessor::output(OutputInfo&& builder) && { - m_impl->out_contexts.push_back(std::move(builder.m_impl)); + m_impl->add_output_info(std::move(builder)); return std::move(*this); } -std::shared_ptr PrePostProcessor::build(const std::shared_ptr& function) { +std::shared_ptr PrePostProcessor::build() { + auto function = m_impl->m_function; FunctionGuard guard(function); std::tuple, bool> existing_names{std::unordered_set{}, false}; bool tensor_data_updated = false; - for (const auto& input : m_impl->in_contexts) { + for (const auto& input_info : m_impl->m_inputs) { + auto& input = input_info.m_impl; std::shared_ptr param; Output node; OPENVINO_ASSERT(input, "Internal error: Invalid preprocessing input, please report a problem"); @@ -339,8 +492,8 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptr(node.get_node_shared_ptr()); // Set parameter layout from 'network' information - if (input->m_network_data && input->m_network_data->is_layout_set() && param->get_layout().empty()) { - param->set_layout(input->m_network_data->get_layout()); + if (input->get_network()->is_layout_set() && param->get_layout().empty()) { + param->set_layout(input->get_network()->get_layout()); } input->m_resolved_param = param; } @@ -348,31 +501,29 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptr>(function->get_parameters().begin(), function->get_parameters().end()); - for (const auto& input : m_impl->in_contexts) { + for (const auto& input_info : m_impl->m_inputs) { + const auto& input = input_info.m_impl; auto param = input->m_resolved_param; auto consumers = param->output(0).get_target_inputs(); - if (!input->m_tensor_data) { - input->create_tensor_data(param->get_element_type(), param->get_layout()); - } - if (!input->m_tensor_data->is_element_type_set()) { - input->m_tensor_data->set_element_type(param->get_element_type()); + if (!input->get_tensor_data()->is_element_type_set()) { + input->get_tensor_data()->set_element_type(param->get_element_type()); } - auto color_info = ColorFormatInfo::get(input->m_tensor_data->get_color_format()); - if (!input->m_tensor_data->is_layout_set()) { + auto color_info = ColorFormatInfo::get(input->get_tensor_data()->get_color_format()); + if (!input->get_tensor_data()->is_layout_set()) { if (!color_info->default_layout().empty()) { - input->m_tensor_data->set_layout(color_info->default_layout()); + input->get_tensor_data()->set_layout(color_info->default_layout()); } else if (!param->get_layout().empty()) { - input->m_tensor_data->set_layout(param->get_layout()); + input->get_tensor_data()->set_layout(param->get_layout()); } } auto net_shape = param->get_partial_shape(); auto new_param_shape = net_shape; - if (input->m_tensor_data->is_layout_set() && !param->get_layout().empty() && - param->get_layout() != input->m_tensor_data->get_layout()) { + if (input->get_tensor_data()->is_layout_set() && !param->get_layout().empty() && + param->get_layout() != input->get_tensor_data()->get_layout()) { // Find transpose between network and tensor layouts and update tensor shape auto net_to_tensor = - layout::find_permutation(param->get_layout(), net_shape.rank(), input->m_tensor_data->get_layout()); + layout::find_permutation(param->get_layout(), net_shape.rank(), input->get_tensor_data()->get_layout()); if (!net_to_tensor.empty()) { std::vector dims(new_param_shape.size()); std::transform(net_to_tensor.begin(), net_to_tensor.end(), dims.begin(), [&](int64_t v) { @@ -380,20 +531,20 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptrm_preprocess) { - new_param_shape = input->m_preprocess->calculate_param_shape(new_param_shape); + } else { + new_param_shape = input->get_preprocess()->calculate_param_shape(new_param_shape); } - if (input->m_tensor_data->is_spatial_shape_set()) { - auto height_idx = get_and_check_height_idx(input->m_tensor_data->get_layout(), new_param_shape); - auto width_idx = get_and_check_width_idx(input->m_tensor_data->get_layout(), new_param_shape); - if (input->m_tensor_data->is_spatial_shape_dynamic()) { + if (input->get_tensor_data()->is_spatial_shape_set()) { + auto height_idx = get_and_check_height_idx(input->get_tensor_data()->get_layout(), new_param_shape); + auto width_idx = get_and_check_width_idx(input->get_tensor_data()->get_layout(), new_param_shape); + if (input->get_tensor_data()->is_spatial_shape_dynamic()) { // Use dynamic spatial dimensions new_param_shape[height_idx] = Dimension::dynamic(); new_param_shape[width_idx] = Dimension::dynamic(); } else { // Use static spatial dimensions - new_param_shape[height_idx] = input->m_tensor_data->get_spatial_height(); - new_param_shape[width_idx] = input->m_tensor_data->get_spatial_width(); + new_param_shape[height_idx] = input->get_tensor_data()->get_spatial_height(); + new_param_shape[width_idx] = input->get_tensor_data()->get_spatial_width(); } } @@ -404,11 +555,11 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptrplanes_count(); plane++) { auto plane_shape = color_info->shape(plane, new_param_shape); auto plane_param = - std::make_shared(input->m_tensor_data->get_element_type(), plane_shape); - if (plane < input->m_tensor_data->planes_sub_names().size()) { + std::make_shared(input->get_tensor_data()->get_element_type(), plane_shape); + if (plane < input->get_tensor_data()->planes_sub_names().size()) { std::unordered_set plane_tensor_names; std::string sub_name; - sub_name = std::string("/") + input->m_tensor_data->planes_sub_names()[plane]; + sub_name = std::string("/") + input->get_tensor_data()->planes_sub_names()[plane]; if (!std::get<1>(existing_names)) { existing_names = std::make_tuple(get_function_tensor_names(function), true); } @@ -428,26 +579,24 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptrget_default_output().get_tensor().get_names()); plane_param->set_friendly_name(param->get_friendly_name()); } - if (!input->m_tensor_data->get_layout().empty()) { - plane_param->set_layout(input->m_tensor_data->get_layout()); + if (!input->get_tensor_data()->get_layout().empty()) { + plane_param->set_layout(input->get_tensor_data()->get_layout()); } new_params.push_back(plane_param); nodes.emplace_back(plane_param); } - PreprocessingContext context(input->m_tensor_data->get_layout()); - context.color_format() = input->m_tensor_data->get_color_format(); + PreprocessingContext context(input->get_tensor_data()->get_layout()); + context.color_format() = input->get_tensor_data()->get_color_format(); context.target_layout() = param->get_layout(); context.network_shape() = param->get_partial_shape(); context.target_element_type() = param->get_element_type(); // 2. Apply preprocessing - if (input->m_preprocess) { - for (const auto& action : input->m_preprocess->actions()) { - auto action_result = action(nodes, function, context); - nodes = std::get<0>(action_result); - tensor_data_updated |= std::get<1>(action_result); - } + for (const auto& action : input->get_preprocess()->actions()) { + auto action_result = action(nodes, function, context); + nodes = std::get<0>(action_result); + tensor_data_updated |= std::get<1>(action_result); } OPENVINO_ASSERT(nodes.size() == 1, @@ -511,7 +660,8 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptrout_contexts) { + for (const auto& output_info : m_impl->m_outputs) { + const auto& output = output_info.m_impl; std::shared_ptr result; Output node; OPENVINO_ASSERT(output, "Internal error: Invalid postprocessing output, please report a problem"); @@ -526,33 +676,30 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptr(node.get_node_shared_ptr()); // Set result layout from 'network' information - if (output->m_network_data && output->m_network_data->is_layout_set() && result->get_layout().empty()) { - result->set_layout(output->m_network_data->get_layout()); + if (output->get_network_data()->is_layout_set() && result->get_layout().empty()) { + result->set_layout(output->get_network_data()->get_layout()); } auto parent = result->get_input_source_output(0); - if (!output->m_tensor_data) { - output->create_tensor_data(); - } PostprocessingContext context(result->get_layout()); - if (output->m_tensor_data->is_layout_set()) { - context.target_layout() = output->m_tensor_data->get_layout(); + if (output->get_tensor_data()->is_layout_set()) { + context.target_layout() = output->get_tensor_data()->get_layout(); } - if (output->m_tensor_data->is_element_type_set()) { - context.target_element_type() = output->m_tensor_data->get_element_type(); + if (output->get_tensor_data()->is_element_type_set()) { + context.target_element_type() = output->get_tensor_data()->get_element_type(); } // Apply post-processing node = result->get_input_source_output(0); - if (output->m_postprocess) { - for (const auto& action : output->m_postprocess->actions()) { - auto action_result = action({node}, context); - node = std::get<0>(action_result); - } + bool post_processing_applied = false; + for (const auto& action : output->get_postprocess()->actions()) { + auto action_result = action({node}, context); + node = std::get<0>(action_result); + post_processing_applied = true; } // Implicit: Convert element type + layout to user's tensor implicitly PostStepsList implicit_steps; - if (node.get_element_type() != output->m_tensor_data->get_element_type() && - output->m_tensor_data->is_element_type_set() && node.get_element_type() != element::dynamic) { - implicit_steps.add_convert_impl(output->m_tensor_data->get_element_type()); + if (node.get_element_type() != output->get_tensor_data()->get_element_type() && + output->get_tensor_data()->is_element_type_set() && node.get_element_type() != element::dynamic) { + implicit_steps.add_convert_impl(output->get_tensor_data()->get_element_type()); } if (!context.target_layout().empty() && context.target_layout() != context.layout()) { @@ -561,10 +708,18 @@ std::shared_ptr PrePostProcessor::build(const std::shared_ptr(action_result); + post_processing_applied = true; } node.get_node_shared_ptr()->set_friendly_name( result->get_input_source_output(0).get_node_shared_ptr()->get_friendly_name()); + // Reset friendly name of input node to avoid names collision + // when there is at a new node inserted by post-processing steps + // If no new nodes are inserted by post-processing, then we need to preserve friendly name of input + // as it's required for old API correct work + if (post_processing_applied) + result->get_input_source_output(0).get_node_shared_ptr()->set_friendly_name(""); + // Create result auto new_result = std::make_shared(node); new_result->set_friendly_name(result->get_friendly_name()); diff --git a/ngraph/core/src/runtime/host_tensor.cpp b/ngraph/core/src/runtime/host_tensor.cpp index 7c146736ea64c9..e7f4938b0b63b6 100644 --- a/ngraph/core/src/runtime/host_tensor.cpp +++ b/ngraph/core/src/runtime/host_tensor.cpp @@ -130,9 +130,11 @@ bool runtime::HostTensor::get_is_allocated() const { } void runtime::HostTensor::set_element_type(const element::Type& element_type) { + OPENVINO_SUPPRESS_DEPRECATED_START NGRAPH_CHECK(get_element_type().is_dynamic() || get_element_type() == element_type, "Can not change a static element type"); m_descriptor->set_element_type(element_type); + OPENVINO_SUPPRESS_DEPRECATED_END } void runtime::HostTensor::set_shape(const Shape& shape) { @@ -141,7 +143,9 @@ void runtime::HostTensor::set_shape(const Shape& shape) { shape, " must be compatible with the partial shape: ", get_partial_shape()); + OPENVINO_SUPPRESS_DEPRECATED_START m_descriptor->set_partial_shape(shape); + OPENVINO_SUPPRESS_DEPRECATED_END } void runtime::HostTensor::set_unary(const HostTensorPtr& arg) { diff --git a/ngraph/core/src/type.cpp b/ngraph/core/src/type.cpp index 9efa977ccbe71d..876fa849634fc5 100644 --- a/ngraph/core/src/type.cpp +++ b/ngraph/core/src/type.cpp @@ -4,20 +4,47 @@ #include "ngraph/type.hpp" -#include "ngraph/util.hpp" +#include "openvino/util/common_util.hpp" namespace std { size_t std::hash::operator()(const ngraph::DiscreteTypeInfo& k) const { - NGRAPH_SUPPRESS_DEPRECATED_START - size_t name_hash = hash()(string(k.name)); - size_t version_hash = hash()(k.version); - // don't use parent for hash calculation, it is not a part of type (yet) - return ngraph::hash_combine(vector{name_hash, version_hash}); - NGRAPH_SUPPRESS_DEPRECATED_END + return k.hash(); } } // namespace std namespace ov { + +size_t DiscreteTypeInfo::hash() const { + if (hash_value != 0) + return hash_value; + size_t name_hash = name ? std::hash()(std::string(name)) : 0; + size_t version_hash = std::hash()(version); + size_t version_id_hash = version_id ? std::hash()(std::string(version_id)) : 0; + + return ov::util::hash_combine(std::vector{name_hash, version_hash, version_id_hash}); +} + +size_t DiscreteTypeInfo::hash() { + if (hash_value == 0) + hash_value = static_cast(this)->hash(); + return hash_value; +} + +bool DiscreteTypeInfo::is_castable(const DiscreteTypeInfo& target_type) const { + return *this == target_type || (parent && parent->is_castable(target_type)); +} + +std::string DiscreteTypeInfo::get_version() const { + if (version_id) { + return std::string(version_id); + } + return std::to_string(version); +} + +DiscreteTypeInfo::operator std::string() const { + return std::string(name) + "_" + get_version(); +} + std::ostream& operator<<(std::ostream& s, const DiscreteTypeInfo& info) { std::string version_id = info.version_id ? info.version_id : "(empty)"; s << "DiscreteTypeInfo{name: " << info.name << ", version_id: " << version_id << ", old_version: " << info.version @@ -33,22 +60,26 @@ std::ostream& operator<<(std::ostream& s, const DiscreteTypeInfo& info) { // parent is commented to fix type relaxed operations bool DiscreteTypeInfo::operator<(const DiscreteTypeInfo& b) const { - if (version_id == nullptr || b.version_id == nullptr) - return version < b.version || - (version == b.version && strcmp(name, b.name) < 0); // || - // (version == b.version && strcmp(name, b.name) == - // 0 && parent && b.parent && *parent < *b.parent); - else - return strcmp(version_id, b.version_id) < 0 || - (strcmp(version_id, b.version_id) == 0 && strcmp(name, b.name) < 0); // || - // (strcmp(version_id, b.version_id) == 0 && strcmp(name, b.name) == 0 && parent && b.parent && - // *parent < *b.parent); + if (version < b.version) + return true; + if (version == b.version && name != nullptr && b.name != nullptr) { + int cmp_status = strcmp(name, b.name); + if (cmp_status < 0) + return true; + if (cmp_status == 0) { + std::string v_id(version_id == nullptr ? "" : version_id); + std::string bv_id(b.version_id == nullptr ? "" : b.version_id); + if (v_id < bv_id) + return true; + } + } + + return false; } bool DiscreteTypeInfo::operator==(const DiscreteTypeInfo& b) const { - if (version_id == nullptr || b.version_id == nullptr) - return version == b.version && strcmp(name, b.name) == 0; // && parent == b.parent; - else - return strcmp(version_id, b.version_id) == 0 && strcmp(name, b.name) == 0; // && parent == b.parent; + if (hash_value != 0 && b.hash_value != 0) + return hash() == b.hash(); + return version == b.version && strcmp(name, b.name) == 0; } bool DiscreteTypeInfo::operator<=(const DiscreteTypeInfo& b) const { return *this == b || *this < b; diff --git a/ngraph/core/src/util.cpp b/ngraph/core/src/util.cpp index 563c63bf7942fe..2c8b59cc5b3076 100644 --- a/ngraph/core/src/util.cpp +++ b/ngraph/core/src/util.cpp @@ -78,11 +78,7 @@ vector ngraph::split(const string& src, char delimiter, bool do_trim) { } size_t ngraph::hash_combine(const std::vector& list) { - size_t seed = 0; - for (size_t v : list) { - seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2); - } - return seed; + return ov::util::hash_combine(list); } void* ngraph::ngraph_malloc(size_t size) { diff --git a/ngraph/core/src/validation_util.cpp b/ngraph/core/src/validation_util.cpp index 10a1844246573a..244be50b167dd6 100644 --- a/ngraph/core/src/validation_util.cpp +++ b/ngraph/core/src/validation_util.cpp @@ -1371,6 +1371,37 @@ shared_ptr ngraph::get_constant_min_of_type(element::Type_t t) { } } +std::shared_ptr ngraph::get_constant_lowest_of_type(element::Type_t t) { +#define NGRAPH_TYPE_TO_LOWEST_CONST(t) \ + case t: \ + return op::Constant::create(t, \ + {}, \ + {std::numeric_limits::value_type>::lowest()}); \ + break + + switch (t) { + NGRAPH_TYPE_TO_LOWEST_CONST(element::boolean); + NGRAPH_TYPE_TO_LOWEST_CONST(element::bf16); + NGRAPH_TYPE_TO_LOWEST_CONST(element::f16); + NGRAPH_TYPE_TO_LOWEST_CONST(element::f32); + NGRAPH_TYPE_TO_LOWEST_CONST(element::f64); + NGRAPH_TYPE_TO_LOWEST_CONST(element::i8); + NGRAPH_TYPE_TO_LOWEST_CONST(element::i16); + NGRAPH_TYPE_TO_LOWEST_CONST(element::i32); + NGRAPH_TYPE_TO_LOWEST_CONST(element::i64); + NGRAPH_TYPE_TO_LOWEST_CONST(element::u1); + NGRAPH_TYPE_TO_LOWEST_CONST(element::u8); + NGRAPH_TYPE_TO_LOWEST_CONST(element::u16); + NGRAPH_TYPE_TO_LOWEST_CONST(element::u32); + NGRAPH_TYPE_TO_LOWEST_CONST(element::u64); + + case element::undefined: + case element::dynamic: + default: + return nullptr; + } +} + namespace { HostTensorPtr equality_mask(const HostTensorPtr& tensor, const shared_ptr& constant) { diff --git a/ngraph/frontend/frontend_manager/CMakeLists.txt b/ngraph/frontend/frontend_manager/CMakeLists.txt index 8ac00ebef8761a..cadaefceb59a74 100644 --- a/ngraph/frontend/frontend_manager/CMakeLists.txt +++ b/ngraph/frontend/frontend_manager/CMakeLists.txt @@ -22,16 +22,7 @@ source_group("src" FILES ${LIBRARY_SRC}) source_group("include" FILES ${LIBRARY_HEADERS}) source_group("public include" FILES ${LIBRARY_PUBLIC_HEADERS}) -# Static library - -add_library(${TARGET_NAME}_static STATIC ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) -add_library(${TARGET_NAME}::static ALIAS ${TARGET_NAME}_static) -target_link_libraries(${TARGET_NAME}_static PRIVATE ${CMAKE_DL_LIBS} openvino::util PUBLIC ngraph) -target_include_directories(${TARGET_NAME}_static PUBLIC ${FRONTEND_INCLUDE_DIR}) -target_include_directories(${TARGET_NAME}_static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) -target_compile_definitions(${TARGET_NAME}_static PUBLIC USE_STATIC_FRONTEND_MANAGER) - -# Shared library - need to recompile object files to export necessary symbols +# create library add_library(${TARGET_NAME} ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) add_library(ngraph::${TARGET_NAME} ALIAS ${TARGET_NAME}) @@ -55,6 +46,21 @@ if(COMMAND ie_add_vs_version_file) FILEDESCRIPTION "Manager of OpenVINO nGraph Frontends") endif() +# create static library if needed + +if(BUILD_SHARED_LIBS) + add_library(${TARGET_NAME}_static STATIC ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS}) + add_library(${TARGET_NAME}::static ALIAS ${TARGET_NAME}_static) + target_link_libraries(${TARGET_NAME}_static PRIVATE ${CMAKE_DL_LIBS} openvino::util PUBLIC ngraph) + target_include_directories(${TARGET_NAME}_static PUBLIC + $) + target_include_directories(${TARGET_NAME}_static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) + target_compile_definitions(${TARGET_NAME}_static PUBLIC USE_STATIC_FRONTEND_MANAGER) + ov_install_static_lib(${TARGET_NAME}_static ngraph) +else() + add_library(${TARGET_NAME}::static ALIAS ${TARGET_NAME}) +endif() + # Installation rules for shared version only set_target_properties(${TARGET_NAME} PROPERTIES EXPORT_NAME frontend::manager) diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp index a58bf9de640ef3..583d8eb35916f9 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend.hpp @@ -10,12 +10,12 @@ #include "frontend_manager_defs.hpp" #include "input_model.hpp" -#include "ngraph/function.hpp" -#include "ngraph/variant.hpp" #include "openvino/core/extension.hpp" +#include "openvino/core/function.hpp" #include "openvino/core/op_extension.hpp" +#include "openvino/core/variant.hpp" -namespace ngraph { +namespace ov { namespace frontend { /// \brief An interface for identifying a frontend for a particular framework. /// Provides an ability to load and convert of input model @@ -59,11 +59,11 @@ class FRONTEND_API FrontEnd { /// possible /// \param model Input model /// \return fully converted nGraph function - virtual std::shared_ptr convert(InputModel::Ptr model) const; + virtual std::shared_ptr convert(InputModel::Ptr model) const; /// \brief Completely convert the remaining, not converted part of a function. /// \param partiallyConverted partially converted nGraph function - virtual void convert(std::shared_ptr partially_converted) const; + virtual void convert(std::shared_ptr partially_converted) const; /// \brief Convert only those parts of the model that can be converted leaving others /// as-is. Converted parts are not normalized by additional transformations; normalize @@ -71,18 +71,18 @@ class FRONTEND_API FrontEnd { /// conversion process. /// \param model Input model /// \return partially converted nGraph function - virtual std::shared_ptr convert_partially(InputModel::Ptr model) const; + virtual std::shared_ptr convert_partially(InputModel::Ptr model) const; /// \brief Convert operations with one-to-one mapping with decoding nodes. /// Each decoding node is an nGraph node representing a single FW operation node with /// all attributes represented in FW-independent way. /// \param model Input model /// \return nGraph function after decoding - virtual std::shared_ptr decode(InputModel::Ptr model) const; + virtual std::shared_ptr decode(InputModel::Ptr model) const; /// \brief Runs normalization passes on function that was loaded with partial conversion /// \param function partially converted nGraph function - virtual void normalize(std::shared_ptr function) const; + virtual void normalize(std::shared_ptr function) const; /// \brief Gets name of this FrontEnd. Can be used by clients /// if frontend is selected automatically by FrontEndManager::load_by_model @@ -107,7 +107,7 @@ class FRONTEND_API FrontEnd { #endif /// @brief Registers extension - /// @param extension Extension class which is inherited from ov::BaseExtension class + /// @param extension Extension class which is inherited from ov::BaseOpExtension class template ::value, bool>::type = true> void add_extension(const T& extension) { std::shared_ptr ext = std::make_shared(extension); @@ -136,4 +136,4 @@ inline bool FrontEnd::supported(const std::vector>& var } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_exceptions.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_exceptions.hpp index f725b4244f8c44..f95c499cb4dc68 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_exceptions.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_exceptions.hpp @@ -8,42 +8,42 @@ #include #include "frontend_manager_defs.hpp" -#include "ngraph/check.hpp" +#include "openvino/core/except.hpp" -namespace ngraph { +namespace ov { namespace frontend { -class FRONTEND_API GeneralFailure : public CheckFailure { +class FRONTEND_API GeneralFailure : public AssertFailure { public: GeneralFailure(const CheckLocInfo& check_loc_info, const std::string& context, const std::string& explanation) - : CheckFailure(check_loc_info, "FrontEnd API failed with GeneralFailure: " + context, explanation) {} + : AssertFailure(check_loc_info, "FrontEnd API failed with GeneralFailure: " + context, explanation) {} }; -class FRONTEND_API InitializationFailure : public CheckFailure { +class FRONTEND_API InitializationFailure : public AssertFailure { public: InitializationFailure(const CheckLocInfo& check_loc_info, const std::string& context, const std::string& explanation) - : CheckFailure(check_loc_info, "FrontEnd API failed with InitializationFailure: " + context, explanation) {} + : AssertFailure(check_loc_info, "FrontEnd API failed with InitializationFailure: " + context, explanation) {} }; -class FRONTEND_API OpValidationFailure : public CheckFailure { +class FRONTEND_API OpValidationFailure : public AssertFailure { public: OpValidationFailure(const CheckLocInfo& check_loc_info, const std::string& context, const std::string& explanation) - : CheckFailure(check_loc_info, "FrontEnd API failed with OpValidationFailure: " + context, explanation) {} + : AssertFailure(check_loc_info, "FrontEnd API failed with OpValidationFailure: " + context, explanation) {} }; -class FRONTEND_API OpConversionFailure : public CheckFailure { +class FRONTEND_API OpConversionFailure : public AssertFailure { public: OpConversionFailure(const CheckLocInfo& check_loc_info, const std::string& context, const std::string& explanation) - : CheckFailure(check_loc_info, "FrontEnd API failed with OpConversionFailure: " + context, explanation) {} + : AssertFailure(check_loc_info, "FrontEnd API failed with OpConversionFailure: " + context, explanation) {} }; -class FRONTEND_API NotImplementedFailure : public CheckFailure { +class FRONTEND_API NotImplementedFailure : public AssertFailure { public: NotImplementedFailure(const CheckLocInfo& check_loc_info, const std::string& context, const std::string& explanation) - : CheckFailure(check_loc_info, "FrontEnd API failed with NotImplementedFailure: " + context, explanation) {} + : AssertFailure(check_loc_info, "FrontEnd API failed with NotImplementedFailure: " + context, explanation) {} }; /// \brief Macro to check whether a boolean condition holds. @@ -51,39 +51,39 @@ class FRONTEND_API NotImplementedFailure : public CheckFailure { /// \param ... Additional error message info to be added to the error message via the `<<` /// stream-insertion operator. Note that the expressions here will be evaluated lazily, /// i.e., only if the `cond` evalutes to `false`. -/// \throws ::ngraph::frontend::GeneralFailure if `cond` is false. -#define FRONT_END_GENERAL_CHECK(...) NGRAPH_CHECK_HELPER(::ngraph::frontend::GeneralFailure, "", __VA_ARGS__) +/// \throws ::ov::frontend::GeneralFailure if `cond` is false. +#define FRONT_END_GENERAL_CHECK(...) OPENVINO_ASSERT_HELPER(::ov::frontend::GeneralFailure, "", __VA_ARGS__) /// \brief Macro to check whether a boolean condition holds. /// \param cond Condition to check /// \param ... Additional error message info to be added to the error message via the `<<` /// stream-insertion operator. Note that the expressions here will be evaluated lazily, /// i.e., only if the `cond` evalutes to `false`. -/// \throws ::ngraph::frontend::InitializationFailure if `cond` is false. +/// \throws ::ov::frontend::InitializationFailure if `cond` is false. #define FRONT_END_INITIALIZATION_CHECK(...) \ - NGRAPH_CHECK_HELPER(::ngraph::frontend::InitializationFailure, "", __VA_ARGS__) + OPENVINO_ASSERT_HELPER(::ov::frontend::InitializationFailure, "", __VA_ARGS__) /// \brief Macro to check whether a boolean condition holds. /// \param cond Condition to check /// \param ... Additional error message info to be added to the error message via the `<<` /// stream-insertion operator. Note that the expressions here will be evaluated lazily, /// i.e., only if the `cond` evalutes to `false`. -/// \throws ::ngraph::frontend::OpConversionFailure if `cond` is false. -#define FRONT_END_OP_CONVERSION_CHECK(...) NGRAPH_CHECK_HELPER(::ngraph::frontend::OpConversionFailure, "", __VA_ARGS__) +/// \throws ::ov::frontend::OpConversionFailure if `cond` is false. +#define FRONT_END_OP_CONVERSION_CHECK(...) OPENVINO_ASSERT_HELPER(::ov::frontend::OpConversionFailure, "", __VA_ARGS__) /// \brief Assert macro. /// \param NAME Name of the function that is not implemented -/// \throws ::ngraph::frontend::NotImplementedFailure -#define FRONT_END_NOT_IMPLEMENTED(NAME) \ - NGRAPH_CHECK_HELPER(::ngraph::frontend::NotImplementedFailure, \ - "", \ - false, \ - #NAME " is not implemented for this FrontEnd class") +/// \throws ::ov::frontend::NotImplementedFailure +#define FRONT_END_NOT_IMPLEMENTED(NAME) \ + OPENVINO_ASSERT_HELPER(::ov::frontend::NotImplementedFailure, \ + "", \ + false, \ + #NAME " is not implemented for this FrontEnd class") /// \brief Assert macro. /// \param MSG Error message -/// \throws ::ngraph::frontend::GeneralFailure +/// \throws ::ov::frontend::GeneralFailure #define FRONT_END_THROW(MSG) FRONT_END_GENERAL_CHECK(false, MSG) } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp index 607636e9c344d6..1414aedf19fc17 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager.hpp @@ -10,10 +10,10 @@ #include "frontend.hpp" #include "frontend_manager_defs.hpp" -#include "ngraph/variant.hpp" +#include "openvino/core/variant.hpp" #include "parameters.hpp" -namespace ngraph { +namespace ov { namespace frontend { // -------------- FrontEndManager ----------------- using FrontEndFactory = std::function; @@ -98,4 +98,4 @@ struct FrontEndPluginInfo { }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager_defs.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager_defs.hpp index 662ce487923074..708fa83f52500d 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager_defs.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/frontend_manager_defs.hpp @@ -4,7 +4,7 @@ #pragma once -#include "ngraph/visibility.hpp" +#include "openvino/core/visibility.hpp" // Increment each time when FrontEnd/InputModel/Place interface is changed #define OV_FRONTEND_API_VERSION 1 diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp index 6e930e4ecfba1d..c20840de6e56d0 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/input_model.hpp @@ -9,11 +9,11 @@ #include #include "frontend_manager_defs.hpp" -#include "ngraph/partial_shape.hpp" -#include "ngraph/type/element_type.hpp" +#include "openvino/core/partial_shape.hpp" +#include "openvino/core/type/element_type.hpp" #include "place.hpp" -namespace ngraph { +namespace ov { namespace frontend { /// \brief InputModel class represents an original, not yet converted model graph in a /// framework format given services to find places of interest in a graph or specialize/edit @@ -173,17 +173,17 @@ class FRONTEND_API InputModel { /// converted to ngraph. /// \param place Model place /// \param shape Partial shape for this place - virtual void set_partial_shape(Place::Ptr place, const ngraph::PartialShape& shape); + virtual void set_partial_shape(Place::Ptr place, const ov::PartialShape& shape); /// \brief Returns current partial shape used for this place /// \param place Model place /// \return Partial shape for this place - virtual ngraph::PartialShape get_partial_shape(Place::Ptr place) const; + virtual ov::PartialShape get_partial_shape(Place::Ptr place) const; /// \brief Sets new element type for a place /// \param place Model place /// \param type New element type - virtual void set_element_type(Place::Ptr place, const ngraph::element::Type& type); + virtual void set_element_type(Place::Ptr place, const ov::element::Type& type); /// \brief Freezes a tensor with statically defined value or replace existing value for /// already constant node or tensor @@ -200,4 +200,4 @@ class FRONTEND_API InputModel { }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/parameters.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/parameters.hpp index d5f1ec28e6ec8d..c24205620a8ad2 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/parameters.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/parameters.hpp @@ -9,10 +9,10 @@ #include #include "frontend_manager_defs.hpp" -#include "ngraph/op/constant.hpp" #include "ngraph/opsets/opset.hpp" #include "openvino/core/rtti.hpp" #include "openvino/core/variant.hpp" +#include "openvino/op/constant.hpp" namespace ov { diff --git a/ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp b/ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp index 033bc01a6cbeba..1c3f2c6ef6eb31 100644 --- a/ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp +++ b/ngraph/frontend/frontend_manager/include/frontend_manager/place.hpp @@ -10,7 +10,7 @@ #include "frontend_manager_defs.hpp" -namespace ngraph { +namespace ov { namespace frontend { /// \brief An interface for identifying a place in a graph and iterate over it; can refer to /// an operation node, tensor, port etc. @@ -303,4 +303,4 @@ class FRONTEND_API Place { virtual bool is_equal_data(Ptr another) const; }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp index 68e15dc3e1f64a..e1c82ad3bdb5d5 100644 --- a/ngraph/frontend/frontend_manager/src/frontend_manager.cpp +++ b/ngraph/frontend/frontend_manager/src/frontend_manager.cpp @@ -12,8 +12,8 @@ #include "so_extension.hpp" #include "utils.hpp" -using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov; +using namespace ov::frontend; //----------- FrontEndManager --------------------------- class FrontEndManager::Impl { diff --git a/ngraph/frontend/frontend_manager/src/plugin_loader.cpp b/ngraph/frontend/frontend_manager/src/plugin_loader.cpp index cd2c6d032c471e..53426c2912d8bb 100644 --- a/ngraph/frontend/frontend_manager/src/plugin_loader.cpp +++ b/ngraph/frontend/frontend_manager/src/plugin_loader.cpp @@ -16,23 +16,26 @@ #include +#include #include #include #include "openvino/util/file_util.hpp" #include "plugin_loader.hpp" -using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov; +using namespace ov::frontend; #ifdef WIN32 # define DLOPEN(file_str) LoadLibrary(TEXT(file_str.c_str())) # define DLSYM(obj, func) GetProcAddress(obj, func) # define DLCLOSE(obj) FreeLibrary(obj) +# define DLERROR() "" #else # define DLOPEN(file_str) dlopen(file_str.c_str(), RTLD_LAZY) # define DLSYM(obj, func) dlsym(obj, func) # define DLCLOSE(obj) dlclose(obj) +# define DLERROR() dlerror() #endif // TODO: change to std::filesystem for C++17 @@ -70,12 +73,13 @@ static std::vector list_files(const std::string& path) { NGRAPH_SUPPRESS_DEPRECATED_END } -std::vector ngraph::frontend::load_plugins(const std::string& dir_name) { +std::vector ov::frontend::load_plugins(const std::string& dir_name) { auto files = list_files(dir_name); std::vector res; for (const auto& file : files) { auto shared_object = DLOPEN(file); if (!shared_object) { + NGRAPH_DEBUG << "Error loading FrontEnd " << file << " " << DLERROR() << std::endl; continue; } diff --git a/ngraph/frontend/frontend_manager/src/plugin_loader.hpp b/ngraph/frontend/frontend_manager/src/plugin_loader.hpp index 0ee22038e406cf..3319006a535552 100644 --- a/ngraph/frontend/frontend_manager/src/plugin_loader.hpp +++ b/ngraph/frontend/frontend_manager/src/plugin_loader.hpp @@ -14,7 +14,7 @@ static const char FileSeparator[] = "/"; static const char PathSeparator[] = ":"; #endif // _WIN32 -namespace ngraph { +namespace ov { namespace frontend { /// Plugin library handle wrapper. On destruction calls internal function which frees /// library handle @@ -51,4 +51,4 @@ struct PluginData { std::vector load_plugins(const std::string& dir_name); } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/frontend_manager/src/utils.cpp b/ngraph/frontend/frontend_manager/src/utils.cpp index c9b87b93c7e50e..be0daaed730c81 100644 --- a/ngraph/frontend/frontend_manager/src/utils.cpp +++ b/ngraph/frontend/frontend_manager/src/utils.cpp @@ -42,7 +42,7 @@ static std::string _get_frontend_library_path() { CHAR ie_library_path[MAX_PATH]; HMODULE hm = NULL; if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - reinterpret_cast(ngraph::frontend::get_frontend_library_path), + reinterpret_cast(ov::frontend::get_frontend_library_path), &hm)) { FRONT_END_INITIALIZATION_CHECK(false, "GetModuleHandle returned ", GetLastError()); } @@ -50,13 +50,13 @@ static std::string _get_frontend_library_path() { return get_path_name(std::string(ie_library_path)); #elif defined(__APPLE__) || defined(__linux__) Dl_info info; - dladdr(reinterpret_cast(ngraph::frontend::get_frontend_library_path), &info); + dladdr(reinterpret_cast(ov::frontend::get_frontend_library_path), &info); return get_path_name(std::string(info.dli_fname)).c_str(); #else # error "Unsupported OS" #endif // _WIN32 } -std::string ngraph::frontend::get_frontend_library_path() { +std::string ov::frontend::get_frontend_library_path() { return _get_frontend_library_path(); } diff --git a/ngraph/frontend/frontend_manager/src/utils.hpp b/ngraph/frontend/frontend_manager/src/utils.hpp index 50ad9201240af8..d60d5b16ad982a 100644 --- a/ngraph/frontend/frontend_manager/src/utils.hpp +++ b/ngraph/frontend/frontend_manager/src/utils.hpp @@ -6,8 +6,8 @@ #include "frontend_manager/frontend_manager_defs.hpp" -namespace ngraph { +namespace ov { namespace frontend { -FRONTEND_API std::string get_frontend_library_path(); +std::string get_frontend_library_path(); } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/ir/include/ir_frontend/frontend.hpp b/ngraph/frontend/ir/include/ir_frontend/frontend.hpp index 7b1faa012ad219..0ba82d81f10f79 100644 --- a/ngraph/frontend/ir/include/ir_frontend/frontend.hpp +++ b/ngraph/frontend/ir/include/ir_frontend/frontend.hpp @@ -4,12 +4,11 @@ #pragma once -#include -#include - +#include "frontend_manager/frontend.hpp" +#include "openvino/core/variant.hpp" #include "utility.hpp" -namespace ngraph { +namespace ov { namespace frontend { class IR_API FrontEndIR : public FrontEnd { @@ -48,4 +47,4 @@ class IR_API FrontEndIR : public FrontEnd { }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/ir/include/ir_frontend/model.hpp b/ngraph/frontend/ir/include/ir_frontend/model.hpp index 2116a0fe50eaf4..057a9d23c26d11 100644 --- a/ngraph/frontend/ir/include/ir_frontend/model.hpp +++ b/ngraph/frontend/ir/include/ir_frontend/model.hpp @@ -4,15 +4,15 @@ #pragma once -#include -#include #include #include -#include -#include -namespace ngraph { +#include "frontend_manager/frontend_manager.hpp" +#include "ir_frontend/utility.hpp" + +namespace ov { namespace frontend { + class IR_API InputModelIR : public InputModel { friend class FrontEndIR; class InputModelIRImpl; @@ -27,4 +27,4 @@ class IR_API InputModelIR : public InputModel { }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/ir/src/frontend.cpp b/ngraph/frontend/ir/src/frontend.cpp index 91ffea9996a7cc..b02cb3a58edbd9 100644 --- a/ngraph/frontend/ir/src/frontend.cpp +++ b/ngraph/frontend/ir/src/frontend.cpp @@ -7,18 +7,18 @@ #include #include -#include "ir_deserializer.hpp" #include "ir_frontend/model.hpp" #include "ir_frontend/utility.hpp" -#include "ngraph/variant.hpp" -#include "openvino/core/op_extension.hpp" +#include "ngraph/runtime/aligned_buffer.hpp" +#include "ngraph/runtime/shared_buffer.hpp" +#include "openvino/core/variant.hpp" #include "openvino/util/file_util.hpp" #include "so_extension.hpp" #include "xml_parse_utils.h" -using namespace ngraph; +using namespace ov; -namespace ngraph { +namespace ov { namespace frontend { namespace { @@ -215,7 +215,7 @@ InputModel::Ptr FrontEndIR::load_impl(const std::vector bin_stream.read(aligned_weights_buffer->get_ptr(), aligned_weights_buffer->size()); bin_stream.close(); - weights = std::make_shared>>( + weights = std::make_shared>>( aligned_weights_buffer->get_ptr(), aligned_weights_buffer->size(), aligned_weights_buffer); @@ -224,7 +224,7 @@ InputModel::Ptr FrontEndIR::load_impl(const std::vector return create_input_model(); } -std::shared_ptr FrontEndIR::convert(InputModel::Ptr model) const { +std::shared_ptr FrontEndIR::convert(InputModel::Ptr model) const { auto ir_model = std::dynamic_pointer_cast(model); OPENVINO_ASSERT(ir_model != nullptr); return ir_model->convert(); @@ -234,9 +234,9 @@ std::string FrontEndIR::get_name() const { return "ir"; } } // namespace frontend -} // namespace ngraph +} // namespace ov -extern "C" IR_API ngraph::frontend::FrontEndVersion GetAPIVersion() { +extern "C" IR_API ov::frontend::FrontEndVersion GetAPIVersion() { return OV_FRONTEND_API_VERSION; } diff --git a/ngraph/frontend/ir/src/ir_deserializer.cpp b/ngraph/frontend/ir/src/ir_deserializer.cpp index 4ced1f2f2eb6f3..8908fb6c03a242 100644 --- a/ngraph/frontend/ir/src/ir_deserializer.cpp +++ b/ngraph/frontend/ir/src/ir_deserializer.cpp @@ -2,18 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include "ir_deserializer.hpp" -#include -#include -#include -#include #include -#include -#include -#include +#include "ie_ngraph_utils.hpp" #include "ir_frontend/model.hpp" +#include "ngraph/op/util/framework_node.hpp" +#include "ngraph/opsets/opset1.hpp" +#include "rt_info_deserializer.hpp" +#include "transformations/rt_info/attributes.hpp" +#include "utils.hpp" +#include "xml_parse_utils.h" using namespace ov; @@ -727,6 +727,9 @@ std::shared_ptr XmlDeserializer::createNode(const std::vectorvisit_attributes(attribute_visitor)) { diff --git a/ngraph/frontend/ir/src/ir_deserializer.hpp b/ngraph/frontend/ir/src/ir_deserializer.hpp index 90398fc42f28ad..192d8b7276d89c 100644 --- a/ngraph/frontend/ir/src/ir_deserializer.hpp +++ b/ngraph/frontend/ir/src/ir_deserializer.hpp @@ -4,25 +4,26 @@ #pragma once -#include - -#include -#include #include #include -#include #include -#include +#include "ie_ngraph_utils.hpp" +#include "ir_frontend/model.hpp" +#include "openvino/core/attribute_visitor.hpp" #include "openvino/core/op_extension.hpp" +#include "openvino/op/loop.hpp" +#include "openvino/op/util/sub_graph_base.hpp" +#include "utils.hpp" +#include "xml_parse_utils.h" namespace ov { struct GenericLayerParams { struct LayerPortData { size_t portId; - std::vector dims; - ngraph::element::Type_t precision; + std::vector dims; + ov::element::Type_t precision; std::unordered_set names; }; size_t layerId; @@ -55,13 +56,13 @@ struct GenericLayerParams { } }; -class XmlDeserializer : public ngraph::AttributeVisitor { +class XmlDeserializer : public ov::AttributeVisitor { public: explicit XmlDeserializer(const pugi::xml_node& node, const std::shared_ptr& weights, const std::unordered_map& opsets, const std::unordered_map& extensions, - std::unordered_map>& variables, + std::unordered_map>& variables, size_t version) : m_node(node), m_weights(weights), @@ -70,13 +71,13 @@ class XmlDeserializer : public ngraph::AttributeVisitor { m_variables(variables), m_version(version) {} - void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { + void on_adapter(const std::string& name, ov::ValueAccessor& value) override { std::string val; if (!getStrAttribute(m_node.child("data"), name, val)) return; value.set(val); } - void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { + void on_adapter(const std::string& name, ov::ValueAccessor& value) override { std::string val; if (!getStrAttribute(m_node.child("data"), name, val)) return; @@ -93,46 +94,45 @@ class XmlDeserializer : public ngraph::AttributeVisitor { return; value.set(is_true); } - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override; + void on_adapter(const std::string& name, ov::ValueAccessor& adapter) override; - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor& adapter) override { std::string val; if (!getStrAttribute(m_node.child("data"), name, val)) return; adapter.set(stringToType(val)); } - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor& adapter) override { std::string val; if (!getStrAttribute(m_node.child("data"), name, val)) return; adapter.set(stringToType(val)); } - void on_adapter(const std::string& name, - ngraph::ValueAccessor>& adapter) override; + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override; - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { std::vector value; if (!getParameters(m_node.child("data"), name, value)) return; adapter.set(value); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { std::vector value; if (!getParameters(m_node.child("data"), name, value)) return; adapter.set(value); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { std::vector value; if (!getParameters(m_node.child("data"), name, value)) return; adapter.set(value); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { std::vector value; if (!getParameters(m_node.child("data"), name, value)) return; @@ -149,41 +149,41 @@ class XmlDeserializer : public ngraph::AttributeVisitor { /// \brief Traverses port_map in order to create vector of InputDescription shared_ptrs. /// Shall be used only for ops which have port_map attribute. /// \param node xml op representation - std::vector> + std::vector> parseInputDescription(const pugi::xml_node& node, const std::string& body_name, const std::string& port_map_name); /// \brief Traverses port_map in order to create vector of OutputDescription shared_ptrs. /// Shall be used only for ops which have port_map attribute. /// \param node xml op representation - std::vector> + std::vector> parseOutputDescription(const pugi::xml_node& node, const std::string& body_name, const std::string& port_map_name); // TODO consider to call only once per layer/TI-Loop node IoMap updated_io_map(const pugi::xml_node& node, const pugi::xml_node& body_node); - /// \brief Traverses xml node representation in order to create nGraph function for it. + /// \brief Traverses xml node representation in order to create ov function for it. /// \param node xml node representation /// \param weights weights attached to current node /// \return shared pointer to function representing input node - std::shared_ptr parse_function(const pugi::xml_node& root, - const std::shared_ptr& weights); + std::shared_ptr parse_function(const pugi::xml_node& root, + const std::shared_ptr& weights); /// \brief Traverses xml node representation in order to get the purpose attribute of /// inputs/outputs in the body of Loop op. \param node xml node representation \return struct /// with value of purpuse attribute - ngraph::op::v5::Loop::SpecialBodyPorts parsePurposeAttribute(const pugi::xml_node& node); + ov::op::v5::Loop::SpecialBodyPorts parsePurposeAttribute(const pugi::xml_node& node); GenericLayerParams parseGenericParams(const pugi::xml_node& node); - std::shared_ptr createNode(const ngraph::OutputVector& inputs, - const pugi::xml_node& node, - const ov::Weights& weights, - const GenericLayerParams& params); + std::shared_ptr createNode(const ov::OutputVector& inputs, + const pugi::xml_node& node, + const ov::Weights& weights, + const GenericLayerParams& params); // -- DATA -- const pugi::xml_node m_node; const ov::Weights& m_weights; const std::unordered_map& m_opsets; const std::unordered_map& m_extensions; - std::unordered_map>& m_variables; + std::unordered_map>& m_variables; /// /// store information about parameters/results order during function creation diff --git a/ngraph/frontend/ir/src/model.cpp b/ngraph/frontend/ir/src/model.cpp index 2fa09ab8c4a78e..270218219b69ac 100644 --- a/ngraph/frontend/ir/src/model.cpp +++ b/ngraph/frontend/ir/src/model.cpp @@ -11,6 +11,8 @@ #include #include +#include "openvino/core/validation_util.hpp" + using namespace ngraph; using namespace InferenceEngine; @@ -182,7 +184,7 @@ void ParsePreProcess(pugi::xml_node& root, } } // namespace -namespace ngraph { +namespace ov { namespace frontend { class InputModelIR::InputModelIRImpl { std::shared_ptr m_weights; @@ -239,4 +241,4 @@ std::shared_ptr InputModelIR::InputModelIRImpl::convert() { return function; } } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/ir/src/rt_info_deserializer.cpp b/ngraph/frontend/ir/src/rt_info_deserializer.cpp index 739432e594f378..0b7bee7c329e7b 100644 --- a/ngraph/frontend/ir/src/rt_info_deserializer.cpp +++ b/ngraph/frontend/ir/src/rt_info_deserializer.cpp @@ -9,16 +9,16 @@ using namespace ov; -void RTInfoDeserializer::on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) { +void RTInfoDeserializer::on_adapter(const std::string& name, ValueAccessor& adapter) { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) return; - if (auto a = ngraph::as_type>>(&adapter)) { + if (auto a = as_type>>(&adapter)) { std::set ss; str_to_container(val, ss); a->set(ss); } else { IR_THROW("Not implemented"); } -} \ No newline at end of file +} diff --git a/ngraph/frontend/ir/src/rt_info_deserializer.hpp b/ngraph/frontend/ir/src/rt_info_deserializer.hpp index de9c708b78d5cb..86274edd88776c 100644 --- a/ngraph/frontend/ir/src/rt_info_deserializer.hpp +++ b/ngraph/frontend/ir/src/rt_info_deserializer.hpp @@ -4,18 +4,19 @@ #pragma once -#include #include #include -#include -#include + +#include "ir_frontend/utility.hpp" +#include "openvino/core/attribute_visitor.hpp" +#include "utils.hpp" namespace ov { -class RTInfoDeserializer : public ngraph::AttributeVisitor { +class RTInfoDeserializer : public ov::AttributeVisitor { public: explicit RTInfoDeserializer(const pugi::xml_node& node) : m_node(node) {} - void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { + void on_adapter(const std::string& name, ov::ValueAccessor& value) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -23,7 +24,7 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { value.set(val); } - void on_adapter(const std::string& name, ngraph::ValueAccessor& value) override { + void on_adapter(const std::string& name, ov::ValueAccessor& value) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -42,16 +43,16 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { value.set(is_true); } - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override; + void on_adapter(const std::string& name, ov::ValueAccessor& adapter) override; - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor& adapter) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) return; adapter.set(stringToType(val)); } - void on_adapter(const std::string& name, ngraph::ValueAccessor& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor& adapter) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -59,12 +60,11 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { adapter.set(stringToType(val)); } - void on_adapter(const std::string& name, - ngraph::ValueAccessor>& adapter) override { - throw ngraph::ngraph_error("Function type is unsupported for rt info deserialization"); + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { + throw ov::Exception("Function type is unsupported for rt info deserialization"); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -74,7 +74,7 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { adapter.set(value); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -84,7 +84,7 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { adapter.set(value); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -94,7 +94,7 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { adapter.set(value); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -104,7 +104,7 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { adapter.set(value); } - void on_adapter(const std::string& name, ngraph::ValueAccessor>& adapter) override { + void on_adapter(const std::string& name, ov::ValueAccessor>& adapter) override { check_attribute_name(name); std::string val; if (!getStrAttribute(m_node, name, val)) @@ -116,11 +116,11 @@ class RTInfoDeserializer : public ngraph::AttributeVisitor { void check_attribute_name(const std::string& name) const { if (name == "name" || name == "version") { - throw ngraph::ngraph_error("Attribute key with name: " + name + " is not allowed. Please use another name"); + throw ov::Exception("Attribute key with name: " + name + " is not allowed. Please use another name"); } } private: pugi::xml_node m_node; }; -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/ir/src/utils.cpp b/ngraph/frontend/ir/src/utils.cpp index 37bd3ff1315fe1..9af2f072fb012b 100644 --- a/ngraph/frontend/ir/src/utils.cpp +++ b/ngraph/frontend/ir/src/utils.cpp @@ -4,9 +4,12 @@ #include "utils.hpp" +#include "ie_ngraph_utils.hpp" +#include "openvino/util/common_util.hpp" + namespace ov { -void operator>>(const std::stringstream& in, ngraph::element::Type& type) { - type = InferenceEngine::details::convertPrecision(ngraph::trim(in.str())); +void operator>>(const std::stringstream& in, ov::element::Type& type) { + type = InferenceEngine::details::convertPrecision(ov::util::trim(in.str())); } bool getStrAttribute(const pugi::xml_node& node, const std::string& name, std::string& value) { @@ -19,4 +22,4 @@ bool getStrAttribute(const pugi::xml_node& node, const std::string& name, std::s value = std::string(attr.value()); return true; } -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/ir/src/utils.hpp b/ngraph/frontend/ir/src/utils.hpp index 31486ead3a6750..0e734c16a0e0b7 100644 --- a/ngraph/frontend/ir/src/utils.hpp +++ b/ngraph/frontend/ir/src/utils.hpp @@ -4,16 +4,13 @@ #pragma once -#include - -#include -#include #include -#include -#include + +#include "openvino/core/type/element_type.hpp" +#include "xml_parse_utils.h" namespace ov { -void operator>>(const std::stringstream& in, ngraph::element::Type& type); +void operator>>(const std::stringstream& in, ov::element::Type& type); bool getStrAttribute(const pugi::xml_node& node, const std::string& name, std::string& value); @@ -49,4 +46,4 @@ T stringToType(const std::string& valStr) { } return ret; } -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/CMakeLists.txt b/ngraph/frontend/onnx/frontend/CMakeLists.txt index ed1086f929e4c4..a1aabaccecd6c3 100644 --- a/ngraph/frontend/onnx/frontend/CMakeLists.txt +++ b/ngraph/frontend/onnx/frontend/CMakeLists.txt @@ -51,9 +51,6 @@ target_include_directories(${TARGET_NAME} PUBLIC $ convert(InputModel::Ptr model) const override; - void convert(std::shared_ptr partially_converted) const override; - std::shared_ptr decode(InputModel::Ptr model) const override; + std::shared_ptr convert(InputModel::Ptr model) const override; + void convert(std::shared_ptr partially_converted) const override; + std::shared_ptr decode(InputModel::Ptr model) const override; std::string get_name() const override; bool supported_impl(const std::vector>& variants) const override; @@ -27,5 +27,4 @@ class ONNX_FRONTEND_API FrontEndONNX : public FrontEnd { }; } // namespace frontend - -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/src/core/attribute.hpp b/ngraph/frontend/onnx/frontend/src/core/attribute.hpp index fbd972444bc1f9..c2ca178573ee61 100644 --- a/ngraph/frontend/onnx/frontend/src/core/attribute.hpp +++ b/ngraph/frontend/onnx/frontend/src/core/attribute.hpp @@ -28,12 +28,7 @@ namespace error { namespace attribute { namespace detail { struct Attribute : ngraph_error { -#ifdef NGRAPH_USE_PROTOBUF_LITE Attribute(const std::string& msg, AttributeProto_AttributeType type) : ngraph_error{msg} {} -#else - Attribute(const std::string& msg, AttributeProto_AttributeType type) - : ngraph_error{msg + ": " + ONNX_NAMESPACE::AttributeProto_AttributeType_Name(type)} {} -#endif }; } // namespace detail diff --git a/ngraph/frontend/onnx/frontend/src/core/graph.cpp b/ngraph/frontend/onnx/frontend/src/core/graph.cpp index bf4cb53d32e613..51d1d3772b5f52 100644 --- a/ngraph/frontend/onnx/frontend/src/core/graph.cpp +++ b/ngraph/frontend/onnx/frontend/src/core/graph.cpp @@ -260,6 +260,22 @@ OutputVector Graph::make_ng_nodes(const Node& onnx_node) const { } void Graph::set_friendly_names(const Node& onnx_node, const OutputVector& ng_node_vector) const { + if (onnx_node.op_type() == "Identity") { + // we eliminate Identity op (since it's a no-op) and therefore + // we must preserve its input name, unless Identity is connected + // to a graph's output - in that case Identity's input gets + // a new name + const auto& graph_outputs = m_model->get_graph().output(); + const auto& name = onnx_node.output(0); + bool is_identity_on_output = std::find_if(graph_outputs.begin(), + graph_outputs.end(), + [&name](const ONNX_NAMESPACE::ValueInfoProto& output) -> bool { + return output.name() == name; + }) != graph_outputs.end(); + if (!is_identity_on_output) { + return; + } + } for (size_t i = 0; i < ng_node_vector.size(); ++i) { // Trailing optional outputs may not be specified in the ONNX model. // Other optional outputs should have name set to an empty string. diff --git a/ngraph/frontend/onnx/frontend/src/core/tensor.hpp b/ngraph/frontend/onnx/frontend/src/core/tensor.hpp index 9d0982993e6d68..7656fc1f1bc997 100644 --- a/ngraph/frontend/onnx/frontend/src/core/tensor.hpp +++ b/ngraph/frontend/onnx/frontend/src/core/tensor.hpp @@ -29,23 +29,11 @@ using TensorProto_DataType = decltype(ONNX_NAMESPACE::TensorProto{}.data_type()) namespace error { namespace tensor { struct invalid_data_type : ngraph_error { -#ifdef NGRAPH_USE_PROTOBUF_LITE explicit invalid_data_type(TensorProto_DataType type) : ngraph_error{"invalid data type"} {} -#else - explicit invalid_data_type(TensorProto_DataType type) - : ngraph_error{"invalid data type: " + ONNX_NAMESPACE::TensorProto_DataType_Name( - static_cast(type))} {} -#endif }; struct unsupported_data_type : ngraph_error { -#ifdef NGRAPH_USE_PROTOBUF_LITE explicit unsupported_data_type(TensorProto_DataType type) : ngraph_error{"unsupported data type"} {} -#else - explicit unsupported_data_type(TensorProto_DataType type) - : ngraph_error{"unsupported data type: " + ONNX_NAMESPACE::TensorProto_DataType_Name( - static_cast(type))} {} -#endif }; struct unspecified_name : ngraph_error { diff --git a/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.cpp b/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.cpp index f7662d1f116b9e..980669c6d54992 100644 --- a/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.cpp +++ b/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.cpp @@ -11,7 +11,7 @@ #include "ngraph/check.hpp" -using namespace ngraph::onnx_editor; +using namespace ov::onnx_editor; enum class PortType { InputPort, OutputPort }; @@ -78,6 +78,10 @@ bool is_graph_initializer(const ONNX_NAMESPACE::GraphProto& graph, const std::st int find_source_node_idx(const ONNX_NAMESPACE::GraphProto& graph, const int current_node_idx, const std::string& input_name) { + // Some operators (e.g. Clip) have optional inputs + if (input_name.empty()) + return -1; + for (int i = current_node_idx - 1; i >= 0; --i) { const auto& outputs = graph.node(i).output(); const auto output_found = std::any_of(std::begin(outputs), std::end(outputs), is_equal_to(input_name)); @@ -329,11 +333,11 @@ void SubgraphExtractor::extract_subgraph(std::vector subgraph_output SubgraphExtractor::SubgraphComponents SubgraphExtractor::discover_output_contributors( const OutputEdge& output_edge, const SubgraphComponents& already_collected) const { - const auto already_visited = [&already_collected](const int node_index) { - return already_collected.nodes.count(node_index) > 0; + SubgraphComponents output_contributors; + const auto already_visited = [&already_collected, &output_contributors](const int node_index) { + return already_collected.nodes.count(node_index) > 0 || output_contributors.nodes.count(node_index) > 0; }; - SubgraphComponents output_contributors; const auto tensor_name = get_output_tensor_name(m_onnx_graph, output_edge); output_contributors.outputs.insert(tensor_name); @@ -357,7 +361,7 @@ SubgraphExtractor::SubgraphComponents SubgraphExtractor::discover_output_contrib // and/or keep looking for more contributors further up in the graph // when an input or initializer is reached, the visitor stops the lookup - const auto n_inputs = m_node_inputs[n]; + const auto& n_inputs = m_node_inputs[n]; for (auto& input_name : n_inputs) { if (is_graph_input(m_onnx_graph, input_name)) { output_contributors.inputs.insert(input_name); @@ -371,7 +375,9 @@ SubgraphExtractor::SubgraphComponents SubgraphExtractor::discover_output_contrib } else { // if an edge points to another node (source node) it should be visited // in one of the future iterations - nodes_to_visit.push(find_source_node_idx(m_onnx_graph, n, input_name)); + const auto node_idx = find_source_node_idx(m_onnx_graph, n, input_name); + if (node_idx >= 0) + nodes_to_visit.push(node_idx); } } } @@ -391,6 +397,7 @@ std::vector SubgraphExtractor::all_output_edges() const { for (const auto& graph_output : m_onnx_graph.output()) { const auto node_index = find_source_node_idx(m_onnx_graph, m_onnx_graph.node_size(), graph_output.name()); + OPENVINO_ASSERT(node_index >= 0); const auto& node_outputs = m_onnx_graph.node(node_index).output(); const auto output_port_it = std::find(std::begin(node_outputs), std::end(node_outputs), graph_output.name()); all_outputs.emplace_back(node_index, output_port_it - std::begin(node_outputs)); diff --git a/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.hpp b/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.hpp index 979dbde719a4e6..e273bfcfd4aedc 100644 --- a/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.hpp +++ b/ngraph/frontend/onnx/frontend/src/detail/subgraph_extraction.hpp @@ -18,7 +18,7 @@ class NodeProto; class ValueInfoProto; } // namespace ONNX_NAMESPACE -namespace ngraph { +namespace ov { namespace onnx_editor { /// \brief Subgraph extraction helper structure struct SubgraphExtractor { @@ -95,4 +95,4 @@ struct SubgraphExtractor { void extract_subgraph_from_onnx_model(const SubgraphComponents& subgraph); }; } // namespace onnx_editor -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/src/edge_mapper.cpp b/ngraph/frontend/onnx/frontend/src/edge_mapper.cpp index 4602a2db623403..4fd7e75f4938fd 100644 --- a/ngraph/frontend/onnx/frontend/src/edge_mapper.cpp +++ b/ngraph/frontend/onnx/frontend/src/edge_mapper.cpp @@ -11,8 +11,8 @@ #include "ngraph/check.hpp" #include "ngraph/except.hpp" -using namespace ngraph; -using namespace ngraph::onnx_editor; +using namespace ov; +using namespace ov::onnx_editor; onnx_editor::EdgeMapper::EdgeMapper(const ONNX_NAMESPACE::GraphProto& graph_proto) : m_node_inputs(graph_proto.node().size()), @@ -66,8 +66,8 @@ int onnx_editor::EdgeMapper::get_node_output_idx(int node_index, const std::stri const auto& node_outputs = m_node_outputs[node_index]; const auto out_port_idx = std::find(std::begin(node_outputs), std::end(node_outputs), output_name); if (out_port_idx == std::end(node_outputs)) { - throw ngraph_error("Node with index: " + std::to_string(node_index) + - " has not output with name: " + output_name); + throw ov::Exception("Node with index: " + std::to_string(node_index) + + " has not output with name: " + output_name); } return (out_port_idx - std::begin(node_outputs)); } @@ -88,8 +88,8 @@ std::vector onnx_editor::EdgeMapper::get_node_input_indexes(int node_index, ++index; } if (node_inputs_indexes.size() == 0) { - throw ngraph_error("Node with index: " + std::to_string(node_index) + - " has not input with name: " + input_name); + throw ov::Exception("Node with index: " + std::to_string(node_index) + + " has not input with name: " + input_name); } return node_inputs_indexes; } @@ -102,9 +102,9 @@ InputEdge onnx_editor::EdgeMapper::find_input_edge(const EditorNode& node, const if (node_indexes.size() == 1) { node_index = node_indexes[0]; } else if (node_indexes.empty()) { - throw ngraph_error("Node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) + - " and output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) + - " was not found"); + throw ov::Exception("Node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) + + " and output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) + + " was not found"); } else if (!in.m_input_name.empty()) // input indexes are not deterministic if a node name is ambiguous { // many nodes with the same name @@ -117,16 +117,16 @@ InputEdge onnx_editor::EdgeMapper::find_input_edge(const EditorNode& node, const } } if (matched_inputs_number == 0) { - throw ngraph_error("Input edge described by: " + node.m_node_name + - " and input name: " + in.m_input_name + " was not found"); + throw ov::Exception("Input edge described by: " + node.m_node_name + + " and input name: " + in.m_input_name + " was not found"); } if (matched_inputs_number > 1) { - throw ngraph_error("Given node name: " + node.m_node_name + " and input name: " + in.m_input_name + - " are ambiguous to determine input edge"); + throw ov::Exception("Given node name: " + node.m_node_name + " and input name: " + in.m_input_name + + " are ambiguous to determine input edge"); } } else { - throw ngraph_error("Given node name: " + node.m_node_name + " and input index: " + - std::to_string(in.m_input_index) + " are ambiguous to determine input edge"); + throw ov::Exception("Given node name: " + node.m_node_name + " and input index: " + + std::to_string(in.m_input_index) + " are ambiguous to determine input edge"); } } else { // the node index is provided check_node_index(node_index); @@ -139,27 +139,27 @@ InputEdge onnx_editor::EdgeMapper::find_input_edge(const EditorNode& node, const const auto input_indexes = get_node_input_indexes(node_index, in.m_input_name); if (input_indexes.size() > 1) // more indexes with the same name { - throw ngraph_error("Node with index: " + std::to_string(node_index) + - " has more than one inputs with name: " + in.m_input_name + - ". You should use port indexes to distinguish them."); + throw ov::Exception("Node with index: " + std::to_string(node_index) + + " has more than one inputs with name: " + in.m_input_name + + ". You should use port indexes to distinguish them."); } return InputEdge{node_index, input_indexes[0], in.m_new_input_name}; } else { - throw ngraph_error("Not enough information to determine input edge"); + throw ov::Exception("Not enough information to determine input edge"); } } OutputEdge onnx_editor::EdgeMapper::find_output_edge(const EditorNode& node, const EditorOutput& out) const { - int node_index = node_index = node.m_node_index; + int node_index = node.m_node_index; if (node_index == -1) { // the node index is not provided // identification can be both based on node name and output name (if the node index is not provided) const auto& node_indexes = find_node_indexes(node.m_node_name, node.m_output_name); if (node_indexes.size() == 1) { node_index = node_indexes[0]; } else if (node_indexes.empty()) { - throw ngraph_error("Node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) + - " and output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) + - " was not found"); + throw ov::Exception("Node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) + + " and output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) + + " was not found"); } else if (!out.m_output_name.empty()) // output indexes are not deterministic if a node name is ambiguous { // many nodes with the same name @@ -173,12 +173,12 @@ OutputEdge onnx_editor::EdgeMapper::find_output_edge(const EditorNode& node, con } } if (matched_outputs_number == 0) { - throw ngraph_error("Output edge described by: " + node.m_node_name + - " and output name: " + out.m_output_name + " was not found"); + throw ov::Exception("Output edge described by: " + node.m_node_name + + " and output name: " + out.m_output_name + " was not found"); } } else { - throw ngraph_error("Given node name: " + node.m_node_name + " and output index: " + - std::to_string(out.m_output_index) + " are ambiguous to determine output edge"); + throw ov::Exception("Given node name: " + node.m_node_name + " and output index: " + + std::to_string(out.m_output_index) + " are ambiguous to determine output edge"); } } else { // the node index is provided check_node_index(node_index); @@ -191,7 +191,7 @@ OutputEdge onnx_editor::EdgeMapper::find_output_edge(const EditorNode& node, con const auto output_idx = get_node_output_idx(node_index, out.m_output_name); return OutputEdge{node_index, output_idx}; } else { - throw ngraph_error("Not enough information to determine output edge"); + throw ov::Exception("Not enough information to determine output edge"); } } diff --git a/ngraph/frontend/onnx/frontend/src/edge_mapper.hpp b/ngraph/frontend/onnx/frontend/src/edge_mapper.hpp index d9fe93fcaf03c9..44619d5a305407 100644 --- a/ngraph/frontend/onnx/frontend/src/edge_mapper.hpp +++ b/ngraph/frontend/onnx/frontend/src/edge_mapper.hpp @@ -16,7 +16,7 @@ namespace ONNX_NAMESPACE { class GraphProto; } // namespace ONNX_NAMESPACE -namespace ngraph { +namespace ov { namespace onnx_editor { /// \brief A class which allows specifying InputEdge and OutputEdge by user-friendly ONNX /// names. @@ -149,4 +149,4 @@ class EdgeMapper { std::multimap m_output_consumers_index; }; } // namespace onnx_editor -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/src/editor.cpp b/ngraph/frontend/onnx/frontend/src/editor.cpp index 641f43b144a1d4..3ed788fb8e9514 100644 --- a/ngraph/frontend/onnx/frontend/src/editor.cpp +++ b/ngraph/frontend/onnx/frontend/src/editor.cpp @@ -17,8 +17,8 @@ #include "onnx_common/utils.hpp" #include "utils/onnx_internal.hpp" -using namespace ngraph; -using namespace ngraph::onnx_editor; +using namespace ov; +using namespace ov::onnx_editor; NGRAPH_SUPPRESS_DEPRECATED_START @@ -69,25 +69,25 @@ ValueInfoProto* find_graph_value_info(GraphProto& graph, const std::string& name void modify_input_type(ValueInfoProto& onnx_input, const element::Type_t elem_type) { if (!onnx_input.has_type()) { - throw ngraph_error("The input is malformed - it doesn't contain the 'type' field. Cannot change the " - "data type. Input name: " + - onnx_input.name()); + throw ov::Exception("The input is malformed - it doesn't contain the 'type' field. Cannot change the " + "data type. Input name: " + + onnx_input.name()); } auto* type_proto = onnx_input.mutable_type(); if (!type_proto->has_tensor_type()) { - throw ngraph_error("The input is malformed - it doesn't contain the 'tensor_type' field. Cannot " - "change the data type. Input name: " + - onnx_input.name()); + throw ov::Exception("The input is malformed - it doesn't contain the 'tensor_type' field. Cannot " + "change the data type. Input name: " + + onnx_input.name()); } auto* tensor_type = type_proto->mutable_tensor_type(); - if (onnx_common::is_supported_ng_type(elem_type)) { - tensor_type->set_elem_type(onnx_common::ng_to_onnx_data_type(elem_type)); + if (ngraph::onnx_common::is_supported_ng_type(elem_type)) { + tensor_type->set_elem_type(ngraph::onnx_common::ng_to_onnx_data_type(elem_type)); } else { - throw ngraph_error("The input type for input '" + onnx_input.name() + "' cannot be set to: " + - element::Type(elem_type).get_type_name() + ". This type is not allowed in ONNX."); + throw ov::Exception("The input type for input '" + onnx_input.name() + "' cannot be set to: " + + element::Type(elem_type).get_type_name() + ". This type is not allowed in ONNX."); } } @@ -106,16 +106,16 @@ void add_dim_to_onnx_shape(const Dimension& dim, ONNX_NAMESPACE::TensorShapeProt void modify_input_shape(ValueInfoProto& onnx_input, const PartialShape& new_shape) { if (!onnx_input.has_type()) { - throw ngraph_error("The input is malformed - it doesn't contain the 'type' field. Cannot change the " - "input shape. Input name: " + - onnx_input.name()); + throw ov::Exception("The input is malformed - it doesn't contain the 'type' field. Cannot change the " + "input shape. Input name: " + + onnx_input.name()); } auto* type_proto = onnx_input.mutable_type(); if (!type_proto->has_tensor_type()) { - throw ngraph_error("The input is malformed - it doesn't contain the 'tensor_type' field. Cannot " - "change the input shape. Input name: " + - onnx_input.name()); + throw ov::Exception("The input is malformed - it doesn't contain the 'tensor_type' field. Cannot " + "change the input shape. Input name: " + + onnx_input.name()); } auto* tensor_type = type_proto->mutable_tensor_type(); @@ -144,22 +144,22 @@ void modify_initializer(TensorProto& initializer, const std::shared_ptr values, ValueInfoProto* input) { const auto elem_type = values->get_element_type(); - if (!onnx_common::is_supported_ng_type(elem_type)) { - throw ngraph_error("Initializer '" + name + "' type cannot be set to: " + - element::Type(elem_type).get_type_name() + ". This type is not allowed in ONNX."); + if (!ngraph::onnx_common::is_supported_ng_type(elem_type)) { + throw ov::Exception("Initializer '" + name + "' type cannot be set to: " + + element::Type(elem_type).get_type_name() + ". This type is not allowed in ONNX."); } initializer.Clear(); initializer.set_name(name); - initializer.set_data_type(onnx_common::ng_to_onnx_data_type(values->get_element_type())); + initializer.set_data_type(ngraph::onnx_common::ng_to_onnx_data_type(values->get_element_type())); for (const auto& dim : values->get_shape()) { initializer.add_dims(dim); } const auto data_size_in_bytes = - shape_size(values->get_shape()) * onnx_common::get_onnx_data_size(initializer.data_type()); + shape_size(values->get_shape()) * ngraph::onnx_common::get_onnx_data_size(initializer.data_type()); initializer.set_raw_data(values->get_data_ptr(), data_size_in_bytes); // update input with type and shape of initializer @@ -183,8 +183,11 @@ class InferShapesAutoRelease { m_infer_shapes_was_run = true; } ~InferShapesAutoRelease() { - if (m_infer_shapes_was_run) { - m_model_proto->mutable_graph()->clear_value_info(); + try { + if (m_infer_shapes_was_run) { + m_model_proto->mutable_graph()->clear_value_info(); + } + } catch (...) { } } @@ -203,14 +206,17 @@ struct onnx_editor::ONNXModelEditor::Impl { Impl() = delete; Impl(const std::string& model_path) - : m_model_proto{std::make_shared(onnx_common::parse_from_file(model_path))} {} + : m_model_proto{ + std::make_shared(ngraph::onnx_common::parse_from_file(model_path))} {} Impl(std::istream& model_stream) - : m_model_proto{std::make_shared(onnx_common::parse_from_istream(model_stream))} {} + : m_model_proto{ + std::make_shared(ngraph::onnx_common::parse_from_istream(model_stream))} {} #if defined(OPENVINO_ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) Impl(const std::wstring& model_path) - : m_model_proto{std::make_shared(onnx_common::parse_from_file(model_path))} {} + : m_model_proto{ + std::make_shared(ngraph::onnx_common::parse_from_file(model_path))} {} #endif }; @@ -222,7 +228,7 @@ onnx_editor::ONNXModelEditor::ONNXModelEditor(const std::string& model_path) #if defined(OPENVINO_ENABLE_UNICODE_PATH_SUPPORT) && defined(_WIN32) onnx_editor::ONNXModelEditor::ONNXModelEditor(const std::wstring& model_path) - : m_model_path{file_util::wstring_to_string(model_path)}, + : m_model_path{ngraph::file_util::wstring_to_string(model_path)}, m_pimpl{new ONNXModelEditor::Impl{model_path}, [](Impl* impl) { delete impl; }} {} @@ -242,11 +248,11 @@ void onnx_editor::ONNXModelEditor::serialize(const std::string& out_file_path) c std::ofstream out_file{out_file_path, std::ios::out | std::ios::binary}; if (!out_file.is_open()) { - throw ngraph_error("Could not open the file: " + out_file_path); + throw ov::Exception("Could not open the file: " + out_file_path); }; if (!m_pimpl->m_model_proto->SerializeToOstream(&out_file)) { - throw ngraph_error("Could not serialize the model to: " + out_file_path); + throw ov::Exception("Could not serialize the model to: " + out_file_path); } else { out_file.close(); } @@ -260,8 +266,8 @@ void onnx_editor::ONNXModelEditor::set_input_types(const std::maptype().tensor_type(); if (onnx_tensor_type.has_shape()) { - return onnx_common::to_ng_shape(onnx_tensor_type.shape()); + return ngraph::onnx_common::to_ng_shape(onnx_tensor_type.shape()); } else { return PartialShape::dynamic(); } } else if (tensor) { return PartialShape{Shape{tensor->dims().cbegin(), tensor->dims().cend()}}; } else { - throw ngraph_error("The tensor: " + tensor_name + " was not found in the graph"); + throw ov::Exception("The tensor: " + tensor_name + " was not found in the graph"); } } @@ -402,7 +408,7 @@ std::string onnx_editor::ONNXModelEditor::model_string() const { } std::shared_ptr onnx_editor::ONNXModelEditor::get_function() const { - return onnx_import::detail::import_onnx_model(m_pimpl->m_model_proto, m_model_path); + return ngraph::onnx_import::detail::import_onnx_model(m_pimpl->m_model_proto, m_model_path); } void onnx_editor::ONNXModelEditor::set_input_values( @@ -581,5 +587,5 @@ std::vector onnx_editor::ONNXModelEditor::get_output_ports(const Ed } std::shared_ptr onnx_editor::ONNXModelEditor::decode() { - return onnx_import::detail::decode_to_framework_nodes(m_pimpl->m_model_proto, m_model_path); + return ngraph::onnx_import::detail::decode_to_framework_nodes(m_pimpl->m_model_proto, m_model_path); } diff --git a/ngraph/frontend/onnx/frontend/src/editor.hpp b/ngraph/frontend/onnx/frontend/src/editor.hpp index c288fa4ccd0676..4d997d7ae61d2a 100644 --- a/ngraph/frontend/onnx/frontend/src/editor.hpp +++ b/ngraph/frontend/onnx/frontend/src/editor.hpp @@ -15,7 +15,7 @@ #include "ngraph/type/element_type.hpp" #include "onnx_import/onnx_importer_visibility.hpp" -namespace ngraph { +namespace ov { namespace onnx_editor { /// \brief A class representing a set of utilities allowing modification of an ONNX model /// @@ -275,4 +275,4 @@ class ONNX_IMPORTER_API ONNXModelEditor final { std::unique_ptr m_pimpl; }; } // namespace onnx_editor -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/src/editor_types.hpp b/ngraph/frontend/onnx/frontend/src/editor_types.hpp index c9c7e02408f7d9..53dcf9393d6a58 100644 --- a/ngraph/frontend/onnx/frontend/src/editor_types.hpp +++ b/ngraph/frontend/onnx/frontend/src/editor_types.hpp @@ -7,7 +7,7 @@ #include #include -namespace ngraph { +namespace ov { enum class EdgeType { INPUT, OUTPUT }; template @@ -124,4 +124,4 @@ struct EditorNode { int m_node_index = -1; }; } // namespace onnx_editor -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/src/frontend.cpp b/ngraph/frontend/onnx/frontend/src/frontend.cpp index 98213c8b3e8043..113ce25a603607 100644 --- a/ngraph/frontend/onnx/frontend/src/frontend.cpp +++ b/ngraph/frontend/onnx/frontend/src/frontend.cpp @@ -13,8 +13,8 @@ #include "onnx_common/onnx_model_validator.hpp" -using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov; +using namespace ov::frontend; using VariantString = VariantWrapper; using VariantWString = VariantWrapper; @@ -71,7 +71,7 @@ std::shared_ptr FrontEndONNX::convert(InputModel::Ptr model) c } void FrontEndONNX::convert(std::shared_ptr partially_converted) const { - onnx_import::detail::convert_decoded_function(partially_converted); + ngraph::onnx_import::detail::convert_decoded_function(partially_converted); } std::shared_ptr FrontEndONNX::decode(InputModel::Ptr model) const { @@ -123,14 +123,14 @@ bool FrontEndONNX::supported_impl(const std::vector>& v #endif if (model_stream.is_open()) { model_stream.seekg(0, model_stream.beg); - const bool is_valid_model = onnx_common::is_valid_model(model_stream); + const bool is_valid_model = ngraph::onnx_common::is_valid_model(model_stream); model_stream.close(); return is_valid_model; } if (ov::is_type(variants[0])) { const auto stream = ov::as_type_ptr(variants[0])->get(); StreamRewinder rwd{*stream}; - return onnx_common::is_valid_model(*stream); + return ngraph::onnx_common::is_valid_model(*stream); } return false; } diff --git a/ngraph/frontend/onnx/frontend/src/input_model.cpp b/ngraph/frontend/onnx/frontend/src/input_model.cpp index b61e8fe19c6cf9..9c0a11a34a0a09 100644 --- a/ngraph/frontend/onnx/frontend/src/input_model.cpp +++ b/ngraph/frontend/onnx/frontend/src/input_model.cpp @@ -5,12 +5,12 @@ #include "input_model.hpp" #include -#include +#include #include "place.hpp" -using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov; +using namespace ov::frontend; NGRAPH_SUPPRESS_DEPRECATED_START @@ -28,8 +28,10 @@ InputModelONNX::InputModelONNX(std::istream& model_stream) InputModelONNX::InputModelONNX(std::istream& model_stream, const std::string& path) : m_editor{std::make_shared(model_stream, path)} {} +#ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT InputModelONNX::InputModelONNX(std::istream& model_stream, const std::wstring& path) - : InputModelONNX(model_stream, file_util::wstring_to_string(path)) {} + : InputModelONNX(model_stream, ov::util::wstring_to_string(path)) {} +#endif std::vector InputModelONNX::get_inputs() const { const auto& inputs = m_editor->model_inputs(); diff --git a/ngraph/frontend/onnx/frontend/src/input_model.hpp b/ngraph/frontend/onnx/frontend/src/input_model.hpp index 59bf6cb2e53676..5db8f881308289 100644 --- a/ngraph/frontend/onnx/frontend/src/input_model.hpp +++ b/ngraph/frontend/onnx/frontend/src/input_model.hpp @@ -8,7 +8,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { class InputModelONNX : public InputModel { public: @@ -20,7 +20,9 @@ class InputModelONNX : public InputModel { // The path can be required even if the model is passed as a stream because it is necessary // for ONNX external data feature InputModelONNX(std::istream& model_stream, const std::string& path); +#ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT InputModelONNX(std::istream& model_stream, const std::wstring& path); +#endif std::vector get_inputs() const override; std::vector get_outputs() const override; @@ -54,7 +56,7 @@ class InputModelONNX : public InputModel { void extract_subgraph(const std::vector& inputs, const std::vector& outputs) override; private: - std::shared_ptr m_editor; + std::shared_ptr m_editor; }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/src/op/clip.cpp b/ngraph/frontend/onnx/frontend/src/op/clip.cpp index c39a53b89806f1..1f2f229fb1d0cb 100644 --- a/ngraph/frontend/onnx/frontend/src/op/clip.cpp +++ b/ngraph/frontend/onnx/frontend/src/op/clip.cpp @@ -9,6 +9,7 @@ #include "default_opset.hpp" #include "ngraph/builder/make_constant.hpp" +#include "ngraph/validation_util.hpp" #include "onnx_import/core/null_node.hpp" namespace ngraph { @@ -36,19 +37,19 @@ OutputVector clip(const Node& node) { Output max; // If second input is provided, assign to min input, otherwise set lowest - // numeric limit of double as min input. + // numeric limit of data type as min input. if (inputs.size() > 1 && !ngraph::op::is_null(inputs.at(1))) { min = inputs.at(1); } else { - min = builder::make_constant_from_double(data_type, Shape{}, std::numeric_limits::lowest()); + min = ngraph::get_constant_lowest_of_type(data_type); } // If third input is provided, assign to max input, otherwise set maximum - // numeric limit of double as max input. + // numeric limit of data type as max input. if (inputs.size() == 3 && !ngraph::op::is_null(inputs.at(2))) { max = inputs.at(2); } else { - max = builder::make_constant_from_double(data_type, Shape{}, std::numeric_limits::max()); + max = ngraph::get_constant_max_of_type(data_type); } const auto max_of_min_and_data = std::make_shared(min, data); diff --git a/ngraph/frontend/onnx/frontend/src/op/com.microsoft/attention.cpp b/ngraph/frontend/onnx/frontend/src/op/com.microsoft/attention.cpp new file mode 100644 index 00000000000000..f874f96bb3cf3e --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/com.microsoft/attention.cpp @@ -0,0 +1,548 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op/com.microsoft/attention.hpp" + +#include "default_opset.hpp" +#include "ngraph/builder/split.hpp" +#include "onnx_import/core/null_node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace detail { +namespace { +NodeVector split_to_QKV(const std::shared_ptr& node, + int64_t num_heads, + const std::vector& qkv_hidden_sizes); + +using NodeTuple = std::tuple, std::shared_ptr>; + +NodeTuple get_attention_mask(const OutputVector& op_inputs, bool unidirectional); + +std::shared_ptr attention_softmax(const OutputVector& op_inputs, + const std::shared_ptr& Q, + std::shared_ptr K, + std::shared_ptr V, + const std::shared_ptr& attention_mask, + const std::shared_ptr& bin_mask, + const std::shared_ptr& head_size, + bool unidirectional); + +std::shared_ptr get_present_state(const std::shared_ptr& K, + const std::shared_ptr& V, + const OutputVector& op_inputs); +} // namespace +} // namespace detail + +namespace set_1 { +OutputVector attention(const Node& node) { + auto nodes = node.get_ng_inputs(); + const auto& input = nodes[0]; + const auto& weights = nodes[1]; + const auto& bias = nodes[2]; + + // Attention is defined as: + // Q = input x Wq, K = input x Wk, V = input x Wv + // attention = softmax((Q x K') / sqrt(head_size)) x V + // + // In this operator, Wq, Wk and Wv are combined in a single input 'weights' along the second axis. + // So the approach here is to do a single big matrix multiply + // and then split the result into Q, K, V matrices + + auto matmul = std::make_shared(input, weights); + auto add = std::make_shared(matmul, bias); + + const auto num_heads = node.get_attribute_value("num_heads"); + const auto qkv_hidden_sizes = node.get_attribute_value>("qkv_hidden_sizes", {}); + const auto split_result = detail::split_to_QKV(add, num_heads, qkv_hidden_sizes); + + bool unidirectional = static_cast(node.get_attribute_value("unidirectional", 0)); + // mask has values either 0 or -10000 and its shape must be + // broadcastable to (batch_size, num_heads, sequence_length, past_sequence_length + sequence_length) + // so it can be added to Q x K' later + // past_sequence_length can be 0 if 'past' input is not available + std::shared_ptr attention_mask = nullptr, bin_mask = nullptr; + std::tie(attention_mask, bin_mask) = detail::get_attention_mask(nodes, unidirectional); + + const auto& Q = split_result[0]; + const auto& K = split_result[1]; + const auto& V = split_result[2]; + const auto& head_size = split_result[3]; + + // compute softmax((Q x K' + mask) / sqrt(head_size)) + const auto output = detail::attention_softmax(nodes, Q, K, V, attention_mask, bin_mask, head_size, unidirectional); + + // present = concat(K, V) if 'past' input is unavailable + // or + // present = concat(past, K, V) + const auto present = detail::get_present_state(K, V, nodes); + + return {output, present}; +} +} // namespace set_1 + +namespace detail { +namespace { + +std::shared_ptr get_dimensions(const std::shared_ptr& shape, + const std::vector& dims) { + static const auto zero = default_opset::Constant::create(element::i32, Shape{}, {0}); + const auto dims_const = default_opset::Constant::create(element::i32, Shape{dims.size()}, dims); + return std::make_shared(shape, dims_const, zero); +} + +std::shared_ptr get_dimensions(const std::shared_ptr& node, const std::vector& dims) { + return get_dimensions(std::make_shared(node), dims); +} + +std::shared_ptr get_hidden_size(const std::shared_ptr& node_shape) { + // node has shape (batch_size, sequence_length, 3 * hidden_size) + const auto zero = default_opset::Constant::create(element::i32, Shape{}, {0}); + const auto hidden_size_x3 = get_dimensions(node_shape, {2}); + const auto three = default_opset::Constant::create(element::i64, Shape{}, {3}); + const auto hidden_size = std::make_shared(hidden_size_x3, three); + return hidden_size; +} + +NodeVector split_to_QKV(const std::shared_ptr& node, + int64_t num_heads, + const std::vector& qkv_hidden_sizes) { + OutputVector split; + std::shared_ptr head_size = nullptr; + const auto& node_type = node->get_element_type(); + const auto node_shape = std::make_shared(node); + // node has shape (batch_size, sequence_length, 3 * hidden_size) + // fetch the first two dimensions + const auto batch_size_seq_len = get_dimensions(node_shape, {0, 1}); + const auto num_heads_node = default_opset::Constant::create(element::i64, Shape{1}, {num_heads}); + if (qkv_hidden_sizes.size() == 0) { + const auto hidden_size = get_hidden_size(node_shape); + // head_size = hidden_size / num_heads + head_size = std::make_shared(hidden_size, num_heads_node); + // split the node into 3 even parts Q, K, V with shape (batch_size, sequence_len, hidden_size) + split = ngraph::builder::opset1::split(node, 3, 2); + // and reshape each part to new shape (batch_size, sequence_len, num_heads, head_size) + auto new_shape = + std::make_shared(NodeVector{batch_size_seq_len, num_heads_node, head_size}, 0); + for (size_t i = 0; i < split.size(); i++) { + split[i] = std::make_shared(split[i], new_shape, false); + } + head_size = std::make_shared(head_size, node_type); + } else { + // in this case, weights have shape + // (input_hidden_size, qkv_hidden_sizes[0] + qkv_hidden_sizes[1] + qkv_hidden_sizes[2]) + // so user specified hidden_sizes for Q, K and V + NGRAPH_CHECK(qkv_hidden_sizes.size() == 3, "qkv_hidden_sizes attribute needs to have 3 values"); + NGRAPH_CHECK(qkv_hidden_sizes[0] == qkv_hidden_sizes[1], + "qkv_hidden_sizes first element should be same as the second"); + // split the node into 3 parts Q, K, V with shapes + // Q: (batch_size, sequence_len, qkv_hidden_sizes[0]) + // K: (batch_size, sequence_len, qkv_hidden_sizes[1]) + // V: (batch_size, sequence_len, qkv_hidden_sizes[2]) + split = ngraph::builder::opset1::split(node, qkv_hidden_sizes, 2); + // and reshape each part to new shape (batch_size, sequence_len, num_heads, head_size) + for (size_t i = 0; i < split.size(); i++) { + auto new_shape = std::make_shared( + NodeVector{batch_size_seq_len, + num_heads_node, + default_opset::Constant::create(element::i64, Shape{1}, {qkv_hidden_sizes[i] / num_heads})}, + 0); + split[i] = std::make_shared(split[i], new_shape, false); + } + float head_size_val = qkv_hidden_sizes[0] > 0 ? static_cast(qkv_hidden_sizes[0]) / num_heads + : static_cast(qkv_hidden_sizes[2]) / num_heads; + head_size = default_opset::Constant::create(node_type, Shape{1}, {head_size_val}); + } + + // transpose Q, K and V to (batch_size, num_heads, sequence_len, head_size) + auto perm = default_opset::Constant::create(element::i64, Shape{4}, {0, 2, 1, 3}); + auto Q = std::make_shared(split[0], perm); + auto K = std::make_shared(split[1], perm); + auto V = std::make_shared(split[2], perm); + + return {Q, K, V, head_size}; +} + +// This function handles the case when mask_index rank is 1 - so its shape is (batch_size) or (2 * batch_size). +// The returned mask consists of 0 and -10000 and has shape (batch_size, 1, 1, all_seq_len). 'mask_index' input contains +// positions from where the -10000 values start appearing in the final mask per batch (if shape is (batch_size)) or if +// shape is (2 * batch_size), user can define two ranges of -10000 values appearing in the final mask. For example: +// +// batch_size = 3, all_seq_len = 5, mask_index = [2, 4, 3] +// the function returns following mask with shape (3, 1, 1, 5): +// 0, 0, -10000, -10000, -10000 +// 0, 0, 0, 0, -10000 +// 0, 0, 0, -10000, -10000 +// +// e.g., for batch = 2, -10000 values appear within range [mask_index[2]:5] (or [3:5]) +// +// Another example, but with mask_index shape (2 * batch_size) +// batch_size = 3, all_seq_len = 5, mask_index = [2, 4, 3, 1, 2, 2] +// the function returns following mask with shape (3, 1, 1, 5): +// -10000, 0, -10000, -10000, -10000 +// -10000, -10000, 0, 0, -10000 +// -10000, -10000, 0, -10000, -10000 +// +// e.g., for batch = 1, -10000 values appear within two ranges [0, mask_index[4]] and [mask_index[1]:5] (or [0:2],[4:5]) +// +// +// This is how it's done with nGraph operations: +// +// First the 'base' is generated by range + broadcast: +// base = range(0, all_seq_len) +// base = broadcast(base, shape=(batch_size, all_seq_len)) +// +// With batch_size = 3 and all_seq_len = 5, 'base' looks as follows: +// [[0, 1, 2, 3, 4], +// [0, 1, 2, 3, 4], +// [0, 1, 2, 3, 4]] +// +// Next step is to reshape mask_index: +// mask_index = reshape(mask_index, shape=(-1, batch_size)) +// +// With the second example above (mask_index = [2, 4, 3, 1, 2, 2]), now it looks like: +// mask_index = [[2, 4, 3], +// [1, 2, 2]] +// +// Now we get the first row and reshape it to (batch_size, 1) to have indices laid out in column: +// tail_range_indices = gather(mask_index, indices=[0], axis=0) # tail_range_indices = [2, 4, 3] +// tail_range_indices = reshape(tail_range_indices, shape=(batch_size, 1) +// # tail_range_indices = [[2], +// # [4], +// # [3]] +// +// Then the base is compared with the indices +// tail_range_mask = base >= tail_range_indices +// +// Thanks to autobroadcast in elementwise operators, the comparison conceptually happens between: +// [[0, 1, 2, 3, 4], [[2, 2, 2, 2, 2], +// [0, 1, 2, 3, 4], >= [4, 4, 4, 4, 4], +// [0, 1, 2, 3, 4]] [3, 3, 3, 3, 3]] +// +// and the result is: +// [[0, 0, 1, 1, 1], +// [0, 0, 0, 0, 1], +// [0, 0, 0, 1, 1]] +// +// So we get the final tail range mask by multiplying this by -10000 +// +// Similarly we process with head range - we fetch the second row from reshaped mask_index, +// compare it with 'base' (but with 'Less' operator instead of 'GreaterEqual') and combine it +// with tail_range_mask. +// +// Handling both mask_index variants (so (batch_size) and (2 * batch_size)) is tricky since we don't +// know its dimensions upfront. So we compute both variants and use Select operator to select +// the right one in the runtime (unless it gets constantfolded before). +std::shared_ptr attention_mask_from_indices(const Output& mask_index, + const element::Type_t& type, + const std::shared_ptr& batch_size, + const std::shared_ptr& all_seq_len) { + const auto zero = default_opset::Constant::create(element::i64, Shape{}, {0}); + const auto one = default_opset::Constant::create(element::i64, Shape{}, {1}); + const auto stop = std::make_shared(all_seq_len, zero); + std::shared_ptr base = + std::make_shared(zero, stop, one, mask_index.get_element_type()); + const auto target_shape = std::make_shared(NodeVector{batch_size, all_seq_len}, 0); + // broadcast 'base' to (batch_size, all_seq_len) + base = std::make_shared(base, target_shape); + const auto indices_shape = std::make_shared( + NodeVector{default_opset::Constant::create(element::i64, Shape{1}, {-1}), batch_size}, + 0); + std::shared_ptr indices = std::make_shared(mask_index, indices_shape, false); + // fetch first row from indices + std::shared_ptr tail_range_indices = std::make_shared(indices, zero, zero); + tail_range_indices = + std::make_shared(tail_range_indices, + default_opset::Constant::create(element::i32, Shape{2}, {-1, 1}), + false); + const auto greater_eq = std::make_shared(base, tail_range_indices); + std::shared_ptr tail_range_mask = + std::make_shared(std::make_shared(greater_eq, type), + default_opset::Constant::create(type, Shape{}, {-10000})); + tail_range_mask = + std::make_shared(tail_range_mask, + default_opset::Constant::create(element::i64, Shape{2}, {1, 2})); + + const auto gather_index = + std::make_shared(default_opset::Constant::create(element::i64, Shape{}, {1}), + get_dimensions(indices, {0})); + // fetch indices from the second row (or first if not available) + std::shared_ptr head_range_indices = + std::make_shared(indices, gather_index, zero); + head_range_indices = + std::make_shared(head_range_indices, + default_opset::Constant::create(element::i32, Shape{2}, {-1, 1}), + false); + const auto less = std::make_shared(base, head_range_indices); + std::shared_ptr mask = std::make_shared(less, greater_eq); + mask = std::make_shared(std::make_shared(mask, type), + default_opset::Constant::create(type, Shape{}, {-10000})); + // reshape from (batch_size, all_seq_len) to (batch_size, 1, 1, all_seq_len) + mask = std::make_shared(mask, + default_opset::Constant::create(element::i64, Shape{2}, {1, 2})); + + const auto mask_index_first_dim = get_dimensions(mask_index.get_node_shared_ptr(), {0}); + // compare mask_index.shape[0] with batch_size value + // if they're equal - select tail_range_mask + // else select full mask + mask = std::make_shared( + std::make_shared(batch_size, mask_index_first_dim), + tail_range_mask, + mask); + + return mask; +} + +// Prepare unidirectional_mask like it's done in +// https://github.com/microsoft/onnxruntime/blob/851554536ca8185b3413ee57449ea5ac93370193/onnxruntime/contrib_ops/cpu/bert/attention_helper.h#L87-L96 +// +// Function returns two masks - one attention mask with values 0 or -10000 with shape (seq_len, all_seq_len), +// the second one is a binary mask where it has 0 on positions where attention mask has -10000 values and 1 otherwise. +// +// For example: +// seq_len = 4, all_seq_len = 7, past_seq_len = 3. Returned attention mask has shape (4, 7) and contains: +// 0 0 0 0 -10000 -10000 -10000 +// 0 0 0 0 0 -10000 -10000 +// 0 0 0 0 0 0 -10000 +// 0 0 0 0 0 0 0 +// +// Returned binary mask has the shape (4, 7) and following values: +// 1 1 1 1 0 0 0 +// 1 1 1 1 1 0 0 +// 1 1 1 1 1 1 0 +// 1 1 1 1 1 1 1 +// +// Binary mask is used later before softmax to achieve +// https://github.com/microsoft/onnxruntime/blob/851554536ca8185b3413ee57449ea5ac93370193/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h#L158-L166 +// +// The approach used to generate those masks is similar to one from attention_mask_from_indices function (see comments +// there). +NodeTuple unidirectional_mask(const element::Type_t& type, + const std::shared_ptr& seq_len, + const std::shared_ptr& all_seq_len, + const std::shared_ptr& past_seq_len) { + const auto zero = default_opset::Constant::create(element::i64, Shape{}, {0}); + const auto one = default_opset::Constant::create(element::i64, Shape{}, {1}); + const auto stop = std::make_shared(all_seq_len, zero); + std::shared_ptr bin_mask = std::make_shared(zero, stop, one, element::i32); + auto target_shape = std::make_shared(NodeVector{seq_len, all_seq_len}, 0); + bin_mask = std::make_shared(bin_mask, target_shape); + auto start = + std::make_shared(std::make_shared(past_seq_len, one), zero); + auto end = std::make_shared(std::make_shared(all_seq_len, one), zero); + auto indices = std::make_shared( + std::make_shared(start, end, one, element::i32), + default_opset::Constant::create(element::i32, Shape{1}, {1})); + bin_mask = std::make_shared(bin_mask, indices); + std::shared_ptr attention_mask = + std::make_shared(std::make_shared(bin_mask, type), + default_opset::Constant::create(type, Shape{}, {-10000})); + bin_mask = std::make_shared(std::make_shared(bin_mask), type); + return NodeTuple{attention_mask, bin_mask}; +} + +// This is the easiest variant of 'mask_index' input - the input consists of 0 or 1 values +// and we transform them to: +// * -10000 for positions where mask_index == 0 +// * 0 for positions where mask_index == 1 +// +// It handles mask_index with shapes: +// (batch_size, past_sequence_length + sequence_length) or +// (batch_size, sequence_length, past_sequence_length + sequence_length) +// +// Shape (batch_size, 1, max_sequence_length, max_sequence_length) is not supported in onnxruntime: +// https://github.com/microsoft/onnxruntime/blob/851554536ca8185b3413ee57449ea5ac93370193/onnxruntime/contrib_ops/cpu/bert/attention_helper.h#L78 +std::shared_ptr raw_mask(const Output& mask_index, + Dimension::value_type mask_rank, + const element::Type_t& type) { + std::shared_ptr mask = std::make_shared(mask_index, type); + mask = std::make_shared(mask, type); + mask = std::make_shared(default_opset::Constant::create(type, Shape{}, {1}), mask); + mask = std::make_shared(mask, default_opset::Constant::create(type, Shape{}, {-10000})); + switch (mask_rank) { + // Handle mask_index with (batch_size, past_sequence_length + sequence_length) shape + // Reshape it to (batch_size, 1, 1, past_sequence_length + sequence_length) + case 2: + mask = std::make_shared( + mask, + default_opset::Constant::create(element::i64, Shape{4}, {0, 1, 1, -1}), + true); + break; + // Handle mask_index with (batch_size, sequence_length, past_sequence_length + sequence_length) shape + // Reshape it to (batch_size, 1, sequence_length, past_sequence_length + sequence_length) + case 3: + mask = std::make_shared( + mask, + default_opset::Constant::create(element::i64, Shape{4}, {0, 1, 0, -1}), + true); + break; + } + return mask; +} + +bool is_past_input_available(const OutputVector& op_inputs) { + return op_inputs.size() > 4 && !ngraph::op::is_null(op_inputs[4]); +} + +NodeTuple get_attention_mask(const OutputVector& op_inputs, bool unidirectional) { + const auto zero = default_opset::Constant::create(element::i64, Shape{1}, {0}); + const auto one = default_opset::Constant::create(element::i64, Shape{1}, {1}); + + std::shared_ptr past_seq_len; + // get the value of past_sequence_length + if (is_past_input_available(op_inputs)) { + const auto& past = op_inputs[4]; + // 'past' node has shape (2, batch_size, num_heads, past_sequence_length, head_size) + past_seq_len = get_dimensions(past.get_node_shared_ptr(), {3}); + } else { + past_seq_len = zero; + } + + // 'input' node has shape (batch_size, sequence_length, input_hidden_size) + auto input_shape = std::make_shared(op_inputs[0]); + auto seq_len = get_dimensions(input_shape, {1}); + auto all_seq_len = std::make_shared(seq_len, past_seq_len); + const auto& type = op_inputs[0].get_element_type(); + std::shared_ptr attention_mask = nullptr; + std::shared_ptr bin_mask = nullptr; + if (unidirectional) { + std::tie(attention_mask, bin_mask) = unidirectional_mask(type, seq_len, all_seq_len, past_seq_len); + } + if (op_inputs.size() > 3 && !ngraph::op::is_null(op_inputs[3])) { + const auto& mask_index = op_inputs[3]; + NGRAPH_CHECK(mask_index.get_element_type() == element::i32, "'mask_index' type must be int32"); + auto batch_size = get_dimensions(input_shape, {0}); + const auto mask_rank = mask_index.get_partial_shape().rank(); + NGRAPH_CHECK(mask_rank.is_static(), "'mask_index' rank must be static"); + auto mask_rank_val = mask_rank.get_length(); + std::shared_ptr mask; + if (mask_rank_val == 1) { + // case when mask_index has shape (batch_size) or (2 * batch_size) + // so it contains positions that specify how mask should be generated + mask = attention_mask_from_indices(mask_index, type, batch_size, all_seq_len); + } else if (mask_rank_val < 4) { + mask = raw_mask(mask_index, mask_rank.get_length(), type); + } else { + NGRAPH_CHECK(false, "mask_index with rank " + std::to_string(mask_rank_val) + " is not supported"); + } + // add the mask with unidirectional mask if available + if (attention_mask) { + attention_mask = std::make_shared(attention_mask, mask); + } else { + attention_mask = mask; + } + } + return NodeTuple{attention_mask, bin_mask}; +} + +// Compute softmax(Q x K' / sqrt(head_size)) x V +std::shared_ptr attention_softmax(const OutputVector& op_inputs, + const std::shared_ptr& Q, + std::shared_ptr K, + std::shared_ptr V, + const std::shared_ptr& attention_mask, + const std::shared_ptr& bin_mask, + const std::shared_ptr& head_size, + bool unidirectional) { + auto zero = default_opset::Constant::create(element::i64, Shape{}, {0}); + if (is_past_input_available(op_inputs)) { + // concat past K and V with present ones + const auto& past = op_inputs[4]; + // 'past' input has two matrices K and V with shape (1, batch_size, num_heads, past_sequence_length, head_size) + // concatenated along first axis to a single + // (2, batch_size, num_heads, past_sequence_length + sequence_length, head_size) + // so we need to split it into two parts, remove first dimension from each part and concatenate first part + // with current K and second part with current V + const auto split = ngraph::builder::opset1::split(past, 2, 0); + const auto past_K = std::make_shared(split[0], zero); + K = std::make_shared(NodeVector{past_K, K}, 2); + const auto past_V = std::make_shared(split[1], zero); + V = std::make_shared(NodeVector{past_V, V}, 2); + } + // perform Q x K' + std::shared_ptr softmax_input = std::make_shared(Q, K, false, true); + // Q x K' + mask + if (attention_mask) { + if (unidirectional) { + // Perform the equivalent of + // https://github.com/microsoft/onnxruntime/blob/851554536ca8185b3413ee57449ea5ac93370193/onnxruntime/contrib_ops/cpu/bert/attention_cpu_base.h#L158-L166 + // For positions where unidirectional_mask has -10000 values - attention_mask is moved to softmax input + softmax_input = std::make_shared(softmax_input, bin_mask); + } + softmax_input = std::make_shared(softmax_input, attention_mask); + } + const auto sqrt = std::make_shared(head_size); + // (Q x K' + mask) / sqrt(head_size) + softmax_input = std::make_shared(softmax_input, sqrt); + // handle 'extra_add' input + if (op_inputs.size() > 5 && !ngraph::op::is_null(op_inputs[5])) { + NGRAPH_CHECK(!is_past_input_available(op_inputs), + "Cannot use both 'past' and 'extra_add' inputs in the same node"); + const auto& extra_add = op_inputs[5]; + softmax_input = std::make_shared(softmax_input, extra_add); + } + // softmax((Q x K' + mask) / sqrt(head_size)) + const auto softmax = std::make_shared(softmax_input, 3); + + // softmax((Q x K' + mask) / sqrt(head_size)) x V + std::shared_ptr output = std::make_shared(softmax, V); + // transpose the result from (batch_size, num_heads, sequence_length, head_size) + // to (batch_size, sequence_length, num_heads, head_size) + const auto perm = default_opset::Constant::create(element::i64, Shape{4}, {0, 2, 1, 3}); + output = std::make_shared(output, perm); + auto new_shape = default_opset::Constant::create(element::i32, Shape{3}, {0, 0, -1}); + // reshape the result from (batch_size, sequence_length, num_heads, head_size) to (batch_size, sequence_length, + // num_heads * head_size) + output = std::make_shared(output, new_shape, true); + + return output; +} + +// Make present state from K and V matrices by reshaping them from: +// (batch_size, num_heads, sequence_length, head_size) to (1, batch_size, num_heads, sequence_length, head_size) +// and concatenating them along first axis to make 'present' output. +// If fifth input ('past') is available, it gets concatenated with 'present' output along fourth axis. +std::shared_ptr get_present_state(const std::shared_ptr& K, + const std::shared_ptr& V, + const OutputVector& op_inputs) { + auto zero = default_opset::Constant::create(element::i64, Shape{1}, {0}); + // expand K shape (batch_size, num_heads, sequence_length, head_size) to + // (1, batch_size, num_heads, sequence_length, head_size) + auto K_unsqueezed = std::make_shared(K, zero); + // similarly expand V shape + auto V_unsqueezed = std::make_shared(V, zero); + + // add padding in case K and V have different shapes (it happens when used provided uneven qkv_hidden_sizes) + // if the shapes are equal (so padding will be zero), Pad gets eliminated in NopElimination pass + const auto K_shape = std::make_shared(K_unsqueezed); + const auto V_shape = std::make_shared(V_unsqueezed); + const auto K_pads_end = + std::make_shared(std::make_shared(V_shape, K_shape), zero); + const auto V_pads_end = + std::make_shared(std::make_shared(K_shape, V_shape), zero); + const auto pads_begin = + std::make_shared(zero, std::make_shared(K_shape)); + const auto K_padded = + std::make_shared(K_unsqueezed, pads_begin, K_pads_end, ngraph::op::PadMode::CONSTANT); + const auto V_padded = + std::make_shared(V_unsqueezed, pads_begin, V_pads_end, ngraph::op::PadMode::CONSTANT); + + // concat key and value tensors along first axis to make 'present' state + // after that operation, 'present' has shape (2, batch_size, num_heads, sequence_length, head_size) + std::shared_ptr present = std::make_shared(NodeVector{K_padded, V_padded}, 0); + if (is_past_input_available(op_inputs)) { + const auto& past = op_inputs[4]; + // concat 'past' to 'present' output along fourth axis + // after that operation, 'present' has shape: + // (2, batch_size, num_heads, past_sequence_length + sequence_length, head_size) + present = std::make_shared(OutputVector{past, present}, 3); + } + return present; +} +} // namespace +} // namespace detail +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/com.microsoft/attention.hpp b/ngraph/frontend/onnx/frontend/src/op/com.microsoft/attention.hpp new file mode 100644 index 00000000000000..50ecbd82ef57fe --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/com.microsoft/attention.hpp @@ -0,0 +1,17 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "onnx_import/core/node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { +OutputVector attention(const Node& node); +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/max_pool.cpp b/ngraph/frontend/onnx/frontend/src/op/max_pool.cpp index 18004d6bf43739..df02d83943e695 100644 --- a/ngraph/frontend/onnx/frontend/src/op/max_pool.cpp +++ b/ngraph/frontend/onnx/frontend/src/op/max_pool.cpp @@ -25,8 +25,14 @@ OutputVector max_pool(const Node& node) { } // namespace set_1 +namespace set_8 { +OutputVector max_pool(const Node& node) { + return pooling::PoolingFactory(node).make_max_pool_with_indices(); +} +} // namespace set_8 + } // namespace op } // namespace onnx_import -} // namespace ngraph \ No newline at end of file +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/max_pool.hpp b/ngraph/frontend/onnx/frontend/src/op/max_pool.hpp index 82c10cc45c5a6f..b7fda5e4058c17 100644 --- a/ngraph/frontend/onnx/frontend/src/op/max_pool.hpp +++ b/ngraph/frontend/onnx/frontend/src/op/max_pool.hpp @@ -23,6 +23,19 @@ OutputVector max_pool(const Node& node); } // namespace set_1 +namespace set_8 { +/// +/// \brief Convert ONNX MaxPool operation to an nGraph node. +/// +/// \param node The ONNX node object representing this operation. +/// +/// \return The vector containing Ngraph nodes producing output of ONNX MaxPool +/// operation. +/// +OutputVector max_pool(const Node& node); + +} // namespace set_8 + } // namespace op } // namespace onnx_import diff --git a/ngraph/frontend/onnx/frontend/src/op/random_normal.cpp b/ngraph/frontend/onnx/frontend/src/op/random_normal.cpp new file mode 100644 index 00000000000000..574a44f177cece --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_normal.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "utils/random_normal.hpp" + +#include "exceptions.hpp" +#include "ngraph/shape.hpp" +#include "utils/common.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_normal(const Node& node) { + CHECK_VALID_NODE(node, node.has_attribute("shape"), "RandomNormal operator must specify a 'shape' attribute."); + + const auto dtype = + node.get_attribute_value("dtype", static_cast(ONNX_NAMESPACE::TensorProto_DataType_FLOAT)); + const auto target_type = common::get_ngraph_element_type(dtype); + + const auto mean = node.get_attribute_value("mean", 0.0f); + const auto scale = node.get_attribute_value("scale", 1.0f); + const auto seed = node.get_attribute_value("seed", 0); + + const auto shape_dims = node.get_attribute_value>("shape"); + const auto shape = default_opset::Constant::create(element::i64, {shape_dims.size()}, shape_dims); + + return detail::make_random_normal(shape, target_type, mean, scale, seed); +} + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_normal.hpp b/ngraph/frontend/onnx/frontend/src/op/random_normal.hpp new file mode 100644 index 00000000000000..80e95e34dcb9fe --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_normal.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/node.hpp" +#include "onnx_import/core/node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_normal(const Node& node); + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_normal_like.cpp b/ngraph/frontend/onnx/frontend/src/op/random_normal_like.cpp new file mode 100644 index 00000000000000..5648643c79b6b8 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_normal_like.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "ngraph/shape.hpp" +#include "op/random_uniform_like.hpp" +#include "utils/common.hpp" +#include "utils/random_normal.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_normal_like(const Node& node) { + const auto input = node.get_ng_inputs().at(0); + + ngraph::element::Type target_type; + if (node.has_attribute("dtype")) { + const auto dtype = node.get_attribute_value("dtype"); + target_type = common::get_ngraph_element_type(dtype); + } else { + target_type = input.get_element_type(); + } + + const auto shape = std::make_shared(input); + const auto mean = node.get_attribute_value("mean", 0.0f); + const auto scale = node.get_attribute_value("scale", 1.0f); + const auto seed = node.get_attribute_value("seed", 0.0f); + + return detail::make_random_normal(shape, target_type, mean, scale, seed); +} + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_normal_like.hpp b/ngraph/frontend/onnx/frontend/src/op/random_normal_like.hpp new file mode 100644 index 00000000000000..4d608bd61dda15 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/op/random_normal_like.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/node.hpp" +#include "onnx_import/core/node.hpp" + +namespace ngraph { +namespace onnx_import { +namespace op { +namespace set_1 { + +OutputVector random_normal_like(const Node& node); + +} // namespace set_1 +} // namespace op +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp b/ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp index cf01a8edef8677..da14edbe18d6e5 100644 --- a/ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp +++ b/ngraph/frontend/onnx/frontend/src/op/random_uniform.cpp @@ -23,7 +23,7 @@ OutputVector random_uniform(const Node& node) { node.get_attribute_value("dtype", static_cast(ONNX_NAMESPACE::TensorProto_DataType_FLOAT)); const auto high = node.get_attribute_value("high", 1.0f); const auto low = node.get_attribute_value("low", 0.0f); - const auto seed = node.get_attribute_value("seed", 0); + const auto seed = node.get_attribute_value("seed", 0.0f); const auto shape = node.get_attribute_value>("shape"); const auto target_shape_const = default_opset::Constant::create(ngraph::element::i64, Shape{shape.size()}, shape); @@ -32,19 +32,17 @@ OutputVector random_uniform(const Node& node) { const auto target_type = common::get_ngraph_element_type(dtype); const uint64_t global_seed = 0; + const auto seed_uint64 = static_cast(seed * 1000); return {std::make_shared(target_shape_const, low_const, high_const, target_type, global_seed, - seed)}; + seed_uint64)}; } } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp b/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp index 0ca673622478b4..08835a0429dec8 100644 --- a/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp +++ b/ngraph/frontend/onnx/frontend/src/op/random_uniform_like.cpp @@ -18,7 +18,7 @@ namespace set_1 { OutputVector random_uniform_like(const Node& node) { OutputVector inputs{node.get_ng_inputs()}; - auto input = inputs.at(0); + const auto input = inputs.at(0); ngraph::element::Type target_type; if (node.has_attribute("dtype")) { @@ -32,25 +32,23 @@ OutputVector random_uniform_like(const Node& node) { const auto high = node.get_attribute_value("high", 1.0f); const auto low = node.get_attribute_value("low", 0.0f); - const auto seed = node.get_attribute_value("seed", 0); + const auto seed = node.get_attribute_value("seed", 0.f); const auto high_const = default_opset::Constant::create(ngraph::element::f32, Shape{1}, {high}); const auto low_const = default_opset::Constant::create(ngraph::element::f32, Shape{1}, {low}); const uint64_t global_seed = 0; + const auto seed_uint64 = static_cast(seed * 1000); return {std::make_shared(target_shape, low_const, high_const, target_type, global_seed, - seed)}; + seed_uint64)}; } } // namespace set_1 - } // namespace op - } // namespace onnx_import - } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp b/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp index 93badc431fa806..7d12281d44674e 100644 --- a/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp +++ b/ngraph/frontend/onnx/frontend/src/ops_bridge.cpp @@ -31,6 +31,7 @@ #include "op/cast_like.hpp" #include "op/ceil.hpp" #include "op/clip.hpp" +#include "op/com.microsoft/attention.hpp" #include "op/com.microsoft/bias_gelu.hpp" #include "op/com.microsoft/embed_layer_normalization.hpp" #include "op/com.microsoft/skip_layer_normalization.hpp" @@ -116,6 +117,8 @@ #include "op/qlinear_conv.hpp" #include "op/qlinear_matmul.hpp" #include "op/quantize_linear.hpp" +#include "op/random_normal.hpp" +#include "op/random_normal_like.hpp" #include "op/random_uniform.hpp" #include "op/random_uniform_like.hpp" #include "op/range.hpp" @@ -359,6 +362,7 @@ OperatorsBridge::OperatorsBridge() { REGISTER_OPERATOR("MatMulInteger", 1, matmul_integer); REGISTER_OPERATOR("MatMul", 1, matmul); REGISTER_OPERATOR("MaxPool", 1, max_pool); + REGISTER_OPERATOR("MaxPool", 8, max_pool); REGISTER_OPERATOR("Max", 1, max); REGISTER_OPERATOR("Max", 8, max); REGISTER_OPERATOR("Mean", 1, mean); @@ -384,6 +388,8 @@ OperatorsBridge::OperatorsBridge() { REGISTER_OPERATOR("QuantizeLinear", 1, quantize_linear); REGISTER_OPERATOR("QuantizeLinear", 13, quantize_linear); REGISTER_OPERATOR("Range", 1, range); + REGISTER_OPERATOR("RandomNormal", 1, random_normal); + REGISTER_OPERATOR("RandomNormalLike", 1, random_normal_like); REGISTER_OPERATOR("RandomUniform", 1, random_uniform); REGISTER_OPERATOR("RandomUniformLike", 1, random_uniform_like); REGISTER_OPERATOR("Reciprocal", 1, reciprocal); @@ -485,6 +491,7 @@ OperatorsBridge::OperatorsBridge() { REGISTER_OPERATOR_WITH_DOMAIN(OPENVINO_ONNX_DOMAIN, "PriorBoxClustered", 1, prior_box_clustered); REGISTER_OPERATOR_WITH_DOMAIN(OPENVINO_ONNX_DOMAIN, "Swish", 1, swish); + REGISTER_OPERATOR_WITH_DOMAIN(MICROSOFT_DOMAIN, "Attention", 1, attention); REGISTER_OPERATOR_WITH_DOMAIN(MICROSOFT_DOMAIN, "BiasGelu", 1, bias_gelu); REGISTER_OPERATOR_WITH_DOMAIN(MICROSOFT_DOMAIN, "EmbedLayerNormalization", 1, embed_layer_normalization); REGISTER_OPERATOR_WITH_DOMAIN(MICROSOFT_DOMAIN, "SkipLayerNormalization", 1, skip_layer_normalization); diff --git a/ngraph/frontend/onnx/frontend/src/place.cpp b/ngraph/frontend/onnx/frontend/src/place.cpp index c8f20e65add056..b143edbf32f6e9 100644 --- a/ngraph/frontend/onnx/frontend/src/place.cpp +++ b/ngraph/frontend/onnx/frontend/src/place.cpp @@ -6,8 +6,8 @@ #include -using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov; +using namespace ov::frontend; PlaceInputEdgeONNX::PlaceInputEdgeONNX(const onnx_editor::InputEdge& edge, std::shared_ptr editor) diff --git a/ngraph/frontend/onnx/frontend/src/place.hpp b/ngraph/frontend/onnx/frontend/src/place.hpp index a9d7b2a78dd4be..79344974e0f3bc 100644 --- a/ngraph/frontend/onnx/frontend/src/place.hpp +++ b/ngraph/frontend/onnx/frontend/src/place.hpp @@ -9,7 +9,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { class PlaceInputEdgeONNX : public Place { public: @@ -126,4 +126,4 @@ class PlaceOpONNX : public Place { std::shared_ptr m_editor; }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/onnx/frontend/src/utils/arg_min_max_factory.cpp b/ngraph/frontend/onnx/frontend/src/utils/arg_min_max_factory.cpp index 5edcf2f4267a66..e32dd2bbf41a78 100644 --- a/ngraph/frontend/onnx/frontend/src/utils/arg_min_max_factory.cpp +++ b/ngraph/frontend/onnx/frontend/src/utils/arg_min_max_factory.cpp @@ -53,11 +53,17 @@ std::shared_ptr ArgMinMaxFactory::make_topk_subgraph(default_opset // res_index = dims_on_axis - topk->output(1) = 6 - 3 = 3 // result = res_index - 1 = 3 - 1 = 2 - const auto axis_node = default_opset::Constant::create(ngraph::element::i64, Shape{1}, {m_axis}); + const int64_t normalized_axis = + normalize_axis(m_input_node.get_node(), m_axis, m_input_node.get_partial_shape().rank()); + + const auto axis_node = default_opset::Constant::create(ngraph::element::i64, Shape{1}, {normalized_axis}); const auto reverse = std::make_shared(m_input_node, axis_node, opset1::Reverse::Mode::INDEX); - const auto topk = - std::make_shared(reverse, k_node, m_axis, mode, default_opset::TopK::SortType::NONE); + const auto topk = std::make_shared(reverse, + k_node, + normalized_axis, + mode, + default_opset::TopK::SortType::NONE); const auto data_shape = std::make_shared(m_input_node); const auto dims_on_axis = std::make_shared( diff --git a/ngraph/frontend/onnx/frontend/src/utils/common.cpp b/ngraph/frontend/onnx/frontend/src/utils/common.cpp index e0d5aea94cc056..691addbe8611d7 100644 --- a/ngraph/frontend/onnx/frontend/src/utils/common.cpp +++ b/ngraph/frontend/onnx/frontend/src/utils/common.cpp @@ -43,13 +43,7 @@ const ngraph::element::Type& get_ngraph_element_type(int64_t onnx_type) { case ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16: return element::bf16; } -#ifdef NGRAPH_USE_PROTOBUF_LITE throw ngraph_error("unsupported element type"); -#else - throw ngraph_error( - "unsupported element type: " + - ONNX_NAMESPACE::TensorProto_DataType_Name(static_cast(onnx_type))); -#endif } std::shared_ptr get_monotonic_range_along_node_rank(const Output& value, diff --git a/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.cpp b/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.cpp index fff79f9988f948..4984698bbacd7c 100644 --- a/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.cpp +++ b/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.cpp @@ -14,6 +14,27 @@ namespace ngraph { namespace onnx_import { namespace pooling { + +namespace { +std::shared_ptr transposition_axis_order(const Rank& input_rank) { + NGRAPH_CHECK(input_rank.is_static(), + "Generating column-major MaxPool results is supported only for inputs with static rank."); + + const auto rank = static_cast(input_rank.get_length()); + + std::vector axes(rank); + std::iota(axes.begin(), axes.end(), 0); + std::reverse(axes.begin() + 2, axes.end()); + + return std::make_shared(element::i32, Shape{rank}, axes); +} + +std::shared_ptr identity(Output node_output) { + const auto zero = default_opset::Constant::create(node_output.get_element_type(), {}, {0}); + return std::make_shared(node_output, zero); +} +} // namespace + PoolingFactory::PoolingFactory(const Node& node) : m_onnx_node{node}, m_inputs{node.get_ng_inputs()}, @@ -27,6 +48,7 @@ PoolingFactory::PoolingFactory(const Node& node) const CoordinateDiff& padding_below{paddings.first}; m_padding_below = Shape{std::begin(padding_below), std::end(padding_below)}; m_padding_above = Shape{std::begin(padding_above), std::end(padding_above)}; + m_storage_order = static_cast(node.get_attribute_value("storage_order", 0)); } OutputVector PoolingFactory::make_avg_pool() const { @@ -50,6 +72,26 @@ OutputVector PoolingFactory::make_max_pool() const { m_rounding_type, m_auto_pad)}; } + +OutputVector PoolingFactory::make_max_pool_with_indices() const { + const auto max_pool = std::make_shared(m_inputs.at(0), + m_strides, + m_dilations, + m_padding_below, + m_padding_above, + m_kernel_shape, + m_rounding_type, + m_auto_pad); + if (m_storage_order == StorageOrder::COLUMN_MAJOR) { + const auto transposition_axes = transposition_axis_order(m_inputs.at(0).get_partial_shape().rank()); + const auto transposed_indices = + std::make_shared(max_pool->output(1), transposition_axes); + + return {max_pool->output(0), transposed_indices}; + } else { + return {identity(max_pool->output(0)), identity(max_pool->output(1))}; + } +} } // namespace pooling } // namespace onnx_import } // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.hpp b/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.hpp index 133f21a6c36194..4e4f750db2528b 100644 --- a/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.hpp +++ b/ngraph/frontend/onnx/frontend/src/utils/pooling_factory.hpp @@ -46,6 +46,9 @@ class PoolingFactory { /// OutputVector make_max_pool() const; + /// \brief Creates max pooling ONNX operation with 2 outputs (values and indices). + OutputVector make_max_pool_with_indices() const; + protected: Node m_onnx_node; const OutputVector m_inputs; @@ -56,6 +59,10 @@ class PoolingFactory { Shape m_padding_above; ngraph::op::PadType m_auto_pad; ngraph::op::RoundingType m_rounding_type; + + enum class StorageOrder : int64_t { ROW_MAJOR = 0, COLUMN_MAJOR = 1 }; + + StorageOrder m_storage_order; }; } // namespace pooling } // namespace onnx_import diff --git a/ngraph/frontend/onnx/frontend/src/utils/random_normal.cpp b/ngraph/frontend/onnx/frontend/src/utils/random_normal.cpp new file mode 100644 index 00000000000000..66cad4983fc6d0 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/utils/random_normal.cpp @@ -0,0 +1,68 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "random_normal.hpp" + +#include + +#include "default_opset.hpp" +#include "ngraph/opsets/opset8.hpp" + +namespace ngraph { +namespace onnx_import { +namespace detail { + +OutputVector make_random_normal(const Output& shape, + element::Type target_type, + float mean, + float scale, + float seed) { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution distrib(0, 9999); + + // We start by generating two random series from a uniform distribution + const uint64_t global_seed = 0; + + // ONNX specifies the seed as a float, but OpenVINO uses uint64_t + const auto op_seed = static_cast(seed * 1000); + + // We need to use two op_seeds to make sure we get different results for two RandomUniform series + const uint64_t seed_1 = (op_seed == 0 ? distrib(gen) : op_seed); + const uint64_t seed_2 = (op_seed == 0 ? distrib(gen) : op_seed + 10000); + + const auto min_val = default_opset::Constant::create(target_type, Shape{1}, {0}); + const auto max_val = default_opset::Constant::create(target_type, Shape{1}, {1}); + + const auto uniform_1 = + std::make_shared(shape, min_val, max_val, target_type, global_seed, seed_1); + const auto uniform_2 = + std::make_shared(shape, min_val, max_val, target_type, global_seed, seed_2); + + // Compute Box–Muller transform + // random_normal = scale * ng.sqrt(-2.0 * ng.log(uniform_1)) * ng.cos(2.0 * np.pi * uniform_2) + mean + const auto pi = default_opset::Constant::create(target_type, Shape{1}, {3.141592653589793}); + const auto minus_two = default_opset::Constant::create(target_type, Shape{1}, {-2.0}); + const auto two = default_opset::Constant::create(target_type, Shape{1}, {2.0}); + + const auto log = std::make_shared(uniform_1); + const auto multiply_minus_two_log = std::make_shared(log, minus_two); + const auto sqrt = std::make_shared(multiply_minus_two_log); + + const auto multiply_two_pi = std::make_shared(uniform_2, pi); + const auto multiply_two_pi_uniform_2 = std::make_shared(multiply_two_pi, uniform_2); + auto const cos = std::make_shared(multiply_two_pi_uniform_2); + + auto const scale_const = default_opset::Constant::create(target_type, Shape{1}, {scale}); + auto const mean_const = default_opset::Constant::create(target_type, Shape{1}, {mean}); + auto const product = + std::make_shared(scale_const, std::make_shared(sqrt, cos)); + auto const sum = std::make_shared(product, mean_const); + + return {sum}; +} + +} // namespace detail +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/frontend/src/utils/random_normal.hpp b/ngraph/frontend/onnx/frontend/src/utils/random_normal.hpp new file mode 100644 index 00000000000000..7e9226d6ca0590 --- /dev/null +++ b/ngraph/frontend/onnx/frontend/src/utils/random_normal.hpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/op/reshape.hpp" +#include "ngraph/output_vector.hpp" + +namespace ngraph { +namespace onnx_import { +namespace detail { + +/// \brief Creates a random normal tensor with the given shape and type. +/// \details Uses Box-Mueller algorithm to generate random numbers from a Gauassian distribution +/// \param shape Shape of the output tensor +/// \param type Type of the output tensor +/// \param mean Mean of the distribution +/// \param scale Standard deviation of the distribution +/// \param seed Seed for the random number generator +OutputVector make_random_normal(const Output& shape, + element::Type type, + float mean, + float scale, + float seed); + +} // namespace detail +} // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx/onnx_common/CMakeLists.txt b/ngraph/frontend/onnx/onnx_common/CMakeLists.txt index bc63b28893d89b..1c4d330290dacd 100644 --- a/ngraph/frontend/onnx/onnx_common/CMakeLists.txt +++ b/ngraph/frontend/onnx/onnx_common/CMakeLists.txt @@ -29,9 +29,4 @@ target_link_libraries(${TARGET_NAME} PRIVATE ngraph) link_system_libraries(${TARGET_NAME} PUBLIC onnx_proto onnx ${Protobuf_LITE_LIBRARIES}) target_include_directories(${TARGET_NAME} PRIVATE ${ONNX_COMMON_SRC_DIR}) - -if(NGRAPH_USE_PROTOBUF_LITE) - target_compile_definitions(${TARGET_NAME} PRIVATE NGRAPH_USE_PROTOBUF_LITE) -endif() - add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) diff --git a/ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp b/ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp index ee75cf47991311..b6395ddf3f8c82 100644 --- a/ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp +++ b/ngraph/frontend/onnx/onnx_common/src/onnx_model_validator.cpp @@ -22,7 +22,8 @@ enum Field { GRAPH = 7, OPSET_IMPORT = 8, METADATA_PROPS = 14, - TRAINING_INFO = 20 + TRAINING_INFO = 20, + FUNCTIONS = 25 }; enum WireType { VARINT = 0, BITS_64 = 1, LENGTH_DELIMITED = 2, START_GROUP = 3, END_GROUP = 4, BITS_32 = 5 }; @@ -46,6 +47,7 @@ bool is_correct_onnx_field(const PbKey& decoded_key) { {OPSET_IMPORT, LENGTH_DELIMITED}, {METADATA_PROPS, LENGTH_DELIMITED}, {TRAINING_INFO, LENGTH_DELIMITED}, + {FUNCTIONS, LENGTH_DELIMITED}, }; if (!onnx_fields.count(static_cast(decoded_key.first))) { diff --git a/ngraph/frontend/onnx/onnx_common/src/parser.cpp b/ngraph/frontend/onnx/onnx_common/src/parser.cpp index 430c569d399dfc..c913a21d723233 100644 --- a/ngraph/frontend/onnx/onnx_common/src/parser.cpp +++ b/ngraph/frontend/onnx/onnx_common/src/parser.cpp @@ -53,20 +53,8 @@ ONNX_NAMESPACE::ModelProto parse_from_istream(std::istream& model_stream) { ONNX_NAMESPACE::ModelProto model_proto; if (!model_proto.ParseFromIstream(&model_stream)) { -#ifdef NGRAPH_USE_PROTOBUF_LITE throw ngraph_error("Error during import of ONNX model provided as input stream " " with binary protobuf message."); -#else - // Rewind to the beginning and clear stream state. - model_stream.clear(); - model_stream.seekg(0); - google::protobuf::io::IstreamInputStream iistream(&model_stream); - // Try parsing input as a prototxt message - if (!google::protobuf::TextFormat::Parse(&iistream, &model_proto)) { - throw ngraph_error("Error during import of ONNX model provided as input stream with prototxt " - "protobuf message."); - } -#endif } return model_proto; diff --git a/ngraph/frontend/onnx/onnx_common/src/utils.cpp b/ngraph/frontend/onnx/onnx_common/src/utils.cpp index 5bc6a79459ac25..5cb45a3a97ecf9 100644 --- a/ngraph/frontend/onnx/onnx_common/src/utils.cpp +++ b/ngraph/frontend/onnx/onnx_common/src/utils.cpp @@ -45,13 +45,7 @@ size_t get_onnx_data_size(int32_t onnx_type) { case ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16: return sizeof(uint16_t); } -#ifdef NGRAPH_USE_PROTOBUF_LITE throw ngraph_error("unsupported element type"); -#else - throw ngraph_error( - "unsupported element type: " + - ONNX_NAMESPACE::TensorProto_DataType_Name(static_cast(onnx_type))); -#endif } namespace { using namespace ONNX_NAMESPACE; diff --git a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/exceptions.hpp b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/exceptions.hpp index d2fd144022db7f..4de8e7286c0ce2 100644 --- a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/exceptions.hpp +++ b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/exceptions.hpp @@ -5,9 +5,8 @@ #pragma once #include -#include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { class NodeContext; @@ -31,7 +30,7 @@ class OpValidationFailurePDPD : public OpValidationFailure { /// \param ... Additional error message info to be added to the error message via the `<<` /// stream-insertion operator. Note that the expressions here will be evaluated lazily, /// i.e., only if the `cond` evalutes to `false`. -/// \throws ::ngraph::OpValidationFailurePDPD if `cond` is false. +/// \throws ::ov::OpValidationFailurePDPD if `cond` is false. #define PDPD_OP_VALIDATION_CHECK(node_context, ...) \ - NGRAPH_CHECK_HELPER(::ngraph::frontend::pdpd::OpValidationFailurePDPD, (node_context), __VA_ARGS__) -} // namespace ngraph + OPENVINO_ASSERT_HELPER(::ov::frontend::pdpd::OpValidationFailurePDPD, (node_context), __VA_ARGS__) +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/frontend.hpp b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/frontend.hpp index cf2fa3ae9e455e..857c5035097b88 100644 --- a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/frontend.hpp +++ b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/frontend.hpp @@ -9,7 +9,7 @@ #include "exceptions.hpp" #include "model.hpp" -namespace ngraph { +namespace ov { namespace frontend { class OpPlacePDPD; @@ -69,4 +69,4 @@ class PDPD_API FrontEndPDPD : public FrontEnd { }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/model.hpp b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/model.hpp index 83f63e38751745..4eff6120552b45 100644 --- a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/model.hpp +++ b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/model.hpp @@ -7,7 +7,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { class OpPlacePDPD; class TensorPlacePDPD; @@ -32,11 +32,11 @@ class PDPD_API InputModelPDPD : public InputModel { void override_all_outputs(const std::vector& outputs) override; void override_all_inputs(const std::vector& inputs) override; void extract_subgraph(const std::vector& inputs, const std::vector& outputs) override; - void set_partial_shape(Place::Ptr place, const ngraph::PartialShape&) override; - ngraph::PartialShape get_partial_shape(Place::Ptr place) const override; - void set_element_type(Place::Ptr place, const ngraph::element::Type&) override; + void set_partial_shape(Place::Ptr place, const ov::PartialShape&) override; + ov::PartialShape get_partial_shape(Place::Ptr place) const override; + void set_element_type(Place::Ptr place, const ov::element::Type&) override; void set_tensor_value(Place::Ptr place, const void* value) override; }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/place.hpp b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/place.hpp index 28a99d1dd2adf0..d4657a97d8ba96 100644 --- a/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/place.hpp +++ b/ngraph/frontend/paddlepaddle/include/paddlepaddle_frontend/place.hpp @@ -17,7 +17,7 @@ class VarDesc; } // namespace framework } // namespace paddle -namespace ngraph { +namespace ov { namespace frontend { class TensorPlacePDPD; class OpPlacePDPD; @@ -196,4 +196,4 @@ class TensorPlacePDPD : public PlacePDPD { }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/decoder.cpp b/ngraph/frontend/paddlepaddle/src/decoder.cpp index 9a8abb718e3fdc..d157a349a8fc99 100644 --- a/ngraph/frontend/paddlepaddle/src/decoder.cpp +++ b/ngraph/frontend/paddlepaddle/src/decoder.cpp @@ -15,7 +15,7 @@ #include "framework.pb.h" -namespace ngraph { +namespace ov { namespace frontend { using namespace paddle::framework; @@ -153,4 +153,4 @@ std::map DecoderPDPDProto::map_for_each_output( } } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/decoder.hpp b/ngraph/frontend/paddlepaddle/src/decoder.hpp index db98b1c3bfdebe..a87bf04f591383 100644 --- a/ngraph/frontend/paddlepaddle/src/decoder.hpp +++ b/ngraph/frontend/paddlepaddle/src/decoder.hpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -19,7 +18,7 @@ #include "framework.pb.h" #include "node_context.hpp" -namespace ngraph { +namespace ov { namespace frontend { extern std::map TYPE_MAP; @@ -51,4 +50,4 @@ class DecoderPDPDProto : public pdpd::DecoderBase { }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/default_opset.hpp b/ngraph/frontend/paddlepaddle/src/default_opset.hpp index 4a7aa3259c6402..677e48045cf8bc 100644 --- a/ngraph/frontend/paddlepaddle/src/default_opset.hpp +++ b/ngraph/frontend/paddlepaddle/src/default_opset.hpp @@ -4,7 +4,7 @@ #include "ngraph/opsets/opset8.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -13,4 +13,4 @@ namespace default_opset = ngraph::opset8; } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/exceptions.cpp b/ngraph/frontend/paddlepaddle/src/exceptions.cpp index caf328b45d0df1..0d172c6f4b537c 100644 --- a/ngraph/frontend/paddlepaddle/src/exceptions.cpp +++ b/ngraph/frontend/paddlepaddle/src/exceptions.cpp @@ -6,7 +6,7 @@ #include "node_context.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { std::string OpValidationFailurePDPD::get_error_msg_prefix_pdpd(const pdpd::NodeContext& node) { @@ -16,4 +16,4 @@ std::string OpValidationFailurePDPD::get_error_msg_prefix_pdpd(const pdpd::NodeC } } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/frontend.cpp b/ngraph/frontend/paddlepaddle/src/frontend.cpp index ea68793fcc6e1a..a551fecdafb4a1 100644 --- a/ngraph/frontend/paddlepaddle/src/frontend.cpp +++ b/ngraph/frontend/paddlepaddle/src/frontend.cpp @@ -5,8 +5,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -21,11 +21,11 @@ #include "pdpd_fw_node.hpp" #include "pdpd_utils.hpp" -using namespace ngraph::opset7; -using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov::opset7; +using namespace ov; +using namespace ov::frontend; -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace { @@ -84,7 +84,7 @@ NamedOutputs make_framework_node(const std::map>& } auto node = - std::make_shared(DecoderPDPDProto(op_place), inputs_vector, inputs_names); + std::make_shared(DecoderPDPDProto(op_place), inputs_vector, inputs_names); return node->return_named_outputs(); } @@ -326,7 +326,7 @@ std::string FrontEndPDPD::get_name() const { return "paddle"; } } // namespace frontend -} // namespace ngraph +} // namespace ov extern "C" PDPD_API FrontEndVersion GetAPIVersion() { return OV_FRONTEND_API_VERSION; diff --git a/ngraph/frontend/paddlepaddle/src/model.cpp b/ngraph/frontend/paddlepaddle/src/model.cpp index 171c596f48efb7..0cbb9038e87ea5 100644 --- a/ngraph/frontend/paddlepaddle/src/model.cpp +++ b/ngraph/frontend/paddlepaddle/src/model.cpp @@ -3,7 +3,7 @@ // #include -#include +#include #include #include #include @@ -19,7 +19,7 @@ # include #endif -namespace ngraph { +namespace ov { namespace frontend { using namespace paddle::framework::proto; @@ -463,4 +463,4 @@ void InputModelPDPD::set_tensor_value(Place::Ptr place, const void* value) { } } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/node_context.hpp b/ngraph/frontend/paddlepaddle/src/node_context.hpp index 34af177d47f5d0..2e02119c485bc3 100644 --- a/ngraph/frontend/paddlepaddle/src/node_context.hpp +++ b/ngraph/frontend/paddlepaddle/src/node_context.hpp @@ -3,10 +3,10 @@ // #pragma once -#include -#include -#include -#include +#include "ngraph/compatibility.hpp" +#include "openvino/core/variant.hpp" +#include "paddlepaddle_frontend/exceptions.hpp" +#include "paddlepaddle_frontend/utility.hpp" #define NGRAPH_VARIANT_DECLARATION(TYPE, info) \ template <> \ @@ -24,9 +24,6 @@ NGRAPH_VARIANT_DECLARATION(std::vector, "Variant::float_vector"); NGRAPH_VARIANT_DECLARATION(bool, "Variant::bool"); NGRAPH_VARIANT_DECLARATION(ngraph::element::Type, "Variant::element_type"); NGRAPH_VARIANT_DECLARATION(std::vector, "Variant::int64_vector"); -} // namespace ov - -namespace ngraph { namespace frontend { namespace pdpd { using InPortName = std::string; @@ -202,4 +199,4 @@ inline NamedOutputs NodeContext::default_single_output_mapping( } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/argmax.cpp b/ngraph/frontend/paddlepaddle/src/op/argmax.cpp index 1194bf25f62746..e2ad9a8fe6d0bd 100644 --- a/ngraph/frontend/paddlepaddle/src/op/argmax.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/argmax.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -38,4 +38,4 @@ NamedOutputs argmax(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/assign_value.cpp b/ngraph/frontend/paddlepaddle/src/op/assign_value.cpp index 4f4f424f169cae..ad5482f8d67a35 100644 --- a/ngraph/frontend/paddlepaddle/src/op/assign_value.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/assign_value.cpp @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include -namespace ngraph { +#include +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -46,4 +46,4 @@ NamedOutputs assign_value(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/batch_norm.cpp b/ngraph/frontend/paddlepaddle/src/op/batch_norm.cpp index 869087ba963cba..1d52fecd0d3be8 100644 --- a/ngraph/frontend/paddlepaddle/src/op/batch_norm.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/batch_norm.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -47,4 +47,4 @@ NamedOutputs batch_norm(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/cast.cpp b/ngraph/frontend/paddlepaddle/src/op/cast.cpp index 2d0181d41bc169..75cf919a12c35e 100644 --- a/ngraph/frontend/paddlepaddle/src/op/cast.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/cast.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -19,4 +19,4 @@ NamedOutputs cast(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/clip.cpp b/ngraph/frontend/paddlepaddle/src/op/clip.cpp index 1fd39ad00c8d18..551548f89b84c2 100644 --- a/ngraph/frontend/paddlepaddle/src/op/clip.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/clip.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -21,4 +21,4 @@ NamedOutputs clip(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/concat.cpp b/ngraph/frontend/paddlepaddle/src/op/concat.cpp index b65043c0444d92..13fb8b45318bbd 100644 --- a/ngraph/frontend/paddlepaddle/src/op/concat.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/concat.cpp @@ -2,20 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { NamedOutputs concat(const NodeContext& node) { auto data = node.get_ng_inputs("X"); auto axis = node.get_attribute("axis"); - return node.default_single_output_mapping({std::make_shared(data, axis)}, {"Out"}); + return node.default_single_output_mapping({std::make_shared(data, axis)}, {"Out"}); } } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/conv2d.cpp b/ngraph/frontend/paddlepaddle/src/op/conv2d.cpp index aa1ea7d928da56..87b0b9f53f9368 100644 --- a/ngraph/frontend/paddlepaddle/src/op/conv2d.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/conv2d.cpp @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // -#include +#include #include "conv2d_utils.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -17,4 +17,4 @@ NamedOutputs conv2d(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/conv2d_transpose.cpp b/ngraph/frontend/paddlepaddle/src/op/conv2d_transpose.cpp index f25f483ffb1601..57133dd626c3bb 100644 --- a/ngraph/frontend/paddlepaddle/src/op/conv2d_transpose.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/conv2d_transpose.cpp @@ -2,12 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include #include "conv2d_utils.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -18,4 +18,4 @@ NamedOutputs conv2d_transpose(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.cpp b/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.cpp index b4475a195913ed..31dd422f53fa37 100644 --- a/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.cpp @@ -4,11 +4,11 @@ #include "conv2d_utils.hpp" -#include +#include #include "node_context.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -93,4 +93,4 @@ std::shared_ptr get_reshaped_filter(const Output& filters, const int } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.hpp b/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.hpp index 589a19279c896b..0dc62aec2d758a 100644 --- a/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.hpp +++ b/ngraph/frontend/paddlepaddle/src/op/conv2d_utils.hpp @@ -5,7 +5,7 @@ #pragma once #include "node_context.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -57,4 +57,4 @@ NamedOutputs conv2d_base(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/cumsum.cpp b/ngraph/frontend/paddlepaddle/src/op/cumsum.cpp index 56a3a12707e4e2..13916a8efd2b1c 100644 --- a/ngraph/frontend/paddlepaddle/src/op/cumsum.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/cumsum.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -34,4 +34,4 @@ NamedOutputs cumsum(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/deformable_conv.cpp b/ngraph/frontend/paddlepaddle/src/op/deformable_conv.cpp index dd02c81fc755b1..5c5b5a7689d4fb 100644 --- a/ngraph/frontend/paddlepaddle/src/op/deformable_conv.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/deformable_conv.cpp @@ -6,7 +6,7 @@ #include "conv2d_utils.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -64,4 +64,4 @@ NamedOutputs deformable_conv(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/dropout.cpp b/ngraph/frontend/paddlepaddle/src/op/dropout.cpp index 3ce9ffeee48888..3548e63b226326 100644 --- a/ngraph/frontend/paddlepaddle/src/op/dropout.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/dropout.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -30,4 +30,4 @@ NamedOutputs dropout(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/elementwise_ops.cpp b/ngraph/frontend/paddlepaddle/src/op/elementwise_ops.cpp index 78c6da2c35359f..dd08bdc7b1552d 100644 --- a/ngraph/frontend/paddlepaddle/src/op/elementwise_ops.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/elementwise_ops.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -83,4 +83,4 @@ NamedOutputs elementwise_greater_equal(const NodeContext& node_context) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/embedding.cpp b/ngraph/frontend/paddlepaddle/src/op/embedding.cpp index a8387dd62b45e0..7a2c337b753b3d 100644 --- a/ngraph/frontend/paddlepaddle/src/op/embedding.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/embedding.cpp @@ -2,10 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -52,4 +52,4 @@ NamedOutputs embedding(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/exp.cpp b/ngraph/frontend/paddlepaddle/src/op/exp.cpp index c767ab67692c01..4af6f32a6b18ab 100644 --- a/ngraph/frontend/paddlepaddle/src/op/exp.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/exp.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -17,4 +17,4 @@ NamedOutputs exp(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/expand_v2.cpp b/ngraph/frontend/paddlepaddle/src/op/expand_v2.cpp index 0619f4fd850818..c9ab3347d1e0c6 100644 --- a/ngraph/frontend/paddlepaddle/src/op/expand_v2.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/expand_v2.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -50,4 +50,4 @@ NamedOutputs expand_v2(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/fill_any_like.cpp b/ngraph/frontend/paddlepaddle/src/op/fill_any_like.cpp index 2a7e9f3facdbb5..11a2371c0d44ca 100644 --- a/ngraph/frontend/paddlepaddle/src/op/fill_any_like.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/fill_any_like.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -18,7 +18,11 @@ NamedOutputs fill_any_like(const NodeContext& node) { // when type does not define, use the input type dtype = x.get_element_type(); } - const auto supported_type = {element::i32, element::i64, element::f16, element::f32, element::f64}; + const std::vector supported_type = {element::i32, + element::i64, + element::f16, + element::f32, + element::f64}; const bool valid_type = std::any_of(supported_type.begin(), supported_type.end(), [dtype](const element::Type& type) { return dtype == type; @@ -34,4 +38,4 @@ NamedOutputs fill_any_like(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/fill_constant.cpp b/ngraph/frontend/paddlepaddle/src/op/fill_constant.cpp index 963c9863aa28dc..ffc92c3397baa0 100644 --- a/ngraph/frontend/paddlepaddle/src/op/fill_constant.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/fill_constant.cpp @@ -2,10 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -41,11 +41,11 @@ NamedOutputs fill_constant(const NodeContext& node) { shape_node = opset6::Constant::create(element::i64, {shape.size()}, shape); } - return node.default_single_output_mapping({std::make_shared(value_node, shape_node)}, + return node.default_single_output_mapping({std::make_shared(value_node, shape_node)}, {"Out"}); } } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/fill_constant_batch_size_like.cpp b/ngraph/frontend/paddlepaddle/src/op/fill_constant_batch_size_like.cpp index 5883dae573b99e..04676913e74b6c 100644 --- a/ngraph/frontend/paddlepaddle/src/op/fill_constant_batch_size_like.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/fill_constant_batch_size_like.cpp @@ -8,7 +8,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -122,4 +122,4 @@ NamedOutputs fill_constant_batch_size_like(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/flatten_contiguous_range.cpp b/ngraph/frontend/paddlepaddle/src/op/flatten_contiguous_range.cpp index 5c1920ea310038..0a32a251ac52b8 100644 --- a/ngraph/frontend/paddlepaddle/src/op/flatten_contiguous_range.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/flatten_contiguous_range.cpp @@ -3,10 +3,10 @@ // #include -#include #include +#include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -44,4 +44,4 @@ NamedOutputs flatten_contiguous_range(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/gelu.cpp b/ngraph/frontend/paddlepaddle/src/op/gelu.cpp index 496a037b91205a..6f0593e9215999 100644 --- a/ngraph/frontend/paddlepaddle/src/op/gelu.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/gelu.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -20,4 +20,4 @@ NamedOutputs gelu(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/hard_sigmoid.cpp b/ngraph/frontend/paddlepaddle/src/op/hard_sigmoid.cpp index 5155f8a3b78048..b3a840c46184ec 100644 --- a/ngraph/frontend/paddlepaddle/src/op/hard_sigmoid.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/hard_sigmoid.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -24,4 +24,4 @@ NamedOutputs hard_sigmoid(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/hard_swish.cpp b/ngraph/frontend/paddlepaddle/src/op/hard_swish.cpp index e2cecdc81c0f2e..618d29ae3bcfc3 100644 --- a/ngraph/frontend/paddlepaddle/src/op/hard_swish.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/hard_swish.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -30,4 +30,4 @@ NamedOutputs hard_swish(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/interp.cpp b/ngraph/frontend/paddlepaddle/src/op/interp.cpp index b8b739b4c96c4e..e1a6fdca36e9d4 100644 --- a/ngraph/frontend/paddlepaddle/src/op/interp.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/interp.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -175,4 +175,4 @@ NamedOutputs bicubic_interp_v2(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/layer_norm.cpp b/ngraph/frontend/paddlepaddle/src/op/layer_norm.cpp index 4dda7426f453c7..f28468a152318c 100644 --- a/ngraph/frontend/paddlepaddle/src/op/layer_norm.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/layer_norm.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -56,4 +56,4 @@ NamedOutputs layer_norm(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/leakyrelu.cpp b/ngraph/frontend/paddlepaddle/src/op/leakyrelu.cpp index f5267bd31c305e..c5ab5b74f215d1 100644 --- a/ngraph/frontend/paddlepaddle/src/op/leakyrelu.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/leakyrelu.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -17,4 +17,4 @@ NamedOutputs leaky_relu(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/log.cpp b/ngraph/frontend/paddlepaddle/src/op/log.cpp index 9a46758790b7af..8b0e18c5826ead 100644 --- a/ngraph/frontend/paddlepaddle/src/op/log.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/log.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -17,4 +17,4 @@ NamedOutputs log(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/logical_not.cpp b/ngraph/frontend/paddlepaddle/src/op/logical_not.cpp index 12b2521c2a4b25..71d571d56c8b86 100644 --- a/ngraph/frontend/paddlepaddle/src/op/logical_not.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/logical_not.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -16,4 +16,4 @@ NamedOutputs logical_not(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/lstm.cpp b/ngraph/frontend/paddlepaddle/src/op/lstm.cpp index 039f5c061bb197..3f34629b39472e 100644 --- a/ngraph/frontend/paddlepaddle/src/op/lstm.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/lstm.cpp @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include #include "ngraph/builder/reshape.hpp" #include "paddlepaddle_frontend/utility.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -28,7 +28,7 @@ enum class LSTMInput { struct LSTMNgInputMap { explicit LSTMNgInputMap(const NodeContext& node, Output& prev_output, int layer) { - auto input_x = builder::opset1::reorder_axes(prev_output, {1, 0, 2}); + auto input_x = ngraph::builder::opset1::reorder_axes(prev_output, {1, 0, 2}); //[begin. end) auto weight_list = node.get_ng_inputs("WeightList"); auto weight_begin = weight_list.begin(); @@ -70,20 +70,20 @@ struct LSTMNgInputMap { auto hidden_bias = std::make_shared(layer_hidden_bias, 0); auto bias = std::make_shared(weight_bias, hidden_bias); m_input_map[LSTMInput::LSTM_INPUT_W] = - ngraph::op::util::convert_lstm_node_format(input_weight, - ngraph::op::util::LSTMWeightsFormat::IFCO, - ngraph::op::util::LSTMWeightsFormat::FICO, - 1); + ov::op::util::convert_lstm_node_format(input_weight, + ov::op::util::LSTMWeightsFormat::IFCO, + ov::op::util::LSTMWeightsFormat::FICO, + 1); m_input_map[LSTMInput::LSTM_INPUT_R] = - ngraph::op::util::convert_lstm_node_format(hidden_weight, - ngraph::op::util::LSTMWeightsFormat::IFCO, - ngraph::op::util::LSTMWeightsFormat::FICO, - 1); + ov::op::util::convert_lstm_node_format(hidden_weight, + ov::op::util::LSTMWeightsFormat::IFCO, + ov::op::util::LSTMWeightsFormat::FICO, + 1); m_input_map[LSTMInput::LSTM_INPUT_B] = - ngraph::op::util::convert_lstm_node_format(bias, - ngraph::op::util::LSTMWeightsFormat::IFCO, - ngraph::op::util::LSTMWeightsFormat::FICO, - 1); + ov::op::util::convert_lstm_node_format(bias, + ov::op::util::LSTMWeightsFormat::IFCO, + ov::op::util::LSTMWeightsFormat::FICO, + 1); // Get dimensions needed for default inputs creation // Parsing init hidden state @@ -115,19 +115,19 @@ struct LSTMNgInputMap { auto c_end = opset6::Constant::create(element::i64, {1}, {layer * bidirect_len + bidirect_len}); m_input_map[LSTMInput::LSTM_INPUT_INIT_H] = - builder::opset1::reorder_axes(std::make_shared(init_states[0], - h_begin, - h_end, - std::vector{0}, - std::vector{0}), - {1, 0, 2}); + ngraph::builder::opset1::reorder_axes(std::make_shared(init_states[0], + h_begin, + h_end, + std::vector{0}, + std::vector{0}), + {1, 0, 2}); m_input_map[LSTMInput::LSTM_INPUT_INIT_C] = - builder::opset1::reorder_axes(std::make_shared(init_states[1], - c_begin, - c_end, - std::vector{0}, - std::vector{0}), - {1, 0, 2}); + ngraph::builder::opset1::reorder_axes(std::make_shared(init_states[1], + c_begin, + c_end, + std::vector{0}, + std::vector{0}), + {1, 0, 2}); } Output& at(const LSTMInput& key) { @@ -172,12 +172,12 @@ NamedOutputs lstm(const NodeContext& node) { input_map.at(LSTMInput::LSTM_INPUT_B), attrs.m_hidden_size, attrs.m_direction); - prev_output = builder::opset1::reorder_axes(lstm_sequence->output(0), {2, 0, 1, 3}); + prev_output = ngraph::builder::opset1::reorder_axes(lstm_sequence->output(0), {2, 0, 1, 3}); auto out_shape = opset6::Constant::create(element::i64, Shape{3}, {0, 0, -1}); prev_output = std::make_shared(prev_output, out_shape, true); - final_h.push_back(builder::opset1::reorder_axes(lstm_sequence->output(1), {1, 0, 2})); - final_c.push_back(builder::opset1::reorder_axes(lstm_sequence->output(2), {1, 0, 2})); + final_h.push_back(ngraph::builder::opset1::reorder_axes(lstm_sequence->output(1), {1, 0, 2})); + final_c.push_back(ngraph::builder::opset1::reorder_axes(lstm_sequence->output(2), {1, 0, 2})); } NamedOutputs named_outputs; @@ -190,4 +190,4 @@ NamedOutputs lstm(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/matmul.cpp b/ngraph/frontend/paddlepaddle/src/op/matmul.cpp index 255bd7d5292003..4e7f76d0e5740f 100644 --- a/ngraph/frontend/paddlepaddle/src/op/matmul.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/matmul.cpp @@ -4,7 +4,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -27,4 +27,4 @@ NamedOutputs matmul(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/matmul_v2.cpp b/ngraph/frontend/paddlepaddle/src/op/matmul_v2.cpp index 2ecd053f1569a0..f4e414a2d0c9fc 100644 --- a/ngraph/frontend/paddlepaddle/src/op/matmul_v2.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/matmul_v2.cpp @@ -5,7 +5,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -21,4 +21,4 @@ NamedOutputs matmul_v2(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/matrix_nms.cpp b/ngraph/frontend/paddlepaddle/src/op/matrix_nms.cpp index 8ecffe5b241037..85ee304832c8eb 100644 --- a/ngraph/frontend/paddlepaddle/src/op/matrix_nms.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/matrix_nms.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -84,4 +84,4 @@ NamedOutputs matrix_nms(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/mul.cpp b/ngraph/frontend/paddlepaddle/src/op/mul.cpp deleted file mode 100644 index d3833b4837ea33..00000000000000 --- a/ngraph/frontend/paddlepaddle/src/op/mul.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -namespace ngraph { -namespace frontend { -namespace pdpd { -namespace op { -NamedOutputs mul(const NodeContext& node) { - auto x = node.get_ng_input("X"); - auto y = node.get_ng_input("Y"); - PDPD_OP_VALIDATION_CHECK(node, x.get_partial_shape().rank().is_static(), "matmul: X rank must be static!"); - int64_t x_rank = x.get_partial_shape().rank().get_length(); - PDPD_OP_VALIDATION_CHECK(node, - y.get_partial_shape().rank().is_static() && y.get_partial_shape().rank().get_length() == 2, - "matmul: Y rank must be static, and 2!"); - if (x_rank > 2) { - auto shape = std::make_shared(x); - int64_t x_num_col_dims = node.get_attribute("x_num_col_dims"); - auto axis = ngraph::opset6::Constant::create(ngraph::element::i64, {}, {0}); - auto split_lengths = - ngraph::opset6::Constant::create(ngraph::element::i64, {2}, {x_num_col_dims, x_rank - x_num_col_dims}); - auto split = std::make_shared(shape, axis, split_lengths); - auto f_dim_red_axis = ngraph::opset6::Constant::create(ngraph::element::i64, {}, {0}); - auto first_dim_reduce = std::make_shared(split->output(0), f_dim_red_axis); - auto f_dim_shape = ngraph::opset6::Constant::create(ngraph::element::i64, {1}, {1}); - auto first_dim = std::make_shared(first_dim_reduce, f_dim_shape, false); - auto s_dim_red_axis = ngraph::opset6::Constant::create(ngraph::element::i64, {}, {0}); - auto second_dim_reduce = std::make_shared(split->output(1), s_dim_red_axis); - auto s_dim_shape = ngraph::opset6::Constant::create(ngraph::element::i64, {1}, {1}); - auto second_dim = std::make_shared(second_dim_reduce, s_dim_shape, false); - auto out_shape = std::make_shared(ngraph::NodeVector{first_dim, second_dim}, 0); - auto x_reshaped = std::make_shared(x, out_shape, false); - return node.default_single_output_mapping({std::make_shared(x_reshaped, y)}, {"Out"}); - } - return node.default_single_output_mapping({std::make_shared(x, y)}, {"Out"}); -} - -} // namespace op -} // namespace pdpd -} // namespace frontend -} // namespace ngraph \ No newline at end of file diff --git a/ngraph/frontend/paddlepaddle/src/op/multiclass_nms.cpp b/ngraph/frontend/paddlepaddle/src/op/multiclass_nms.cpp index 62ee84628c0608..ced2a3271076fe 100644 --- a/ngraph/frontend/paddlepaddle/src/op/multiclass_nms.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/multiclass_nms.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -66,4 +66,4 @@ NamedOutputs multiclass_nms(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/pad3d.cpp b/ngraph/frontend/paddlepaddle/src/op/pad3d.cpp index 173a215faad433..5c92ad7d1e9fb2 100644 --- a/ngraph/frontend/paddlepaddle/src/op/pad3d.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/pad3d.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -84,4 +84,4 @@ NamedOutputs pad3d(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp b/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp index a2c22983f016a5..8869a0c387b787 100644 --- a/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/pool2d.cpp @@ -8,7 +8,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -48,12 +48,12 @@ static void get_paddings(const NodeContext& node, // TODO: need to support NHWC input #55483 switch (paddings.size()) { case 2: - pad_begin = Shape{static_cast(paddings[0]), static_cast(paddings[1])}; + pad_begin = Shape{static_cast(paddings[0]), static_cast(paddings[1])}; pad_end = pad_begin; break; case 4: - pad_begin = Shape{static_cast(paddings[0]), static_cast(paddings[2])}; - pad_end = Shape{static_cast(paddings[1]), static_cast(paddings[3])}; + pad_begin = Shape{static_cast(paddings[0]), static_cast(paddings[2])}; + pad_end = Shape{static_cast(paddings[1]), static_cast(paddings[3])}; break; default: throw std::runtime_error("Unsupported pooling paddings " + std::to_string(paddings.size())); @@ -131,7 +131,7 @@ NamedOutputs pool2d(const NodeContext& node) { auto strides = node.get_attribute>("strides"); auto paddings = node.get_attribute>("paddings"); - uint64_t kernel_h, kernel_w; + size_t kernel_h, kernel_w; if (kernel_shape.size() == 1) { // Not tested: implemented according to spec, but can't generate real // model to test @@ -185,4 +185,4 @@ NamedOutputs pool2d(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/pow.cpp b/ngraph/frontend/paddlepaddle/src/op/pow.cpp index bac27d078ca9ae..52182946a6ed6b 100644 --- a/ngraph/frontend/paddlepaddle/src/op/pow.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/pow.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -16,7 +16,7 @@ NamedOutputs pow(const NodeContext& node) { if (node.has_ng_input("FactorTensor")) { factor_node = node.get_ng_input("FactorTensor"); if (factor_node.get_element_type() != dtype) - factor_node = std::make_shared(factor_node, dtype); + factor_node = std::make_shared(factor_node, dtype); } else { factor_node = ngraph::opset6::Constant::create(dtype, Shape{1}, {node.get_attribute("factor")}); } @@ -27,4 +27,4 @@ NamedOutputs pow(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/prior_box.cpp b/ngraph/frontend/paddlepaddle/src/op/prior_box.cpp index fcdae08eaccf48..a6ffb1a90bc88f 100644 --- a/ngraph/frontend/paddlepaddle/src/op/prior_box.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/prior_box.cpp @@ -8,7 +8,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -109,4 +109,4 @@ NamedOutputs prior_box(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/range.cpp b/ngraph/frontend/paddlepaddle/src/op/range.cpp index ebbf108fc4fefa..a90f60d0cb5cf6 100644 --- a/ngraph/frontend/paddlepaddle/src/op/range.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/range.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -28,4 +28,4 @@ NamedOutputs range(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/relu.cpp b/ngraph/frontend/paddlepaddle/src/op/relu.cpp index 3eefc1939ab8ef..4aa63bda1dc0fe 100644 --- a/ngraph/frontend/paddlepaddle/src/op/relu.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/relu.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -17,4 +17,4 @@ NamedOutputs relu(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/relu6.cpp b/ngraph/frontend/paddlepaddle/src/op/relu6.cpp index c5ae51a2d97ac8..65aa1354cdd07b 100644 --- a/ngraph/frontend/paddlepaddle/src/op/relu6.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/relu6.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -19,4 +19,4 @@ NamedOutputs relu6(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/reshape2.cpp b/ngraph/frontend/paddlepaddle/src/op/reshape2.cpp index a16678a24cc255..6cffb7557ecfc6 100644 --- a/ngraph/frontend/paddlepaddle/src/op/reshape2.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/reshape2.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -39,4 +39,4 @@ NamedOutputs reshape2(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/rnn.cpp b/ngraph/frontend/paddlepaddle/src/op/rnn.cpp index 2115acd95e8324..f0e594079b9735 100644 --- a/ngraph/frontend/paddlepaddle/src/op/rnn.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/rnn.cpp @@ -7,7 +7,7 @@ #include "paddlepaddle_frontend/utility.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -24,4 +24,4 @@ NamedOutputs rnn(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/scale.cpp b/ngraph/frontend/paddlepaddle/src/op/scale.cpp index 7398df6845c66e..9b67eedc70a322 100644 --- a/ngraph/frontend/paddlepaddle/src/op/scale.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/scale.cpp @@ -3,10 +3,10 @@ // #include -#include #include +#include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -25,20 +25,20 @@ NamedOutputs scale(const NodeContext& node) { scale = std::make_shared(scale_tensor_node, dtype); } else { auto scale_val = node.get_attribute("scale"); - scale = ngraph::opset6::Constant::create(dtype, Shape{1}, {scale_val}); + scale = ov::opset6::Constant::create(dtype, Shape{1}, {scale_val}); } auto bias_val = node.get_attribute("bias"); - bias = ngraph::opset6::Constant::create(dtype, Shape{1}, {bias_val}); + bias = ov::opset6::Constant::create(dtype, Shape{1}, {bias_val}); auto bias_after_scale = node.get_attribute("bias_after_scale"); std::shared_ptr result_node; if (!bias_after_scale) { - auto node_add = std::make_shared(data, bias); - result_node = std::make_shared(node_add, scale); + auto node_add = std::make_shared(data, bias); + result_node = std::make_shared(node_add, scale); } else { - auto node_multiply = std::make_shared(data, scale); - result_node = std::make_shared(node_multiply, bias); + auto node_multiply = std::make_shared(data, scale); + result_node = std::make_shared(node_multiply, bias); } return node.default_single_output_mapping({result_node}, {"Out"}); @@ -47,4 +47,4 @@ NamedOutputs scale(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/shape.cpp b/ngraph/frontend/paddlepaddle/src/op/shape.cpp index e6d77876fcf91e..3c777cb87a9c41 100644 --- a/ngraph/frontend/paddlepaddle/src/op/shape.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/shape.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -18,4 +18,4 @@ NamedOutputs shape(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/sigmoid.cpp b/ngraph/frontend/paddlepaddle/src/op/sigmoid.cpp index db2f3e8677225d..f9122d2562f259 100644 --- a/ngraph/frontend/paddlepaddle/src/op/sigmoid.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/sigmoid.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -17,4 +17,4 @@ NamedOutputs sigmoid(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/slice.cpp b/ngraph/frontend/paddlepaddle/src/op/slice.cpp index 8874ca18d7cb0b..873695a8fc8e8c 100644 --- a/ngraph/frontend/paddlepaddle/src/op/slice.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/slice.cpp @@ -8,7 +8,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -77,9 +77,24 @@ NamedOutputs slice(const NodeContext& node) { auto decrease_axis = node.get_attribute>("decrease_axis"); if (decrease_axis.size() > 0) { - auto squeeze_index_node = Constant::create(element::i32, {}, decrease_axis); + // according to paddle slice_op, when all axes are decreased, output shape is [1], instead of scalar. + // Ref: paddle/fluid/operators/slice_op.h + PartialShape input_shape = data.get_partial_shape(); + PDPD_OP_VALIDATION_CHECK(node, + input_shape.rank().is_static(), + "input rank of slice must be static when decrease_axis is set."); + + auto squeeze_index_node = Constant::create(element::i32, {decrease_axis.size()}, decrease_axis); auto decreased_node = std::make_shared(stride_slice_node, squeeze_index_node); + auto input_rank = input_shape.rank().get_length(); + if (input_rank == decrease_axis.size()) { + auto restore_node = std::make_shared(decreased_node, + std::make_shared(element::i64, Shape{1}, 1), + false); // restore to shape (1,) + return node.default_single_output_mapping({restore_node}, {"Out"}); + } + return node.default_single_output_mapping({decreased_node}, {"Out"}); } @@ -88,4 +103,4 @@ NamedOutputs slice(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/softmax.cpp b/ngraph/frontend/paddlepaddle/src/op/softmax.cpp index 0e994765c42280..0646df0b704624 100644 --- a/ngraph/frontend/paddlepaddle/src/op/softmax.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/softmax.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -22,4 +22,4 @@ NamedOutputs softmax(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/split.cpp b/ngraph/frontend/paddlepaddle/src/op/split.cpp index 85cc660b259c30..e4fff9fd0ccc31 100644 --- a/ngraph/frontend/paddlepaddle/src/op/split.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/split.cpp @@ -6,7 +6,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -58,4 +58,4 @@ NamedOutputs split(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/squeeze.cpp b/ngraph/frontend/paddlepaddle/src/op/squeeze.cpp index d47fc784c63b13..ec52228e43dd1c 100644 --- a/ngraph/frontend/paddlepaddle/src/op/squeeze.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/squeeze.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -28,4 +28,4 @@ NamedOutputs squeeze(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/stack.cpp b/ngraph/frontend/paddlepaddle/src/op/stack.cpp index d6924290329ad8..1b11e3715f6b6b 100644 --- a/ngraph/frontend/paddlepaddle/src/op/stack.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/stack.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -38,4 +38,4 @@ NamedOutputs stack(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/tanh.cpp b/ngraph/frontend/paddlepaddle/src/op/tanh.cpp index 11b666cff8c0ca..96ead42fa1b6cd 100644 --- a/ngraph/frontend/paddlepaddle/src/op/tanh.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/tanh.cpp @@ -6,7 +6,7 @@ #include "default_opset.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -19,4 +19,4 @@ NamedOutputs tanh(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/transpose2.cpp b/ngraph/frontend/paddlepaddle/src/op/transpose2.cpp index e86598fb59cd6d..ece4118d602702 100644 --- a/ngraph/frontend/paddlepaddle/src/op/transpose2.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/transpose2.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -20,4 +20,4 @@ NamedOutputs transpose2(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/unsqueeze.cpp b/ngraph/frontend/paddlepaddle/src/op/unsqueeze.cpp index 55edccd9fd184c..34970c70639d76 100644 --- a/ngraph/frontend/paddlepaddle/src/op/unsqueeze.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/unsqueeze.cpp @@ -5,7 +5,7 @@ #include #include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -26,4 +26,4 @@ NamedOutputs unsqueeze(const NodeContext& node) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op/yolo_box.cpp b/ngraph/frontend/paddlepaddle/src/op/yolo_box.cpp index 4ada564a51cc94..c2ad5f91b1a3a7 100644 --- a/ngraph/frontend/paddlepaddle/src/op/yolo_box.cpp +++ b/ngraph/frontend/paddlepaddle/src/op/yolo_box.cpp @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // #include // std::numeric_limits -#include #include #include +#include -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -325,4 +325,4 @@ NamedOutputs yolo_box(const NodeContext& node_context) { } // namespace op } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op_table.cpp b/ngraph/frontend/paddlepaddle/src/op_table.cpp index cf02ab0bb32ff3..36b978258f6108 100644 --- a/ngraph/frontend/paddlepaddle/src/op_table.cpp +++ b/ngraph/frontend/paddlepaddle/src/op_table.cpp @@ -3,7 +3,7 @@ // #include "op_table.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { namespace op { @@ -47,7 +47,6 @@ OP_CONVERTER(log); OP_CONVERTER(logical_not); OP_CONVERTER(matmul); OP_CONVERTER(matmul_v2); -OP_CONVERTER(mul); OP_CONVERTER(matrix_nms); OP_CONVERTER(multiclass_nms); OP_CONVERTER(nearest_interp_v2); @@ -74,13 +73,6 @@ OP_CONVERTER(trilinear_interp_v2); OP_CONVERTER(unsqueeze); OP_CONVERTER(yolo_box); } // namespace op -} // namespace pdpd -} // namespace frontend -} // namespace ngraph - -namespace ngraph { -namespace frontend { -namespace pdpd { std::map get_supported_ops() { return {{"arg_max", op::argmax}, {"assign_value", op::assign_value}, @@ -127,7 +119,6 @@ std::map get_supported_ops() { {"matmul", op::matmul}, {"matmul_v2", op::matmul_v2}, {"max_pool2d_with_index", op::pool2d}, - {"mul", op::mul}, {"matrix_nms", op::matrix_nms}, {"multiclass_nms3", op::multiclass_nms}, {"nearest_interp_v2", op::nearest_interp_v2}, @@ -159,4 +150,4 @@ std::map get_supported_ops() { } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/op_table.hpp b/ngraph/frontend/paddlepaddle/src/op_table.hpp index 0c7d9fd8ca17b3..76ee7d5e3c33ef 100644 --- a/ngraph/frontend/paddlepaddle/src/op_table.hpp +++ b/ngraph/frontend/paddlepaddle/src/op_table.hpp @@ -11,7 +11,7 @@ #include "node_context.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { using CreatorFunction = std::function; @@ -20,4 +20,4 @@ std::map get_supported_ops(); } // namespace pdpd } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.cpp b/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.cpp index 905bf631329a85..e91df788b85ec2 100644 --- a/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.cpp +++ b/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.cpp @@ -4,7 +4,7 @@ #include -namespace ngraph { +namespace ov { namespace frontend { NGRAPH_RTTI_DEFINITION(PDPDFrameworkNode, "PDPDFrameworkNode", 1); @@ -36,4 +36,4 @@ std::map PDPDFrameworkNode::return_named_outputs() { } } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.hpp b/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.hpp index cb429b520cda04..558b29b0e75ec4 100644 --- a/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.hpp +++ b/ngraph/frontend/paddlepaddle/src/pdpd_fw_node.hpp @@ -8,7 +8,7 @@ #include "decoder.hpp" -namespace ngraph { +namespace ov { namespace frontend { class PDPDFrameworkNode : public ov::op::util::FrameworkNode { public: @@ -50,4 +50,4 @@ class PDPDFrameworkNode : public ov::op::util::FrameworkNode { std::vector m_inputs_names; }; } // namespace frontend -} // namespace ngraph +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/pdpd_utils.hpp b/ngraph/frontend/paddlepaddle/src/pdpd_utils.hpp index 7133f96fa7a719..1bf1a9a813d1b6 100644 --- a/ngraph/frontend/paddlepaddle/src/pdpd_utils.hpp +++ b/ngraph/frontend/paddlepaddle/src/pdpd_utils.hpp @@ -6,7 +6,7 @@ #include "frontend_manager/frontend_exceptions.hpp" -namespace ngraph { +namespace ov { namespace frontend { namespace pdpd { #ifdef _WIN32 @@ -40,4 +40,4 @@ bool endsWith(const std::basic_string& str, const std::basic_string& suffi } // namespace pdpd } // namespace frontend -} // namespace ngraph \ No newline at end of file +} // namespace ov diff --git a/ngraph/frontend/paddlepaddle/src/place.cpp b/ngraph/frontend/paddlepaddle/src/place.cpp index 9f5cbb6dcaea38..873eca5a24e4ae 100644 --- a/ngraph/frontend/paddlepaddle/src/place.cpp +++ b/ngraph/frontend/paddlepaddle/src/place.cpp @@ -7,7 +7,7 @@ #include "decoder.hpp" #include "framework.pb.h" -using namespace ngraph; +using namespace ov; using namespace frontend; bool PlacePDPD::is_input() const { diff --git a/ngraph/frontend/tensorflow/CMakeLists.txt b/ngraph/frontend/tensorflow/CMakeLists.txt index db2a3686ff3208..28aacbfaf413c8 100644 --- a/ngraph/frontend/tensorflow/CMakeLists.txt +++ b/ngraph/frontend/tensorflow/CMakeLists.txt @@ -48,7 +48,7 @@ set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS} PROPERTIES GENERATED TRU set_source_files_properties(${PROTO_SRCS} ${PROTO_HDRS} PROPERTIES COMPILE_OPTIONS -w) # Create library -add_library(${TARGET_NAME} ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS} ${PROTO_SRCS} ${PROTO_HDRS}) +add_library(${TARGET_NAME} SHARED ${LIBRARY_SRC} ${LIBRARY_HEADERS} ${LIBRARY_PUBLIC_HEADERS} ${PROTO_SRCS} ${PROTO_HDRS}) add_library(openvino::frontend::tensorflow ALIAS ${TARGET_NAME}) add_dependencies(${TARGET_NAME} tensorflow_ngraph_frontend_proto) diff --git a/ngraph/frontend/tensorflow/include/tensorflow_frontend/frontend.hpp b/ngraph/frontend/tensorflow/include/tensorflow_frontend/frontend.hpp index 5f0996035b03ab..788946fa473bb0 100644 --- a/ngraph/frontend/tensorflow/include/tensorflow_frontend/frontend.hpp +++ b/ngraph/frontend/tensorflow/include/tensorflow_frontend/frontend.hpp @@ -4,13 +4,14 @@ #pragma once -#include -#include #include #include -#include -#include -#include + +#include "frontend_manager/frontend.hpp" +#include "frontend_manager/input_model.hpp" +#include "openvino/core/node_vector.hpp" +#include "openvino/core/variant.hpp" +#include "tensorflow_frontend/utility.hpp" namespace ov { namespace frontend { @@ -22,7 +23,7 @@ class NodeContext; namespace ov { namespace frontend { -class TF_API FrontEndTF : public ngraph::frontend::FrontEnd { +class TF_API FrontEndTF : public ov::frontend::FrontEnd { public: using CreatorFunction = std::function<::ov::OutputVector(const ::ov::frontend::tf::NodeContext&)>; using TranslatorDictionaryType = std::map; @@ -34,11 +35,11 @@ class TF_API FrontEndTF : public ngraph::frontend::FrontEnd { FrontEndTF(); /// \brief Completely convert the model - /// \return fully converted nGraph function - std::shared_ptr convert(ngraph::frontend::InputModel::Ptr model) const override; + /// \return fully converted ov function + std::shared_ptr convert(ov::frontend::InputModel::Ptr model) const override; /// \brief Completely convert the remaining, not converted part of a function. - /// \param partiallyConverted partially converted nGraph function + /// \param partiallyConverted partially converted ov function void convert(std::shared_ptr partiallyConverted) const override; /// \brief Convert only those parts of the model that can be converted leaving others @@ -46,18 +47,18 @@ class TF_API FrontEndTF : public ngraph::frontend::FrontEnd { /// function or another form of convert function should be called to finalize the /// conversion process. /// \param model Input model - /// \return partially converted nGraph function - std::shared_ptr convert_partially(ngraph::frontend::InputModel::Ptr model) const override; + /// \return partially converted ov function + std::shared_ptr convert_partially(ov::frontend::InputModel::Ptr model) const override; /// \brief Convert operations with one-to-one mapping with decoding nodes. - /// Each decoding node is an nGraph node representing a single FW operation node with + /// Each decoding node is an ov node representing a single FW operation node with /// all attributes represented in FW-independent way. /// \param model Input model - /// \return nGraph function after decoding - std::shared_ptr decode(ngraph::frontend::InputModel::Ptr model) const override; + /// \return ov function after decoding + std::shared_ptr decode(ov::frontend::InputModel::Ptr model) const override; /// \brief Runs normalization passes on function that was loaded with partial conversion - /// \param function partially converted nGraph function + /// \param function partially converted ov function void normalize(std::shared_ptr function) const override; /// \brief Gets name of this FrontEnd. Can be used by clients @@ -69,11 +70,10 @@ class TF_API FrontEndTF : public ngraph::frontend::FrontEnd { /// \brief Check if FrontEndTensorflow can recognize model from given parts bool supported_impl(const std::vector>& variants) const override; - ngraph::frontend::InputModel::Ptr load_impl( - const std::vector>& variants) const override; + ov::frontend::InputModel::Ptr load_impl(const std::vector>& variants) const override; private: - void translate_graph(const ngraph::frontend::InputModel::Ptr& model, + void translate_graph(const ov::frontend::InputModel::Ptr& model, const std::string& model_name, bool fail_fast, bool no_conversion, diff --git a/ngraph/frontend/tensorflow/include/tensorflow_frontend/graph_iterator.hpp b/ngraph/frontend/tensorflow/include/tensorflow_frontend/graph_iterator.hpp index aa5f7399bd5d68..16fe15017078df 100644 --- a/ngraph/frontend/tensorflow/include/tensorflow_frontend/graph_iterator.hpp +++ b/ngraph/frontend/tensorflow/include/tensorflow_frontend/graph_iterator.hpp @@ -4,9 +4,9 @@ #pragma once -#include -#include -#include +#include "openvino/core/variant.hpp" +#include "tensorflow_frontend/decoder.hpp" +#include "tensorflow_frontend/utility.hpp" namespace ov { namespace frontend { diff --git a/ngraph/frontend/tensorflow/include/tensorflow_frontend/utility.hpp b/ngraph/frontend/tensorflow/include/tensorflow_frontend/utility.hpp index 9a08adbfa3885c..ff814e90398185 100644 --- a/ngraph/frontend/tensorflow/include/tensorflow_frontend/utility.hpp +++ b/ngraph/frontend/tensorflow/include/tensorflow_frontend/utility.hpp @@ -4,12 +4,10 @@ #pragma once -#include +#include "frontend_manager/frontend_exceptions.hpp" #ifdef tensorflow_ngraph_frontend_EXPORTS # define TF_API OPENVINO_CORE_EXPORTS #else # define TF_API OPENVINO_CORE_IMPORTS #endif // tensorflow_ngraph_frontend_EXPORTS - -#define NGRAPH_VLOG(I) std::ostringstream() diff --git a/ngraph/frontend/tensorflow/src/decoder_proto.cpp b/ngraph/frontend/tensorflow/src/decoder_proto.cpp index 0464314b5af5cc..784d352df6fb9a 100644 --- a/ngraph/frontend/tensorflow/src/decoder_proto.cpp +++ b/ngraph/frontend/tensorflow/src/decoder_proto.cpp @@ -6,6 +6,8 @@ #include "node_context.hpp" +using namespace std; + namespace ov { namespace frontend { namespace tf { @@ -27,59 +29,69 @@ const std::map<::tensorflow::DataType, ov::element::Type>& TYPE_MAP() { } } // namespace -std::shared_ptr DecoderTFProto::get_attribute(const std::string& name, - const VariantTypeInfo& type_info) const { +template +bool is_type(const VariantTypeInfo& type_info) { + return type_info == VariantWrapper::get_type_info_static(); +} + +template +shared_ptr> create_variant(const T& data) { + return make_shared>(data); +} + +shared_ptr DecoderTFProto::get_attribute(const string& name, const VariantTypeInfo& type_info) const { auto attrs = decode_attribute_helper(name); if (attrs.empty()) { return nullptr; } - if (type_info == VariantWrapper::get_type_info_static()) { - return std::make_shared>(attrs[0].s()); - } else if (type_info == VariantWrapper::get_type_info_static()) { - return std::make_shared>(attrs[0].i()); - } else if (type_info == VariantWrapper>::get_type_info_static()) { - std::vector longs; + if (is_type(type_info)) { + return create_variant(attrs[0].s()); + } + if (is_type(type_info)) { + return create_variant(attrs[0].i()); + } else if (is_type>(type_info)) { + vector longs; longs.reserve(attrs[0].list().i_size()); for (size_t idx = 0; idx < attrs[0].list().i_size(); ++idx) { longs.push_back(attrs[0].list().i(idx)); } - return std::make_shared>>(longs); - } else if (type_info == VariantWrapper::get_type_info_static()) { - return std::make_shared>(static_cast(attrs[0].i())); - } else if (type_info == VariantWrapper>::get_type_info_static()) { - std::vector ints; + return create_variant>(longs); + } else if (is_type(type_info)) { + return create_variant(static_cast(attrs[0].i())); + } else if (is_type>(type_info)) { + vector ints; ints.reserve(attrs[0].list().i_size()); for (size_t idx = 0; idx < attrs[0].list().i_size(); ++idx) { ints.push_back(static_cast(attrs[0].list().i(idx))); } - return std::make_shared>>(ints); - } else if (type_info == VariantWrapper::get_type_info_static()) { - return std::make_shared>(attrs[0].f()); - } else if (type_info == VariantWrapper>::get_type_info_static()) { - std::vector floats; + return create_variant>(ints); + } else if (is_type(type_info)) { + return create_variant(attrs[0].f()); + } else if (is_type>(type_info)) { + vector floats; floats.reserve(attrs[0].list().i_size()); for (size_t idx = 0; idx < attrs[0].list().i_size(); ++idx) { floats.push_back(attrs[0].list().f(idx)); } - return std::make_shared>>(floats); - } else if (type_info == VariantWrapper::get_type_info_static()) { + return create_variant>(floats); + } else if (is_type(type_info)) { auto data_type = attrs[0].type(); - return std::make_shared>(TYPE_MAP().at(data_type)); - } else if (type_info == VariantWrapper::get_type_info_static()) { - return std::make_shared>(attrs[0].b()); - } else if (type_info == VariantWrapper<::tensorflow::DataType>::get_type_info_static()) { - return std::make_shared>(attrs[0].type()); - } else if (type_info == VariantWrapper<::tensorflow::TensorProto>::get_type_info_static()) { - return std::make_shared>(attrs[0].tensor()); - } else if (type_info == VariantWrapper<::ov::PartialShape>::get_type_info_static()) { - std::vector dims; + return create_variant(TYPE_MAP().at(data_type)); + } else if (is_type(type_info)) { + return create_variant(attrs[0].b()); + } else if (is_type<::tensorflow::DataType>(type_info)) { + return create_variant<::tensorflow::DataType>(attrs[0].type()); + } else if (is_type<::tensorflow::TensorProto>(type_info)) { + return create_variant<::tensorflow::TensorProto>(attrs[0].tensor()); + } else if (is_type<::ov::PartialShape>(type_info)) { + vector dims; auto tf_shape = attrs[0].shape(); for (int i = 0; i < tf_shape.dim_size(); i++) { - dims.push_back(tf_shape.dim(i).size()); + dims.emplace_back(tf_shape.dim(i).size()); } auto pshape = ov::PartialShape(dims); - return std::make_shared>(pshape); + return create_variant<::ov::PartialShape>(pshape); } // type is not supported by decoder @@ -91,14 +103,14 @@ size_t DecoderTFProto::get_input_size() const { } void DecoderTFProto::get_input_node(size_t input_port_idx, - std::string& producer_name, + string& producer_name, size_t& producer_output_port_index) const { // TODO: handle body graph nodes with a couple of columns - std::string producer_port_name = m_node_def->input(input_port_idx); + string producer_port_name = m_node_def->input(input_port_idx); auto delim_pos = producer_port_name.find(':'); - if (delim_pos != std::string::npos) { + if (delim_pos != string::npos) { producer_name = producer_port_name.substr(0, delim_pos); - producer_output_port_index = std::stoi(producer_port_name.substr(delim_pos)); + producer_output_port_index = stoi(producer_port_name.substr(delim_pos)); return; } producer_name = producer_port_name; @@ -113,16 +125,11 @@ const std::string& DecoderTFProto::get_op_name() const { return m_node_def->name(); } -std::vector<::tensorflow::AttrValue> DecoderTFProto::decode_attribute_helper(const std::string& name) const { +vector<::tensorflow::AttrValue> DecoderTFProto::decode_attribute_helper(const string& name) const { auto attr_map = m_node_def->attr(); - FRONT_END_GENERAL_CHECK(attr_map.contains(name), - "An error occurred while parsing the ", - name, - " attribute of ", - this->get_op_type(), - "node"); - auto value = m_node_def->attr().at(name); - return {value}; + if (attr_map.contains(name)) + return {m_node_def->attr().at(name)}; + return {}; } } // namespace tf } // namespace frontend diff --git a/ngraph/frontend/tensorflow/src/exceptions.hpp b/ngraph/frontend/tensorflow/src/exceptions.hpp index d8c9744bff5833..211cebbed10ad3 100644 --- a/ngraph/frontend/tensorflow/src/exceptions.hpp +++ b/ngraph/frontend/tensorflow/src/exceptions.hpp @@ -4,7 +4,8 @@ #pragma once #include -#include + +#include "openvino/core/node.hpp" namespace ov { namespace frontend { @@ -12,7 +13,7 @@ namespace tf { class NodeContext; -class OpValidationFailureTF : public ngraph::frontend::OpValidationFailure { +class OpValidationFailureTF : public ov::frontend::OpValidationFailure { public: OpValidationFailureTF(const CheckLocInfo& check_loc_info, const NodeContext& node, const std::string& explanation) : OpValidationFailure(check_loc_info, get_error_msg_prefix_tf(node), explanation) {} @@ -31,5 +32,5 @@ class OpValidationFailureTF : public ngraph::frontend::OpValidationFailure { /// i.e., only if the `cond` evalutes to `false`. /// \throws ::ov::OpValidationFailureTF if `cond` is false. #define TF_OP_VALIDATION_CHECK(node_context, ...) \ - NGRAPH_CHECK_HELPER(::ov::frontend::tf::OpValidationFailureTF, (node_context), __VA_ARGS__) + OPENVINO_ASSERT_HELPER(::ov::frontend::tf::OpValidationFailureTF, (node_context), __VA_ARGS__) } // namespace ov diff --git a/ngraph/frontend/tensorflow/src/frontend.cpp b/ngraph/frontend/tensorflow/src/frontend.cpp index 5ff7358cf02b62..694b04be1fa565 100644 --- a/ngraph/frontend/tensorflow/src/frontend.cpp +++ b/ngraph/frontend/tensorflow/src/frontend.cpp @@ -2,12 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include #include #include "model.hpp" #include "op_table.hpp" +#include "openvino/util/common_util.hpp" #include "pass/transpose_sinking.hpp" #include "tf_framework_node.hpp" #include "utils.hpp" @@ -34,7 +34,6 @@ void translate_framework_node(const std::shared_ptr& node, NodeContext node_ctx(*node->get_decoder(), named_inputs); auto new_node_outputs = translator_it->second(node_ctx); - SetTracingInfo(node_ctx.get_name(), new_node_outputs.front()); auto new_output = new_node_outputs.begin(); auto old_outputs = node->outputs(); @@ -48,7 +47,7 @@ void translate_framework_node(const std::shared_ptr& node, FrontEndTF::FrontEndTF() : m_op_translators(tf::op::get_supported_ops()) {} -void FrontEndTF::translate_graph(const ngraph::frontend::InputModel::Ptr& model, +void FrontEndTF::translate_graph(const ov::frontend::InputModel::Ptr& model, const std::string& model_name, bool fail_fast, bool no_conversion, @@ -64,12 +63,11 @@ void FrontEndTF::translate_graph(const ngraph::frontend::InputModel::Ptr& model, const auto& model_inputs = model_tf->get_inputs(); const auto& model_outputs = model_tf->get_outputs(); const auto& model_frozen_inputs = model_tf->get_tensor_values(); - std::map> translate_map; const auto& TRANSLATE_OP_MAP = m_op_translators; if (no_conversion) { - const std::set required_types{"Placeholder", "_Retval", "NoOp"}; + const std::set required_types{"Placeholder", "NoOp"}; for (const auto& name : required_types) { translate_map.emplace(name, TRANSLATE_OP_MAP.at(name)); } @@ -85,7 +83,6 @@ void FrontEndTF::translate_graph(const ngraph::frontend::InputModel::Ptr& model, "Input with frozen value has been already met: " + frozen_input_name); ng_op_map[frozen_input_name] = {frozen_input_value}; } - // create parameter nodes for all tensor places corresponding to inputs for (const auto& input_place : model_inputs) { FRONT_END_GENERAL_CHECK(input_place->get_names().size() == 1, "Input place must have one name."); @@ -98,17 +95,16 @@ void FrontEndTF::translate_graph(const ngraph::frontend::InputModel::Ptr& model, auto input_shape = input_tensor_place->get_partial_shape(); auto input_type = input_tensor_place->get_element_type(); - auto input_ng_output = ConstructNgNode(input_name, input_type, input_shape); - auto input_ng_node = std::dynamic_pointer_cast(input_ng_output.get_node_shared_ptr()); - params.push_back(input_ng_node); - ng_op_map[input_name] = {input_ng_output}; + auto param = std::make_shared(input_type, input_shape); + set_node_name(input_name, param); + params.push_back(param); + ng_op_map[input_name] = {param}; } // create the nGraph ops from TensorFlow ops for (const auto& operation_place : operation_places) { auto operation_decoder = operation_place->get_decoder(); auto operation_name = operation_place->get_names()[0]; - // output for parameter nodes has been already generated if (ng_op_map.count(operation_name)) { continue; @@ -180,7 +176,7 @@ void FrontEndTF::translate_graph(const ngraph::frontend::InputModel::Ptr& model, auto ng_node = std::make_shared(operation_decoder, ng_inputs, operation_place->get_output_ports().size()); - SetTracingInfo(operation_name, ng_node); + set_node_name(operation_name, ng_node); ng_outputs = ng_node->outputs(); } } @@ -251,7 +247,6 @@ void FrontEndTF::translate_graph(const ngraph::frontend::InputModel::Ptr& model, results.push_back(std::make_shared(node_outputs[producer_port_idx])); } } - // find all terminal nodes in ngraph graph to complete list of results if (results.empty()) { for (const auto& node_output_vector : ng_op_map) { @@ -268,8 +263,7 @@ void FrontEndTF::translate_graph(const ngraph::frontend::InputModel::Ptr& model, // create the nGraph function ng_function = std::make_shared(results, params, model_name); - - NGRAPH_VLOG(5) << "Done with translations"; + NGRAPH_DEBUG << "Done with translations"; } /// \brief Check if FrontEndTensorflow can recognize model from given parts @@ -291,8 +285,7 @@ bool FrontEndTF::supported_impl(const std::vector>& return false; } -ngraph::frontend::InputModel::Ptr FrontEndTF::load_impl( - const std::vector>& variants) const { +ov::frontend::InputModel::Ptr FrontEndTF::load_impl(const std::vector>& variants) const { // TODO: Support other TensorFlow formats: SavedModel, .meta, checkpoint, pbtxt if (variants.size() == 1) { // a case when binary protobuf format is provided @@ -311,19 +304,17 @@ ngraph::frontend::InputModel::Ptr FrontEndTF::load_impl( return nullptr; } -std::shared_ptr FrontEndTF::convert(ngraph::frontend::InputModel::Ptr model) const { +std::shared_ptr FrontEndTF::convert(ov::frontend::InputModel::Ptr model) const { auto model_tf = std::dynamic_pointer_cast(model); - std::shared_ptr f; translate_graph(model_tf, "here_should_be_a_graph_name", true, false, f); normalize(f); - // TODO: check that nGraph function does not contain operations which are not in the opset return f; } -std::shared_ptr FrontEndTF::convert_partially(ngraph::frontend::InputModel::Ptr model) const { +std::shared_ptr FrontEndTF::convert_partially(ov::frontend::InputModel::Ptr model) const { auto model_tf = std::dynamic_pointer_cast(model); std::shared_ptr f; translate_graph(model_tf, "here_should_be_a_graph_name", false, false, f); @@ -331,7 +322,7 @@ std::shared_ptr FrontEndTF::convert_partially(ngraph::frontend::In return f; } -std::shared_ptr FrontEndTF::decode(ngraph::frontend::InputModel::Ptr model) const { +std::shared_ptr FrontEndTF::decode(ov::frontend::InputModel::Ptr model) const { auto model_tf = std::dynamic_pointer_cast(model); std::shared_ptr f; translate_graph(model_tf, "here_should_be_a_graph_name", false, true, f); diff --git a/ngraph/frontend/tensorflow/src/model.cpp b/ngraph/frontend/tensorflow/src/model.cpp index effc82b029da69..98a922a4d3cbe1 100644 --- a/ngraph/frontend/tensorflow/src/model.cpp +++ b/ngraph/frontend/tensorflow/src/model.cpp @@ -54,18 +54,18 @@ void extract_operation_name_and_port(const std::string& port_name, } // namespace tf class InputModelTF::InputModelTFImpl { public: - InputModelTFImpl(const GraphIterator::Ptr& graph_iterator, const ngraph::frontend::InputModel& input_model); - std::vector getInputs() const; - std::vector getOutputs() const; - ngraph::frontend::Place::Ptr getPlaceByTensorName(const std::string& tensorName) const; - void overrideAllOutputs(const std::vector& outputs); - void overrideAllInputs(const std::vector& inputs); - void extractSubgraph(const std::vector& inputs, - const std::vector& outputs); - void setPartialShape(ngraph::frontend::Place::Ptr place, const ov::PartialShape&); - ov::PartialShape getPartialShape(ngraph::frontend::Place::Ptr place) const; - void setElementType(ngraph::frontend::Place::Ptr place, const ov::element::Type&); - void setTensorValue(ngraph::frontend::Place::Ptr place, const void* value); + InputModelTFImpl(const GraphIterator::Ptr& graph_iterator, const ov::frontend::InputModel& input_model); + std::vector getInputs() const; + std::vector getOutputs() const; + ov::frontend::Place::Ptr getPlaceByTensorName(const std::string& tensorName) const; + void overrideAllOutputs(const std::vector& outputs); + void overrideAllInputs(const std::vector& inputs); + void extractSubgraph(const std::vector& inputs, + const std::vector& outputs); + void setPartialShape(ov::frontend::Place::Ptr place, const ov::PartialShape&); + ov::PartialShape getPartialShape(ov::frontend::Place::Ptr place) const; + void setElementType(ov::frontend::Place::Ptr place, const ov::element::Type&); + void setTensorValue(ov::frontend::Place::Ptr place, const void* value); std::vector> get_op_places() const; std::map> get_tensor_places() const { @@ -82,12 +82,12 @@ class InputModelTF::InputModelTFImpl { std::vector> m_op_places; std::map> m_op_places_map; mutable std::map> m_tensor_places; - std::vector m_inputs; - std::vector m_outputs; + std::vector m_inputs; + std::vector m_outputs; std::map> m_tensor_values; std::shared_ptr m_graph_iterator; - const ngraph::frontend::InputModel& m_input_model; + const ov::frontend::InputModel& m_input_model; // shows if some nodes might be deleted from graph bool m_graph_changed = false; @@ -235,22 +235,22 @@ std::vector> InputModelTF::InputModelTFImpl::determin } InputModelTF::InputModelTFImpl::InputModelTFImpl(const GraphIterator::Ptr& graph_iterator, - const ngraph::frontend::InputModel& input_model) + const ov::frontend::InputModel& input_model) : m_input_model(input_model), m_graph_iterator(graph_iterator) { FRONT_END_GENERAL_CHECK(m_graph_iterator, "Null pointer specified for GraphIterator"); loadPlaces(); } -std::vector InputModelTF::InputModelTFImpl::getInputs() const { +std::vector InputModelTF::InputModelTFImpl::getInputs() const { return m_inputs; } -std::vector InputModelTF::InputModelTFImpl::getOutputs() const { +std::vector InputModelTF::InputModelTFImpl::getOutputs() const { return m_outputs; } -ngraph::frontend::Place::Ptr InputModelTF::InputModelTFImpl::getPlaceByTensorName(const std::string& tensorName) const { +ov::frontend::Place::Ptr InputModelTF::InputModelTFImpl::getPlaceByTensorName(const std::string& tensorName) const { if (m_tensor_places.find(tensorName) != m_tensor_places.end()) return m_tensor_places.at(tensorName); @@ -270,7 +270,7 @@ ngraph::frontend::Place::Ptr InputModelTF::InputModelTFImpl::getPlaceByTensorNam return nullptr; } -std::shared_ptr castToTensorPlace(const ngraph::frontend::Place::Ptr& place) { +std::shared_ptr castToTensorPlace(const ov::frontend::Place::Ptr& place) { if (auto var_place = std::dynamic_pointer_cast(place)) { return var_place; } else if (auto in_port_place = std::dynamic_pointer_cast(place)) { @@ -281,7 +281,7 @@ std::shared_ptr castToTensorPlace(const ngraph::frontend::Place:: FRONT_END_GENERAL_CHECK(false, "Cannot cast this Place to TensorPlaceTF."); } -void InputModelTF::InputModelTFImpl::overrideAllInputs(const std::vector& inputs) { +void InputModelTF::InputModelTFImpl::overrideAllInputs(const std::vector& inputs) { m_graph_changed = true; m_inputs.clear(); for (const auto& input_place : inputs) { @@ -289,7 +289,7 @@ void InputModelTF::InputModelTFImpl::overrideAllInputs(const std::vector& outputs) { +void InputModelTF::InputModelTFImpl::overrideAllOutputs(const std::vector& outputs) { m_graph_changed = true; m_outputs.clear(); for (const auto& output_place : outputs) { @@ -297,27 +297,26 @@ void InputModelTF::InputModelTFImpl::overrideAllOutputs(const std::vector& inputs, - const std::vector& outputs) { +void InputModelTF::InputModelTFImpl::extractSubgraph(const std::vector& inputs, + const std::vector& outputs) { m_graph_changed = true; overrideAllInputs(inputs); overrideAllOutputs(outputs); } -void InputModelTF::InputModelTFImpl::setPartialShape(ngraph::frontend::Place::Ptr place, - const ov::PartialShape& p_shape) { +void InputModelTF::InputModelTFImpl::setPartialShape(ov::frontend::Place::Ptr place, const ov::PartialShape& p_shape) { castToTensorPlace(place)->set_partial_shape(p_shape); } -ov::PartialShape InputModelTF::InputModelTFImpl::getPartialShape(ngraph::frontend::Place::Ptr place) const { +ov::PartialShape InputModelTF::InputModelTFImpl::getPartialShape(ov::frontend::Place::Ptr place) const { return castToTensorPlace(place)->get_partial_shape(); } -void InputModelTF::InputModelTFImpl::setElementType(ngraph::frontend::Place::Ptr place, const ov::element::Type& type) { +void InputModelTF::InputModelTFImpl::setElementType(ov::frontend::Place::Ptr place, const ov::element::Type& type) { castToTensorPlace(place)->set_element_type(type); } -void InputModelTF::InputModelTFImpl::setTensorValue(ngraph::frontend::Place::Ptr place, const void* value) { +void InputModelTF::InputModelTFImpl::setTensorValue(ov::frontend::Place::Ptr place, const void* value) { m_graph_changed = true; auto tensor_place = castToTensorPlace(place); auto p_shape = tensor_place->get_partial_shape(); @@ -343,44 +342,44 @@ std::map> InputModelTF::get_tensor_values() const { return _impl->get_tensor_values(); } -std::vector InputModelTF::get_inputs() const { +std::vector InputModelTF::get_inputs() const { return _impl->getInputs(); } -std::vector InputModelTF::get_outputs() const { +std::vector InputModelTF::get_outputs() const { return _impl->getOutputs(); } -ngraph::frontend::Place::Ptr InputModelTF::get_place_by_tensor_name(const std::string& tensorName) const { +ov::frontend::Place::Ptr InputModelTF::get_place_by_tensor_name(const std::string& tensorName) const { return _impl->getPlaceByTensorName(tensorName); } -void InputModelTF::override_all_outputs(const std::vector& outputs) { +void InputModelTF::override_all_outputs(const std::vector& outputs) { _impl->overrideAllOutputs(outputs); } -void InputModelTF::override_all_inputs(const std::vector& inputs) { +void InputModelTF::override_all_inputs(const std::vector& inputs) { _impl->overrideAllInputs(inputs); } -void InputModelTF::extract_subgraph(const std::vector& inputs, - const std::vector& outputs) { +void InputModelTF::extract_subgraph(const std::vector& inputs, + const std::vector& outputs) { _impl->extractSubgraph(inputs, outputs); } -void InputModelTF::set_partial_shape(ngraph::frontend::Place::Ptr place, const ov::PartialShape& p_shape) { +void InputModelTF::set_partial_shape(ov::frontend::Place::Ptr place, const ov::PartialShape& p_shape) { _impl->setPartialShape(place, p_shape); } -ov::PartialShape InputModelTF::get_partial_shape(ngraph::frontend::Place::Ptr place) const { +ov::PartialShape InputModelTF::get_partial_shape(ov::frontend::Place::Ptr place) const { return _impl->getPartialShape(place); } -void InputModelTF::set_element_type(ngraph::frontend::Place::Ptr place, const ov::element::Type& type) { +void InputModelTF::set_element_type(ov::frontend::Place::Ptr place, const ov::element::Type& type) { _impl->setElementType(place, type); } -void InputModelTF::set_tensor_value(ngraph::frontend::Place::Ptr place, const void* value) { +void InputModelTF::set_tensor_value(ov::frontend::Place::Ptr place, const void* value) { _impl->setTensorValue(place, value); } } // namespace frontend diff --git a/ngraph/frontend/tensorflow/src/model.hpp b/ngraph/frontend/tensorflow/src/model.hpp index e3b9d49a599e5d..94936e0684caae 100644 --- a/ngraph/frontend/tensorflow/src/model.hpp +++ b/ngraph/frontend/tensorflow/src/model.hpp @@ -14,7 +14,7 @@ namespace frontend { class OpPlaceTF; class TensorPlaceTF; -class InputModelTF : public ngraph::frontend::InputModel { +class InputModelTF : public ov::frontend::InputModel { friend class FrontEndTF; class InputModelTFImpl; std::shared_ptr _impl; @@ -26,17 +26,17 @@ class InputModelTF : public ngraph::frontend::InputModel { public: explicit InputModelTF(const GraphIterator::Ptr& graph_iterator); - std::vector get_inputs() const override; - std::vector get_outputs() const override; - ngraph::frontend::Place::Ptr get_place_by_tensor_name(const std::string& tensorName) const override; - void override_all_outputs(const std::vector& outputs) override; - void override_all_inputs(const std::vector& inputs) override; - void extract_subgraph(const std::vector& inputs, - const std::vector& outputs) override; - void set_partial_shape(ngraph::frontend::Place::Ptr place, const ov::PartialShape&) override; - ov::PartialShape get_partial_shape(ngraph::frontend::Place::Ptr place) const override; - void set_element_type(ngraph::frontend::Place::Ptr place, const ov::element::Type&) override; - void set_tensor_value(ngraph::frontend::Place::Ptr place, const void* value) override; + std::vector get_inputs() const override; + std::vector get_outputs() const override; + ov::frontend::Place::Ptr get_place_by_tensor_name(const std::string& tensorName) const override; + void override_all_outputs(const std::vector& outputs) override; + void override_all_inputs(const std::vector& inputs) override; + void extract_subgraph(const std::vector& inputs, + const std::vector& outputs) override; + void set_partial_shape(ov::frontend::Place::Ptr place, const ov::PartialShape&) override; + ov::PartialShape get_partial_shape(ov::frontend::Place::Ptr place) const override; + void set_element_type(ov::frontend::Place::Ptr place, const ov::element::Type&) override; + void set_tensor_value(ov::frontend::Place::Ptr place, const void* value) override; }; } // namespace frontend } // namespace ov diff --git a/ngraph/frontend/tensorflow/src/ngraph_conversions.cpp b/ngraph/frontend/tensorflow/src/ngraph_conversions.cpp index 0a3f88b20cfc17..8f1814da8eb2c6 100644 --- a/ngraph/frontend/tensorflow/src/ngraph_conversions.cpp +++ b/ngraph/frontend/tensorflow/src/ngraph_conversions.cpp @@ -10,7 +10,7 @@ namespace ov { namespace frontend { namespace tf { -void NHWCtoNCHW(const std::string& op_name, bool need_convert, ov::Output& node) { +void convert_nhwc_to_nchw(const std::string& op_name, bool need_convert, ov::Output& node) { if (need_convert) { auto rank = node.get_shape().size(); if (rank == 4) { @@ -18,11 +18,10 @@ void NHWCtoNCHW(const std::string& op_name, bool need_convert, ov::Output(node); } - SetTracingInfo(op_name, node); } } -void NCHWtoNHWC(const std::string& op_name, bool need_convert, ov::Output& node) { +void convert_nchw_to_nhwc(const std::string& op_name, bool need_convert, ov::Output& node) { if (need_convert) { auto rank = node.get_shape().size(); if (rank == 4) { @@ -30,7 +29,6 @@ void NCHWtoNHWC(const std::string& op_name, bool need_convert, ov::Output(node); } - SetTracingInfo(op_name, node); } } diff --git a/ngraph/frontend/tensorflow/src/ngraph_conversions.hpp b/ngraph/frontend/tensorflow/src/ngraph_conversions.hpp index 9a411630695795..fb44b2472fff1e 100644 --- a/ngraph/frontend/tensorflow/src/ngraph_conversions.hpp +++ b/ngraph/frontend/tensorflow/src/ngraph_conversions.hpp @@ -4,11 +4,11 @@ #pragma once -#include #include #include #include "graph.pb.h" +#include "openvino/opsets/opset8.hpp" #include "types.pb.h" namespace ov { @@ -17,8 +17,6 @@ namespace tf { using ::tensorflow::DataType; -void TFTensorShapeToNGraphShape(const ::tensorflow::TensorShapeProto& tf_shape, ov::PartialShape* ng_shape); - template void Transpose(ov::Output& node) { static_assert(a < 4 && b < 4 && c < 4 && d < 4, "Number of dimensions cannot exceed 4"); @@ -56,7 +54,7 @@ void Transpose3D(std::shared_ptr& node) { namespace detail { template -void NHWCtoHW(const std::vector& src, std::vector& dst) { +void convert_nhwc_to_hw(const std::vector& src, std::vector& dst) { if (dst.size() >= 2) { dst[0] = src[1]; dst[1] = src[2]; @@ -67,7 +65,7 @@ void NHWCtoHW(const std::vector& src, std::vector& dst) { } template -void NCHWtoHW(const std::vector& src, std::vector& dst) { +void convert_nchw_to_hw(const std::vector& src, std::vector& dst) { if (dst.size() >= 2) { dst[0] = src[2]; dst[1] = src[3]; @@ -78,16 +76,16 @@ void NCHWtoHW(const std::vector& src, std::vector& dst) { } } // namespace detail -void NHWCtoNCHW(const std::string& op_name, bool need_convert, ov::Output& ng_input); +void convert_nhwc_to_nchw(const std::string& op_name, bool need_convert, ov::Output& ng_input); -void NCHWtoNHWC(const std::string& op_name, bool need_convert, ov::Output& ng_node); +void convert_nchw_to_nhwc(const std::string& op_name, bool need_convert, ov::Output& ng_node); template -void NHWCtoHW(bool is_nhwc, const std::vector& src, std::vector& dst) { +void convert_nhwc_to_hw(bool is_nhwc, const std::vector& src, std::vector& dst) { if (is_nhwc) { - detail::NHWCtoHW(src, dst); + detail::convert_nhwc_to_hw(src, dst); } else { - detail::NCHWtoHW(src, dst); + detail::convert_nchw_to_hw(src, dst); } } diff --git a/ngraph/frontend/tensorflow/src/node_context.hpp b/ngraph/frontend/tensorflow/src/node_context.hpp index f5a44e78b5cd3c..e2f92e53884d4b 100644 --- a/ngraph/frontend/tensorflow/src/node_context.hpp +++ b/ngraph/frontend/tensorflow/src/node_context.hpp @@ -3,10 +3,10 @@ // #pragma once -#include #include #include "exceptions.hpp" +#include "openvino/core/variant.hpp" #include "place.hpp" #include "tensor.pb.h" #include "types.pb.h" @@ -80,7 +80,7 @@ class NodeContext { } /// Detects if there is at least one input attached with a given name - bool has_ng_input(const size_t& port_index) const { + bool has_input(const size_t& port_index) const { auto found = m_name_map.find(port_index); if (found != m_name_map.end()) return !found->second.empty(); @@ -89,19 +89,19 @@ class NodeContext { /// Returns exactly one input with a given name; throws if there is no inputs or /// there are more than one input - Output get_ng_input(const size_t& port_index) const { + Output get_input(const size_t& port_index) const { FRONT_END_GENERAL_CHECK(m_name_map.at(port_index).size() == 1); return m_name_map.at(port_index).at(0); } /// Returns all inputs with a given name - OutputVector get_ng_inputs(const size_t& port_index) const { + OutputVector get_inputs(const size_t& port_index) const { return m_name_map.at(port_index); } /// Returns all inputs in order they appear in map. This is used for FrameworkNode /// creation - OutputVector get_all_ng_inputs() const { + OutputVector get_all_inputs() const { OutputVector res; for (const auto& entry : m_name_map) { res.insert(res.end(), entry.second.begin(), entry.second.end()); @@ -110,7 +110,7 @@ class NodeContext { } /// Get a number of inputs - size_t get_ng_input_size() const { + size_t get_input_size() const { return m_name_map.size(); } diff --git a/ngraph/frontend/tensorflow/src/op/addN.cpp b/ngraph/frontend/tensorflow/src/op/addN.cpp index 89d2e80e0e0806..7b08abde1773e1 100644 --- a/ngraph/frontend/tensorflow/src/op/addN.cpp +++ b/ngraph/frontend/tensorflow/src/op/addN.cpp @@ -3,8 +3,9 @@ // #include -#include -#include + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -14,20 +15,18 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateAddNOp(const NodeContext& node) { - OutputVector ng_arg_vec = node.get_all_ng_inputs(); - - auto ng_addn = std::accumulate(std::next(ng_arg_vec.begin()), - ng_arg_vec.end(), - ng_arg_vec.at(0), - [&node](Output a, Output b) { - return ConstructNgNode(node.get_name(), a, b); - }); // accumulation: start with - // first element. default op is - // addition - return {ng_addn}; +OutputVector translate_add_n_op(const NodeContext& node) { + OutputVector ng_arg_vec = node.get_all_inputs(); + auto res = std::accumulate(std::next(ng_arg_vec.begin()), + ng_arg_vec.end(), + ng_arg_vec.at(0), + [](const Output& a, const Output& b) -> shared_ptr { + return make_shared(a, b); + }); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/arg_min_max.cpp b/ngraph/frontend/tensorflow/src/op/arg_min_max.cpp index cbd0246f859309..50146a386c6adf 100644 --- a/ngraph/frontend/tensorflow/src/op/arg_min_max.cpp +++ b/ngraph/frontend/tensorflow/src/op/arg_min_max.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -14,46 +14,43 @@ namespace tf { namespace op { OutputVector TranslateArgMinMax(const NodeContext& node, std::string mode) { - Output ng_input = node.get_ng_input(0); + Output ng_input = node.get_input(0); std::vector tf_dim; - GetStaticInputVector(node, 1, &tf_dim); + get_static_input_vec(node, 1, &tf_dim); Shape input_shape = ng_input.get_shape(); size_t input_rank = input_shape.size(); - if (tf_dim.size() != 1) { - throw errors::InvalidArgument("ArgMax Op: dimension must be scalar, operates on a single axis"); - } + TF_OP_VALIDATION_CHECK(node, tf_dim.size() == 1, "ArgMax Op: dimension must be scalar, operates on a single axis"); // If input dimension is negative, make it positive if (tf_dim[0] < 0) { - NGRAPH_VLOG(3) << "Input dimension is negative, make it positive " << tf_dim[0]; + NGRAPH_DEBUG << "Input dimension is negative, make it positive " << tf_dim[0]; tf_dim[0] = (int64_t)input_rank + tf_dim[0]; } - NGRAPH_VLOG(3) << "Axis along which to compute " << tf_dim[0]; + NGRAPH_DEBUG << "Axis along which to compute " << tf_dim[0]; size_t k_axis = tf_dim[0]; auto ng_et = node.get_attribute("output_type"); - auto ng_k = ConstructNgNode(node.get_name(), element::i64, Shape{}, std::vector({1})); + auto ng_k = make_shared(element::i64, Shape{}, std::vector({1})); std::string sort = "none"; auto ng_topk = std::make_shared(ng_input, ng_k, k_axis, mode, sort, ng_et); auto ng_indices = ng_topk->output(1); int axis = ng_topk->get_axis(); - auto axis_to_remove = - ConstructNgNode(node.get_name(), element::i64, Shape{1}, std::vector({axis})); - auto reshaped_indices = ConstructNgNode(node.get_name(), ng_indices, axis_to_remove); - SetTracingInfo(node.get_name(), reshaped_indices); - return {reshaped_indices}; + auto axis_to_remove = make_shared(element::i64, Shape{1}, std::vector({axis})); + auto res = make_shared(ng_indices, axis_to_remove); + set_node_name(node.get_name(), res); + return {res}; } -OutputVector TranslateArgMaxOp(const NodeContext& node) { +OutputVector translate_arg_max_op(const NodeContext& node) { return (TranslateArgMinMax(node, "max")); } -OutputVector TranslateArgMinOp(const NodeContext& node) { +OutputVector translate_arg_min_op(const NodeContext& node) { return (TranslateArgMinMax(node, "min")); } } // namespace op diff --git a/ngraph/frontend/tensorflow/src/op/avg_pool.cpp b/ngraph/frontend/tensorflow/src/op/avg_pool.cpp index c4d5fd5f297836..ef34cd07cdefd8 100644 --- a/ngraph/frontend/tensorflow/src/op/avg_pool.cpp +++ b/ngraph/frontend/tensorflow/src/op/avg_pool.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,57 +13,58 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateAvgPoolOp(const NodeContext& node) { - Output ng_input = node.get_ng_input(0); +OutputVector translate_avg_pool_op(const NodeContext& node) { + Output ng_input = node.get_input(0); auto tf_strides = node.get_attribute>("strides"); auto tf_ksize = node.get_attribute>("ksize"); auto tf_padding_type = node.get_attribute("padding"); auto tf_data_format = node.get_attribute("data_format"); - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("AvgPool data format is neither NHWC nor NCHW"); - } + + TF_OP_VALIDATION_CHECK(node, + tf_data_format == "NHWC" || tf_data_format == "NCHW", + "AvgPool data format is neither NHWC nor NCHW"); bool is_nhwc = (tf_data_format == "NHWC"); Strides ng_strides(2); Shape ng_image_shape(2); Shape ng_kernel_shape(2); - NHWCtoHW(is_nhwc, tf_strides, ng_strides); - NHWCtoHW(is_nhwc, ng_input.get_shape(), ng_image_shape); - NHWCtoHW(is_nhwc, tf_ksize, ng_kernel_shape); - NHWCtoNCHW(node.get_name(), is_nhwc, ng_input); + convert_nhwc_to_hw(is_nhwc, tf_strides, ng_strides); + convert_nhwc_to_hw(is_nhwc, ng_input.get_shape(), ng_image_shape); + convert_nhwc_to_hw(is_nhwc, tf_ksize, ng_kernel_shape); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, ng_input); CoordinateDiff padding_below; CoordinateDiff padding_above; Shape ng_dilations{1, 1}; - MakePadding(tf_padding_type, - ng_image_shape, - ng_kernel_shape, - ng_strides, - ng_dilations, - padding_below, - padding_above); + make_padding(tf_padding_type, + ng_image_shape, + ng_kernel_shape, + ng_strides, + ng_dilations, + padding_below, + padding_above); // TODO: remove this once nGraph supports negative padding // (CoordinateDiff) for AvgPool Shape ng_padding_below(padding_below.begin(), padding_below.end()); Shape ng_padding_above(padding_above.begin(), padding_above.end()); - Output ng_avgpool = ConstructNgNode(node.get_name(), - ng_input, - ng_strides, - ng_padding_below, - ng_padding_above, - ng_kernel_shape, - true, - ov::op::RoundingType::FLOOR); - - NCHWtoNHWC(node.get_name(), is_nhwc, ng_avgpool); + auto res_node = make_shared(ng_input, + ng_strides, + ng_padding_below, + ng_padding_above, + ng_kernel_shape, + true, + ov::op::RoundingType::FLOOR); + auto res = res_node->output(0); - return {ng_avgpool}; + convert_nchw_to_nhwc(node.get_name(), is_nhwc, res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/bias_add.cpp b/ngraph/frontend/tensorflow/src/op/bias_add.cpp index f12f1630aedc22..518116c86c857e 100644 --- a/ngraph/frontend/tensorflow/src/op/bias_add.cpp +++ b/ngraph/frontend/tensorflow/src/op/bias_add.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,20 +13,18 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateBiasAddOp(const NodeContext& node) { - Output ng_input = node.get_ng_input(0), ng_bias = node.get_ng_input(1); +OutputVector translate_bias_add_op(const NodeContext& node) { + Output ng_input = node.get_input(0), ng_bias = node.get_input(1); std::string tf_data_format = node.get_attribute("data_format", "NHWC"); - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("BiasAdd data format is neither NHWC nor NCHW"); - } + TF_OP_VALIDATION_CHECK(node, + tf_data_format == "NHWC" || tf_data_format == "NCHW", + "BiasAdd data format is neither NHWC nor NCHW"); auto ng_input_shape = ng_input.get_shape(); auto ng_bias_shape = ng_bias.get_shape(); - if (ng_bias_shape.size() != 1) { - throw errors::InvalidArgument("Bias argument to BiasAdd does not have one dimension"); - } + TF_OP_VALIDATION_CHECK(node, ng_bias_shape.size() == 1, "Bias argument to BiasAdd does not have one dimension"); // We'll choose reshape over broadcast // Reshape the bias to (1, C, 1, ...) if input is channels-first. @@ -42,14 +40,14 @@ OutputVector TranslateBiasAddOp(const NodeContext& node) { } } auto target_shape_node = make_shared(element::i64, Shape{ng_input_shape.size()}, target_shape); - ng_bias_reshaped = ConstructNgNode(node.get_name(), ng_bias, target_shape_node, false); + ng_bias_reshaped = make_shared(ng_bias, target_shape_node, false); } - Output ng_add = ConstructNgNode(node.get_name(), ng_input, ng_bias_reshaped); - - return {ng_add}; + auto res = make_shared(ng_input, ng_bias_reshaped); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/binary_op.cpp b/ngraph/frontend/tensorflow/src/op/binary_op.cpp index 8c31910d537140..97c824aac504c2 100644 --- a/ngraph/frontend/tensorflow/src/op/binary_op.cpp +++ b/ngraph/frontend/tensorflow/src/op/binary_op.cpp @@ -2,96 +2,59 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; -// Helper function to translate a binary op -// Parameters: -// -// TFNodeDecoder* op - TF op being translated. Must have only two -// inputs. -// const std::vector& static_input_map - the static input -// map Builder::OpMap& ng_op_map - The TF-to-nGraph op map. std::function(Output, -// Output)> -// create_binary_op - Function to construct the graph implementing -// the binary op, given the 2 ng_inputs to the -// binaryop -// Example Usage: -// -// if (op->type_string() == "SquaredDifference") { -// TF_RETURN_IF_ERROR(TranslateBinaryOp(op, ng_op_map, -// [](Output ng_input1, Output -// ng_input2) { -// auto ng_diff = Output(input1, -// input2); -// return Output(ng_diff,ng_diff); -// })); -// } -// - namespace ov { namespace frontend { namespace tf { namespace op { -OutputVector TranslateBinaryOp(const NodeContext& node, - std::function(Output&, Output&)> create_binary_op) { - Output ng_lhs = node.get_ng_input(0), ng_rhs = node.get_ng_input(1); - auto ng_node = create_binary_op(ng_lhs, ng_rhs); - // TODO do we need it? - /* if (ng_node != ng_lhs && ng_node != ng_rhs) { - Builder::SetTracingInfo(node.get_name(), ng_node); - }*/ +OutputVector translate_binary_op(const NodeContext& node, + const std::function(Output&, Output&)>& create_binary_op) { + auto ng_lhs = node.get_input(0); + auto ng_rhs = node.get_input(1); + auto ng_node = create_binary_op(ng_lhs, ng_rhs); + set_node_name(node.get_name(), ng_node.get_node_shared_ptr()); return {ng_node}; } -OutputVector TranslateFloorDivOp(const NodeContext& node) { - auto floordiv_fn = [&node](Output x, Output y) { - return ConstructNgNode(node.get_name(), ConstructNgNode(node.get_name(), x, y)); +OutputVector translate_floor_div_op(const NodeContext& node) { + auto floordiv_fn = [](const Output& x, const Output& y) { + return make_shared(make_shared(x, y)); }; - return TranslateBinaryOp(node, floordiv_fn); + return translate_binary_op(node, floordiv_fn); } -// Helper function to translate a binary op in cases where there is a one-to-one -// mapping from TensorFlow ops to nGraph ops. -// -// Example usage: -// -// if (n->type_string == "Add") { -// TF_RETURN_IF_ERROR(TranslateBinaryOp(op, -// static_input_map, -// ng_op_map)); -// } -// - template -OutputVector TranslateBinaryOp(const NodeContext& node) { - return TranslateBinaryOp(node, [&node](Output& ng_lhs, Output& ng_rhs) { - return ConstructNgNode(node.get_name(), ng_lhs, ng_rhs); +OutputVector translate_binary_op(const NodeContext& node) { + return translate_binary_op(node, [](Output& ng_lhs, Output& ng_rhs) { + return make_shared(ng_lhs, ng_rhs); }); } -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); -template OutputVector TranslateBinaryOp(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); +template OutputVector translate_binary_op(const NodeContext& node); } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/cast.cpp b/ngraph/frontend/tensorflow/src/op/cast.cpp index e85195969e61b4..9fe2b177c0fe98 100644 --- a/ngraph/frontend/tensorflow/src/op/cast.cpp +++ b/ngraph/frontend/tensorflow/src/op/cast.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,14 +13,16 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateCastOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0); +OutputVector translate_cast_op(const NodeContext& node) { + auto ng_input = node.get_input(0); auto ng_et = node.get_attribute("DstT"); - return {ConstructNgNode(node.get_name(), ng_input, ng_et)}; + auto res = make_shared(ng_input, ng_et); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/concat.cpp b/ngraph/frontend/tensorflow/src/op/concat.cpp index 61355df5aea7fd..513770039aa576 100644 --- a/ngraph/frontend/tensorflow/src/op/concat.cpp +++ b/ngraph/frontend/tensorflow/src/op/concat.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov; @@ -16,29 +16,35 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateConcatV2Op(const NodeContext& node) { - ValidateInputCountMin(node, 2); +OutputVector translate_concat_op(const NodeContext& node) { + size_t axis_idx, concat_idx_start, concat_idx_stop; + if (node.get_op_type() == "ConcatV2") { + axis_idx = node.get_input_size() - 1; + concat_idx_start = 0; + concat_idx_stop = node.get_input_size() - 1; + } else if (node.get_op_type() == "Concat") { + axis_idx = 0; + concat_idx_start = 1; + concat_idx_stop = node.get_input_size(); + } else { + TF_OP_VALIDATION_CHECK(node, false, "Incorrect operation type."); + } std::vector tf_concat_axis_vec; - GetStaticInputVector(node, node.get_ng_input_size() - 1, &tf_concat_axis_vec); - + get_static_input_vec(node, axis_idx, &tf_concat_axis_vec); int64_t concat_axis = tf_concat_axis_vec[0]; - if (concat_axis < 0) { - auto ng_first_arg = node.get_ng_input(0); - concat_axis += int64_t(ng_first_arg.get_shape().size()); - } - OutputVector ng_args; - - for (int i = 0; i < node.get_ng_input_size() - 1; i++) { - Output ng_arg = node.get_ng_input(i); + for (int i = concat_idx_start; i < concat_idx_stop; i++) { + Output ng_arg = node.get_input(i); ng_args.push_back(ng_arg); } - return {ConstructNgNode(node.get_name(), ng_args, size_t(concat_axis))}; + auto res = make_shared(ng_args, size_t(concat_axis)); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/const.cpp b/ngraph/frontend/tensorflow/src/op/const.cpp index c142ea1ad40d1e..f0dee56b3016f0 100644 --- a/ngraph/frontend/tensorflow/src/op/const.cpp +++ b/ngraph/frontend/tensorflow/src/op/const.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -15,54 +15,56 @@ namespace op { namespace { using ConstMap = std::map&)>, + std::pair&)>, const ov::element::Type>>; const ConstMap& TF_NGRAPH_CONST_MAP() { static const ConstMap the_map = { - {ov::element::f32, make_pair(MakeConstOp, ov::element::f32)}, - {ov::element::f64, make_pair(MakeConstOp, ov::element::f64)}, - {ov::element::i8, make_pair(MakeConstOp, ov::element::i8)}, - {ov::element::i16, make_pair(MakeConstOp, ov::element::i16)}, + {ov::element::f32, make_pair(make_const_op, ov::element::f32)}, + {ov::element::f64, make_pair(make_const_op, ov::element::f64)}, + {ov::element::i8, make_pair(make_const_op, ov::element::i8)}, + {ov::element::i16, make_pair(make_const_op, ov::element::i16)}, #if 0 - {DataType::DT_QINT8, make_pair(MakeConstOp, ov::element::i8)}, - {DataType::DT_QUINT8, make_pair(MakeConstOp, ov::element::u8)}, - {DataType::DT_QUINT16, make_pair(MakeConstOp, ov::element::u16)}, + {DataType::DT_QINT8, make_pair(make_const_op, ov::element::i8)}, + {DataType::DT_QUINT8, make_pair(make_const_op, ov::element::u8)}, + {DataType::DT_QUINT16, make_pair(make_const_op, ov::element::u16)}, #endif - {ov::element::i32, make_pair(MakeConstOp, ov::element::i32)}, - {ov::element::i64, make_pair(MakeConstOp, ov::element::i64)}, - {ov::element::u8, make_pair(MakeConstOp, ov::element::u8)}, - {ov::element::u16, make_pair(MakeConstOp, ov::element::u16)}, - {ov::element::boolean, make_pair(MakeConstOp, ov::element::boolean)} + {ov::element::i32, make_pair(make_const_op, ov::element::i32)}, + {ov::element::i64, make_pair(make_const_op, ov::element::i64)}, + {ov::element::u8, make_pair(make_const_op, ov::element::u8)}, + {ov::element::u16, make_pair(make_const_op, ov::element::u16)}, + {ov::element::boolean, make_pair(make_const_op, ov::element::boolean)} }; return the_map; } } // namespace -OutputVector TranslateConstOp(const NodeContext& node) { +OutputVector translate_const_op(const NodeContext& node) { auto dt = node.get_attribute("dtype"); - Output ng_node; + Output res; // For some reason the following do not work (no specialization of // tensorflow::checkpoint::SavedTypeTraits...) // case DataType::DT_UINT32: - // TF_RETURN_IF_ERROR(MakeConstOp(op, element::u32, + // TF_RETURN_IF_ERROR(make_const_op(op, element::u32, // &ng_node)); // break; // case DataType::DT_UINT64: - // TF_RETURN_IF_ERROR(MakeConstOp(op, element::u64, + // TF_RETURN_IF_ERROR(make_const_op(op, element::u64, // &ng_node)); // break; try { const auto& func_param = TF_NGRAPH_CONST_MAP().at(dt); - TF_RETURN_IF_ERROR(func_param.first(node, func_param.second, ng_node)); + func_param.first(node, func_param.second, res); } catch (const std::out_of_range&) { - throw errors::Unimplemented("Failed to translate Constant with target ngraph type:" + dt.get_type_name()); + TF_OP_VALIDATION_CHECK(node, + false, + "Failed to translate Constant with target ngraph type:" + dt.get_type_name()); } - - return {ng_node}; + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/conv_2d.cpp b/ngraph/frontend/tensorflow/src/op/conv_2d.cpp index f797bd5c096ac2..599354781a9c76 100644 --- a/ngraph/frontend/tensorflow/src/op/conv_2d.cpp +++ b/ngraph/frontend/tensorflow/src/op/conv_2d.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,24 +13,26 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateConv2DOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0), ng_filter = node.get_ng_input(1); +OutputVector translate_conv_2d_op(const NodeContext& node) { + auto ng_input = node.get_input(0), ng_filter = node.get_input(1); auto tf_strides = node.get_attribute>("strides"); auto tf_dilations = node.get_attribute>("dilations"); auto tf_padding_type = node.get_attribute("padding"); auto tf_data_format = node.get_attribute("data_format"); - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("Conv2D data format is neither NHWC nor NCHW"); - } + TF_OP_VALIDATION_CHECK(node, + tf_data_format == "NHWC" || tf_data_format == "NCHW", + "Conv2D data format is neither NHWC nor NCHW"); bool is_nhwc = (tf_data_format == "NHWC"); // TF Kernel Test Checks // Strides in the batch and depth dimension is not supported if (tf_strides[0] != 1 || tf_strides[is_nhwc ? 3 : 1] != 1) { - throw errors::InvalidArgument("Strides in batch and depth dimensions is not supported: " + node.get_op_type()); + TF_OP_VALIDATION_CHECK(node, + false, + "Strides in batch and depth dimensions is not supported: " + node.get_op_type()); } Strides ng_strides(2); @@ -38,37 +40,32 @@ OutputVector TranslateConv2DOp(const NodeContext& node) { Shape ng_image_shape(2); Shape ng_kernel_shape(2); - NHWCtoHW(is_nhwc, tf_strides, ng_strides); - NHWCtoHW(is_nhwc, ng_input.get_shape(), ng_image_shape); - NHWCtoHW(is_nhwc, tf_dilations, ng_dilations); - NHWCtoNCHW(node.get_name(), is_nhwc, ng_input); + convert_nhwc_to_hw(is_nhwc, tf_strides, ng_strides); + convert_nhwc_to_hw(is_nhwc, ng_input.get_shape(), ng_image_shape); + convert_nhwc_to_hw(is_nhwc, tf_dilations, ng_dilations); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, ng_input); auto& ng_filter_shape = ng_filter.get_shape(); ng_kernel_shape[0] = ng_filter_shape[0]; ng_kernel_shape[1] = ng_filter_shape[1]; Transpose<3, 2, 0, 1>(ng_filter); - SetTracingInfo(node.get_name(), ng_filter); CoordinateDiff ng_padding_below; CoordinateDiff ng_padding_above; - MakePadding(tf_padding_type, - ng_image_shape, - ng_kernel_shape, - ng_strides, - ng_dilations, - ng_padding_below, - ng_padding_above); + make_padding(tf_padding_type, + ng_image_shape, + ng_kernel_shape, + ng_strides, + ng_dilations, + ng_padding_below, + ng_padding_above); - Output ng_conv = ConstructNgNode(node.get_name(), - ng_input, - ng_filter, - ng_strides, - ng_padding_below, - ng_padding_above, - ng_dilations); + Output res = + make_shared(ng_input, ng_filter, ng_strides, ng_padding_below, ng_padding_above, ng_dilations); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_conv); - return {ng_conv}; + convert_nchw_to_nhwc(node.get_name(), is_nhwc, res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/conv_2d_backprop.cpp b/ngraph/frontend/tensorflow/src/op/conv_2d_backprop.cpp index 43491428c8bc8a..6c40767a904368 100644 --- a/ngraph/frontend/tensorflow/src/op/conv_2d_backprop.cpp +++ b/ngraph/frontend/tensorflow/src/op/conv_2d_backprop.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,8 +13,8 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateConv2DBackpropInputOp(const NodeContext& node) { - auto ng_filter = node.get_ng_input(1), ng_out_backprop = node.get_ng_input(2); +OutputVector translate_conv_2d_backprop_input_op(const NodeContext& node) { + auto ng_filter = node.get_input(1), ng_out_backprop = node.get_input(2); // TODO: refactor me to be less redundant with other convolution ops auto tf_strides = node.get_attribute>("strides"); @@ -22,17 +22,17 @@ OutputVector TranslateConv2DBackpropInputOp(const NodeContext& node) { auto tf_padding_type = node.get_attribute("padding"); auto tf_data_format = node.get_attribute("data_format"); - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("Conv2DBackpropInput data format is neither NHWC nor NCHW: %s" + tf_data_format); - } + TF_OP_VALIDATION_CHECK(node, + tf_data_format == "NHWC" || tf_data_format == "NCHW", + "Conv2DBackpropInput data format is neither NHWC nor NCHW"); std::vector tf_input_sizes; - GetStaticInputVector(node, 0, &tf_input_sizes); + get_static_input_vec(node, 0, &tf_input_sizes); if (std::any_of(tf_input_sizes.begin(), tf_input_sizes.end(), [](int32_t size) { return size <= 0; })) { - throw errors::InvalidArgument("Conv2DBackpropInput input sizes must be positive integers"); + FRONT_END_THROW("Conv2DBackpropInput input sizes must be positive integers"); } bool is_nhwc = (tf_data_format == "NHWC"); @@ -43,10 +43,10 @@ OutputVector TranslateConv2DBackpropInputOp(const NodeContext& node) { Shape ng_kernel_shape(2); Shape ng_batch_shape(4); - NHWCtoHW(is_nhwc, tf_strides, ng_strides); - NHWCtoHW(is_nhwc, tf_dilations, ng_dilations); - NHWCtoHW(is_nhwc, tf_input_sizes, ng_image_shape); - NHWCtoNCHW(node.get_name(), is_nhwc, ng_out_backprop); + convert_nhwc_to_hw(is_nhwc, tf_strides, ng_strides); + convert_nhwc_to_hw(is_nhwc, tf_dilations, ng_dilations); + convert_nhwc_to_hw(is_nhwc, tf_input_sizes, ng_image_shape); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, ng_out_backprop); if (is_nhwc) { ng_batch_shape = {static_cast(tf_input_sizes[0]), static_cast(tf_input_sizes[3]), @@ -63,36 +63,35 @@ OutputVector TranslateConv2DBackpropInputOp(const NodeContext& node) { ng_kernel_shape[0] = ng_filter_shape[0]; ng_kernel_shape[1] = ng_filter_shape[1]; Transpose<3, 2, 0, 1>(ng_filter); - SetTracingInfo(node.get_name(), ng_filter); CoordinateDiff ng_padding_below; CoordinateDiff ng_padding_above; - MakePadding(tf_padding_type, - ng_image_shape, - ng_kernel_shape, - ng_strides, - ng_dilations, - ng_padding_below, - ng_padding_above); - - auto ng_output_shape = ConstructNgNode(node.get_name(), - element::i64, - Shape{ng_batch_shape.size() - 2}, - vector(ng_batch_shape.begin() + 2, ng_batch_shape.end())); - - auto ng_data = ConstructNgNode(node.get_name(), - ng_out_backprop, - ng_filter, - ng_output_shape, - ng_strides, - ng_padding_below, - ng_padding_above, - ng_dilations); - - NCHWtoNHWC(node.get_name(), is_nhwc, ng_data); - return {ng_data}; + make_padding(tf_padding_type, + ng_image_shape, + ng_kernel_shape, + ng_strides, + ng_dilations, + ng_padding_below, + ng_padding_above); + + auto ng_output_shape = make_shared(element::i64, + Shape{ng_batch_shape.size() - 2}, + vector(ng_batch_shape.begin() + 2, ng_batch_shape.end())); + + auto res_node = make_shared(ng_out_backprop, + ng_filter, + ng_output_shape, + ng_strides, + ng_padding_below, + ng_padding_above, + ng_dilations); + auto res = res_node->output(0); + + convert_nchw_to_nhwc(node.get_name(), is_nhwc, res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/conv_3d.cpp b/ngraph/frontend/tensorflow/src/op/conv_3d.cpp index d40220edd4b725..1a76e9419ab544 100644 --- a/ngraph/frontend/tensorflow/src/op/conv_3d.cpp +++ b/ngraph/frontend/tensorflow/src/op/conv_3d.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -14,17 +14,17 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateConv3DOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0), ng_filter = node.get_ng_input(1); +OutputVector translate_conv_3d_op(const NodeContext& node) { + auto ng_input = node.get_input(0), ng_filter = node.get_input(1); auto tf_strides = node.get_attribute>("strides"); auto tf_dilations = node.get_attribute>("dilations"); auto tf_padding_type = node.get_attribute("padding"); auto tf_data_format = node.get_attribute("data_format"); - if (tf_data_format != "NDHWC" && tf_data_format != "NCDHW") { - throw errors::InvalidArgument("Conv3D data format is neither NDHWC nor NCDHW"); - } + TF_OP_VALIDATION_CHECK(node, + tf_data_format == "NHWC" || tf_data_format == "NCHW", + "Conv3D data format is neither NHWC nor NCHW"); bool is_ndhwc = (tf_data_format == "NDHWC"); @@ -42,40 +42,36 @@ OutputVector TranslateConv3DOp(const NodeContext& node) { Shape ng_image_shape(3); Shape ng_kernel_shape(3); - NHWCtoHW(is_ndhwc, tf_strides, ng_strides); - NHWCtoHW(is_ndhwc, ng_input.get_shape(), ng_image_shape); - NHWCtoHW(is_ndhwc, tf_dilations, ng_dilations); - NHWCtoNCHW(node.get_name(), is_ndhwc, ng_input); + convert_nhwc_to_hw(is_ndhwc, tf_strides, ng_strides); + convert_nhwc_to_hw(is_ndhwc, ng_input.get_shape(), ng_image_shape); + convert_nhwc_to_hw(is_ndhwc, tf_dilations, ng_dilations); + convert_nhwc_to_nchw(node.get_name(), is_ndhwc, ng_input); auto& ng_filter_shape = ng_filter.get_shape(); ng_kernel_shape[0] = ng_filter_shape[0]; ng_kernel_shape[1] = ng_filter_shape[1]; ng_kernel_shape[2] = ng_filter_shape[2]; Transpose3D<4, 3, 0, 1, 2>(ng_filter); - SetTracingInfo(node.get_name(), ng_filter); CoordinateDiff ng_padding_below; CoordinateDiff ng_padding_above; - MakePadding(tf_padding_type, - ng_image_shape, - ng_kernel_shape, - ng_strides, - ng_dilations, - ng_padding_below, - ng_padding_above); + make_padding(tf_padding_type, + ng_image_shape, + ng_kernel_shape, + ng_strides, + ng_dilations, + ng_padding_below, + ng_padding_above); - Output ng_conv = ConstructNgNode(node.get_name(), - ng_input, - ng_filter, - ng_strides, - ng_padding_below, - ng_padding_above, - ng_dilations); + auto res_node = + make_shared(ng_input, ng_filter, ng_strides, ng_padding_below, ng_padding_above, ng_dilations); + auto res = res_node->output(0); - NCHWtoNHWC(node.get_name(), is_ndhwc, ng_conv); - return {ng_conv}; + convert_nchw_to_nhwc(node.get_name(), is_ndhwc, res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/crop_and_resize.cpp b/ngraph/frontend/tensorflow/src/op/crop_and_resize.cpp new file mode 100644 index 00000000000000..763e9dea540a7b --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/crop_and_resize.cpp @@ -0,0 +1,142 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_crop_and_resize_op(const NodeContext& node) { + /// ng_input: [batch, image_height, image_width, depth] + /// ng_boxes: [num_boxes, 4]; each box is a normalized [0.to 1.] co-ordinate + /// [y1, + /// x1, y2, x2] + /// ng_box_ind: [num_boxes]; i-th ng_box_ind refers to the image to crop and + /// ranges from 0 to batch + /// ng_crop_size: [crop_height, crop_width]; + + /// for each box b specified in ng_boxes: + /// 1. crop ng_input[ng_box_ind[b]] w/ co-ordinates in ng_boxes + /// 2. resize according to method + + auto ng_input = node.get_input(0); + auto ng_boxes = node.get_input(1); + auto ng_box_ind = node.get_input(2); + auto ng_size = node.get_input(3); + + auto resize_method = node.get_attribute("method"); + + TF_OP_VALIDATION_CHECK(node, + ng_input.get_partial_shape().is_static() && ng_boxes.get_partial_shape().is_static() && + ng_box_ind.get_partial_shape().is_static() && ng_size.get_partial_shape().is_static(), + "Dynamic shapes are not supported."); + + auto spatial_shape = ng_input.get_shape(); + auto image_height = spatial_shape[1]; + auto image_width = spatial_shape[2]; + auto image_depth = spatial_shape[3]; + + auto const_boxes = dynamic_pointer_cast(ng_boxes.get_node_shared_ptr()); + auto const_box_ind = dynamic_pointer_cast(ng_boxes.get_node_shared_ptr()); + auto const_crop_size = dynamic_pointer_cast(ng_boxes.get_node_shared_ptr()); + + TF_OP_VALIDATION_CHECK(node, + const_boxes && const_box_ind && const_crop_size, + "Boxes, BoxIndexes, CropSize inputs must be constant."); + + auto boxes = const_boxes->cast_vector(); + auto box_ind = const_box_ind->cast_vector(); + auto crop_size = const_crop_size->cast_vector(); + + OutputVector ng_crop_outputs(box_ind.size()); + if (box_ind.empty()) { + return make_shared(element::f32, + Shape{0, + static_cast(crop_size.at(0)), + static_cast(crop_size.at(1)), + image_depth}, + vector({})) + ->outputs(); + } else { + for (int i = 0; i < box_ind.size(); i++) { + int y1, x1, y2, x2; + y1 = boxes.at(0 + i * 4) * (image_height - 1.); + x1 = boxes.at(1 + i * 4) * (image_width - 1.); + y2 = boxes.at(2 + i * 4) * (image_height - 1.); + x2 = boxes.at(3 + i * 4) * (image_width - 1.); + + int crop_height = abs(y2 - y1); + int crop_width = abs(x2 - x1); + + // account for flip crops when y1>y2 or x1>x2 with negative striding + int stride_height = 1, stride_width = 1; + if (y1 > y2) { + y1 = y1 - image_height; + y2 = y2 - image_height - 2; + stride_height = -1; + } + if (x1 > x2) { + x1 = x1 - image_height; + x2 = x2 - image_height - 2; + stride_width = -1; + } + + auto begin = make_shared(element::i64, + Shape{4}, + vector({static_cast(box_ind[i]), y1, x1, 0})); + auto end = make_shared( + element::i64, + Shape{4}, + vector( + {static_cast(box_ind[i]) + 1, y2 + 1, x2 + 1, static_cast(image_depth + 1)})); + auto strides = + make_shared(element::i64, Shape{4}, vector({1, stride_height, stride_width, 1})); + + // crop + auto ng_crop_node = + make_shared(ng_input, begin, end, strides, vector{}, vector{}); + auto ng_crop = ng_crop_node->output(0); + + Interpolate::InterpolateAttrs interpolate_attrs; + // always corner aligned + interpolate_attrs.coordinate_transformation_mode = Interpolate::CoordinateTransformMode::ALIGN_CORNERS; + + // TODO: handle the case when extrapolation value is greatger than 1.0 + // arguments for resizing + auto ng_spatial_shape = + make_shared(element::i32, Shape{2}, vector{crop_height, crop_width}); + auto ng_input_shape = make_shared(ng_spatial_shape, element::f32); + auto ng_crop_size = make_shared(ng_size, element::f32); + auto ng_scales = make_shared(ng_crop_size, ng_input_shape); + auto ng_axes = make_shared(element::i32, Shape{2}, vector({2, 3})); + + if (resize_method == "bilinear") { + interpolate_attrs.mode = Interpolate::InterpolateMode::LINEAR; + } else { // nearest + interpolate_attrs.mode = Interpolate::InterpolateMode::NEAREST; + } + + Transpose<0, 3, 1, 2>(ng_crop); + auto ng_output = + make_shared(ng_crop, ng_size, ng_scales, ng_axes, interpolate_attrs)->output(0); + Transpose<0, 2, 3, 1>(ng_output); + ng_crop_outputs.at(i) = ng_output; + } + + auto res = make_shared(ng_crop_outputs, 0); + set_node_name(node.get_name(), res); + return res->outputs(); + } +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/cumsum.cpp b/ngraph/frontend/tensorflow/src/op/cumsum.cpp index fef02fcbd09570..92738c0ef24039 100644 --- a/ngraph/frontend/tensorflow/src/op/cumsum.cpp +++ b/ngraph/frontend/tensorflow/src/op/cumsum.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,13 +13,17 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateCumsumOp(const NodeContext& node) { - auto ng_x = node.get_ng_input(0), ng_axis = node.get_ng_input(1); - auto exclusive = node.get_attribute("exclusive"), reverse = node.get_attribute("reverse"); +OutputVector translate_cumsum_op(const NodeContext& node) { + auto ng_x = node.get_input(0); + auto ng_axis = node.get_input(1); + auto exclusive = node.get_attribute("exclusive"); + auto reverse = node.get_attribute("reverse"); - return {ConstructNgNode(node.get_name(), ng_x, ng_axis, exclusive, reverse)}; + auto res = make_shared(ng_x, ng_axis, exclusive, reverse); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/depth_to_space.cpp b/ngraph/frontend/tensorflow/src/op/depth_to_space.cpp index f9703ca31af23e..5a5757ea0c7bb2 100644 --- a/ngraph/frontend/tensorflow/src/op/depth_to_space.cpp +++ b/ngraph/frontend/tensorflow/src/op/depth_to_space.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -14,26 +14,27 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateDepthToSpaceOp(const NodeContext& node) { - Output ng_input = node.get_ng_input(0); +OutputVector translate_depth_to_space_op(const NodeContext& node) { + Output ng_input = node.get_input(0); // Get the attributes auto block_size = node.get_attribute("block_size"); std::string tf_data_format = node.get_attribute("data_format"); - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("DepthToSpace data format is neither NHWC nor NCHW"); - } + TF_OP_VALIDATION_CHECK(node, + tf_data_format == "NHWC" || tf_data_format == "NCHW", + "DepthToSpace data format is neither NHWC nor NCHW"); bool is_nhwc = (tf_data_format == "NHWC"); - NHWCtoNCHW(node.get_name(), is_nhwc, ng_input); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, ng_input); auto ng_mode = DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST; - Output depth_to_space = ConstructNgNode(node.get_name(), ng_input, ng_mode, block_size); - NCHWtoNHWC(node.get_name(), is_nhwc, depth_to_space); - return {depth_to_space}; + Output res = make_shared(ng_input, ng_mode, block_size)->output(0); + convert_nchw_to_nhwc(node.get_name(), is_nhwc, res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/depthwise_conv_2d.cpp b/ngraph/frontend/tensorflow/src/op/depthwise_conv_2d.cpp index 4e1561c82429a8..6506b3c5ff8740 100644 --- a/ngraph/frontend/tensorflow/src/op/depthwise_conv_2d.cpp +++ b/ngraph/frontend/tensorflow/src/op/depthwise_conv_2d.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,17 +13,18 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateDepthwiseConv2dNativeOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0), ng_filter = node.get_ng_input(1); +OutputVector translate_depthwise_conv_2d_native_op(const NodeContext& node) { + auto ng_input = node.get_input(0); + auto ng_filter = node.get_input(1); auto tf_strides = node.get_attribute>("strides"); auto tf_dilations = node.get_attribute>("dilations"); auto tf_padding_type = node.get_attribute("padding"); auto tf_data_format = node.get_attribute("data_format"); - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("DepthwiseConv2D data format is neither NHWC nor NCHW"); - } + TF_OP_VALIDATION_CHECK(node, + tf_data_format == "NHWC" || tf_data_format == "NCHW", + "DepthwiseConv2D data format is neither NHWC nor NCHW"); bool is_nhwc = (tf_data_format == "NHWC"); @@ -32,10 +33,10 @@ OutputVector TranslateDepthwiseConv2dNativeOp(const NodeContext& node) { Shape ng_image_shape(2); Shape ng_kernel_shape(2); - NHWCtoHW(is_nhwc, ng_input.get_shape(), ng_image_shape); - NHWCtoHW(is_nhwc, tf_strides, ng_strides); - NHWCtoHW(is_nhwc, tf_dilations, ng_dilations); - NHWCtoNCHW(node.get_name(), is_nhwc, ng_input); + convert_nhwc_to_hw(is_nhwc, ng_input.get_shape(), ng_image_shape); + convert_nhwc_to_hw(is_nhwc, tf_strides, ng_strides); + convert_nhwc_to_hw(is_nhwc, tf_dilations, ng_dilations); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, ng_input); auto& ng_filter_shape = ng_filter.get_shape(); ng_kernel_shape[0] = ng_filter_shape[0]; @@ -43,38 +44,38 @@ OutputVector TranslateDepthwiseConv2dNativeOp(const NodeContext& node) { CoordinateDiff ng_padding_below; CoordinateDiff ng_padding_above; - MakePadding(tf_padding_type, - ng_image_shape, - ng_kernel_shape, - ng_strides, - ng_dilations, - ng_padding_below, - ng_padding_above); + make_padding(tf_padding_type, + ng_image_shape, + ng_kernel_shape, + ng_strides, + ng_dilations, + ng_padding_below, + ng_padding_above); // H W I M -> H W I 1 M - auto filter_shape = ConstructNgNode( - node.get_name(), + auto filter_shape = make_shared( element::u64, Shape{5}, ov::Shape{ng_filter_shape[0], ng_filter_shape[1], ng_filter_shape[2], 1, ng_filter_shape[3]}); - auto reshaped_filter = ConstructNgNode(node.get_name(), ng_filter, filter_shape, false); + auto reshaped_filter = make_shared(ng_filter, filter_shape, false); // H W I 1 M -> I M 1 H W - auto order = ConstructNgNode(node.get_name(), element::i64, Shape{5}, vector{2, 4, 3, 0, 1}); - auto transposed_filter = ConstructNgNode(node.get_name(), reshaped_filter, order); + auto order = make_shared(element::i64, Shape{5}, vector{2, 4, 3, 0, 1}); + auto transposed_filter = make_shared(reshaped_filter, order); - auto ng_conv = ConstructNgNode(node.get_name(), - ng_input, - transposed_filter, - ng_strides, - ng_padding_below, - ng_padding_above, - ng_dilations); + auto ng_conv_node = make_shared(ng_input, + transposed_filter, + ng_strides, + ng_padding_below, + ng_padding_above, + ng_dilations); + auto ng_conv = ng_conv_node->output(0); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_conv); + convert_nchw_to_nhwc(node.get_name(), is_nhwc, ng_conv); + set_node_name(node.get_name(), ng_conv.get_node_shared_ptr()); return {ng_conv}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/elu.cpp b/ngraph/frontend/tensorflow/src/op/elu.cpp index 237768ba1300c3..7241c1549f165c 100644 --- a/ngraph/frontend/tensorflow/src/op/elu.cpp +++ b/ngraph/frontend/tensorflow/src/op/elu.cpp @@ -2,10 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include - #include "node_context.hpp" +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov; @@ -16,10 +15,12 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateEluOp(const NodeContext& node) { - auto input = node.get_ng_input(0); - auto alpha = 1.0; // node.get_attribute("alpha"); - return {ConstructNgNode(node.get_name(), input, alpha)}; +OutputVector translate_elu_op(const NodeContext& node) { + auto input = node.get_input(0); + auto alpha = node.get_attribute("alpha", 1.0); + auto res = make_shared(input, alpha); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/expand_dims.cpp b/ngraph/frontend/tensorflow/src/op/expand_dims.cpp index 600ab95c613060..11d1a0efd1a64a 100644 --- a/ngraph/frontend/tensorflow/src/op/expand_dims.cpp +++ b/ngraph/frontend/tensorflow/src/op/expand_dims.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,14 +13,14 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateExpandDimsOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0); - std::vector dims; - GetStaticInputVector(node, 1, &dims); - auto ng_dims = ConstructNgNode(node.get_name(), element::i64, ov::Shape{dims.size()}, dims); - return {ConstructNgNode(node.get_name(), ng_input, ng_dims)}; +OutputVector translate_expand_dims_op(const NodeContext& node) { + auto input = node.get_input(0); + auto dims = node.get_input(1); + auto res = make_shared(input, dims); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/fake_quant_min_max_vars.cpp b/ngraph/frontend/tensorflow/src/op/fake_quant_min_max_vars.cpp new file mode 100644 index 00000000000000..bdb2595225f952 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/fake_quant_min_max_vars.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_fake_quant_op(const NodeContext& node) { + auto ng_input = node.get_input(0); + auto ng_min = node.get_input(1); + auto ng_max = node.get_input(2); + + auto narrow_range = node.get_attribute("narrow_range"); + auto num_bits = node.get_attribute("num_bits"); + + auto levels = std::pow(2, num_bits) - int(narrow_range); + auto min_less_max = make_shared(ng_min, ng_max); + auto minimum = make_shared(min_less_max, ng_max, ng_min); + + auto zero = make_shared(ng_min.get_element_type(), Shape{}, std::vector({0})); + + auto min_greater_zero = make_shared(minimum, zero); + auto max_minus_min = make_shared(maximum, minimum); + minimum = make_shared(min_greater_zero, max_minus_min, maximum); + + auto max_less_zero = make_shared(maximum, zero); + auto min_minus_max = make_shared(minimum, maximum); + minimum = make_shared(max_less_zero, zero, maximum); + + auto float_range = make_shared(maximum, minimum); + auto quant_min_value = int(narrow_range); + auto quant_max_value = std::pow(2, num_bits) - 1; + auto value = static_cast(quant_max_value - quant_min_value); + auto int_range = make_shared(element::f32, Shape{}, std::vector({value})); + auto scale = make_shared(float_range, int_range); + auto descaled_min = make_shared(minimum, scale); + auto rounded_descaled_min = make_shared(descaled_min, Round::RoundMode::HALF_TO_EVEN); + auto min_adj = make_shared(scale, rounded_descaled_min); + auto adjustment = make_shared(min_adj, minimum); + auto max_adj = make_shared(maximum, adjustment); + + auto ng_input_shape = ng_input.get_shape(); + if (ng_input_shape.size() == 4) + Transpose<0, 3, 1, 2>(ng_input); + auto res = make_shared(ng_input, min_adj, max_adj, min_adj, max_adj, levels)->output(0); + if (ng_input_shape.size() == 4) + Transpose<0, 2, 3, 1>(res); + + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/fill.cpp b/ngraph/frontend/tensorflow/src/op/fill.cpp index 24c4e54ce46281..28e9ed65cf3c55 100644 --- a/ngraph/frontend/tensorflow/src/op/fill.cpp +++ b/ngraph/frontend/tensorflow/src/op/fill.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,9 +13,12 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateFillOp(const NodeContext& node) { - auto ng_dims = node.get_ng_input(0), ng_value = node.get_ng_input(1); - return {ConstructNgNode(node.get_name(), ng_value, ng_dims)}; +OutputVector translate_fill_op(const NodeContext& node) { + auto ng_dims = node.get_input(0); + auto ng_value = node.get_input(1); + auto res = make_shared(ng_value, ng_dims); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/fused_batch_norm.cpp b/ngraph/frontend/tensorflow/src/op/fused_batch_norm.cpp index 92a58c429c2526..93542365b16341 100644 --- a/ngraph/frontend/tensorflow/src/op/fused_batch_norm.cpp +++ b/ngraph/frontend/tensorflow/src/op/fused_batch_norm.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,35 +13,32 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateFusedBatchNormOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0), ng_scale = node.get_ng_input(1), ng_offset = node.get_ng_input(2), - ng_mean = node.get_ng_input(3), ng_variance = node.get_ng_input(4); - bool is_v3 = node.get_op_type() == "FusedBatchNormV3"; +OutputVector translate_fused_batch_norm_op(const NodeContext& node) { + auto ng_input = node.get_input(0); + auto ng_scale = node.get_input(1); + auto ng_offset = node.get_input(2); + auto ng_mean = node.get_input(3); + auto ng_variance = node.get_input(4); - auto tf_data_format = node.get_attribute("data_format"); + bool is_v3 = node.get_op_type() == "FusedBatchNormV3"; - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("Conv2D data format is neither NHWC nor NCHW"); - } + auto data_format = node.get_attribute("data_format"); + TF_OP_VALIDATION_CHECK(node, data_format == "NHWC" || data_format == "NCHW", "Unsupported data format"); - bool is_nhwc = (tf_data_format == "NHWC"); + bool is_nhwc = (data_format == "NHWC"); - NGRAPH_VLOG(3) << "data_format: " << tf_data_format; + NGRAPH_DEBUG << "data_format: " << data_format; - auto tf_epsilon = node.get_attribute("epsilon", 0.0001); // TODO: where does 0.0001 come from? + // TODO: where does 0.0001 come from? + auto tf_epsilon = node.get_attribute("epsilon", 0.0001); - NGRAPH_VLOG(3) << "epsilon: " << tf_epsilon; + NGRAPH_DEBUG << "epsilon: " << tf_epsilon; - NHWCtoNCHW(node.get_name(), is_nhwc, ng_input); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, ng_input); - auto ng_batch_norm = ConstructNgNode(node.get_name(), - ng_input, - ng_scale, - ng_offset, - ng_mean, - ng_variance, - tf_epsilon); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_batch_norm); + auto ng_batch_norm = + make_shared(ng_input, ng_scale, ng_offset, ng_mean, ng_variance, tf_epsilon)->output(0); + convert_nchw_to_nhwc(node.get_name(), is_nhwc, ng_batch_norm); // TODO: Why are there so many? Is it correct? OutputVector result = {ng_batch_norm, ng_mean, ng_variance, ng_mean, ng_variance}; @@ -49,9 +46,10 @@ OutputVector TranslateFusedBatchNormOp(const NodeContext& node) { // FusedBatchNormV3 has 6 outputs result.push_back(ng_mean); // reserve_space_3 } + set_node_name(node.get_name(), ng_batch_norm.get_node_shared_ptr()); return result; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/fused_conv_2d.cpp b/ngraph/frontend/tensorflow/src/op/fused_conv_2d.cpp deleted file mode 100644 index 3b8ba2d31abb64..00000000000000 --- a/ngraph/frontend/tensorflow/src/op/fused_conv_2d.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -using namespace std; -using namespace ov::opset8; - -namespace ov { -namespace frontend { -namespace tf { -namespace op { - -OutputVector TranslateFusedConv2DOp(const NodeContext& node) { - auto num_args = node.get_attribute("num_args"); - auto fused_ops = node.get_attribute>("fused_ops"); - - auto tf_data_format = node.get_attribute("data_format"); - bool is_nhwc = (tf_data_format == "NHWC"); - - auto CreateNgConv = [&](Output& ng_input, Output& ng_filter) { - auto tf_strides = node.get_attribute>("strides"); - auto tf_dilations = node.get_attribute>("dilations"); - auto tf_padding_type = node.get_attribute("padding"); - - if (tf_data_format != "NHWC" && tf_data_format != "NCHW") { - throw errors::InvalidArgument("Conv2D data format is neither NHWC nor NCHW"); - } - - // TF Kernel Test Checks - // Strides in the batch and depth dimension is not supported - if (tf_strides[0] != 1 || tf_strides[is_nhwc ? 3 : 1] != 1) { - throw errors::InvalidArgument("Strides in batch and depth dimensions is not supported: " + - node.get_op_type()); - } - - Strides ng_strides(2); - Strides ng_dilations(2); - Shape ng_image_shape(2); - Shape ng_kernel_shape(2); - - NHWCtoHW(is_nhwc, tf_strides, ng_strides); - NHWCtoHW(is_nhwc, ng_input.get_shape(), ng_image_shape); - NHWCtoHW(is_nhwc, tf_dilations, ng_dilations); - NHWCtoNCHW(node.get_name(), is_nhwc, ng_input); - - auto& ng_filter_shape = ng_filter.get_shape(); - ng_kernel_shape[0] = ng_filter_shape[0]; - ng_kernel_shape[1] = ng_filter_shape[1]; - Transpose<3, 2, 0, 1>(ng_filter); - SetTracingInfo(node.get_name(), ng_filter); - - CoordinateDiff ng_padding_below; - CoordinateDiff ng_padding_above; - MakePadding(tf_padding_type, - ng_image_shape, - ng_kernel_shape, - ng_strides, - ng_dilations, - ng_padding_below, - ng_padding_above); - - return ConstructNgNode(node.get_name() + "_FusedConv2D_Conv", - ng_input, - ng_filter, - ng_strides, - ng_padding_below, - ng_padding_above, - ng_dilations); - }; - - if (VecStrCmp(fused_ops, {"BiasAdd"}) || VecStrCmp(fused_ops, {"BiasAdd", "Relu"}) || - VecStrCmp(fused_ops, {"BiasAdd", "Relu6"})) { - if (num_args != 1) { - throw errors::InvalidArgument("FusedConv2DBiasAdd has incompatible num_args"); - } - - auto ng_input = node.get_ng_input(0), ng_filter = node.get_ng_input(1), ng_bias = node.get_ng_input(2), - ng_conv = CreateNgConv(ng_input, ng_filter); - - auto ng_conv_shape = ng_conv.get_shape(); - auto ng_bias_shape = ng_bias.get_shape(); - if (ng_bias_shape.size() != 1) { - throw errors::InvalidArgument("Bias argument to BiasAdd does not have one dimension"); - } - - std::vector reshape_pattern_values(ng_conv_shape.size(), 1U); - reshape_pattern_values[1] = ng_bias.get_shape().front(); - auto reshape_pattern = - make_shared(element::u64, Shape{reshape_pattern_values.size()}, reshape_pattern_values); - auto ng_bias_reshaped = ConstructNgNode(node.get_name(), ng_bias, reshape_pattern, false); - - auto ng_add = ConstructNgNode(node.get_name() + "_FusedConv2D_BiasAdd", ng_conv, ng_bias_reshaped); - - if (VecStrCmp(fused_ops, {"BiasAdd", "Relu"})) { - auto ng_relu = ConstructNgNode(node.get_name() + "_FusedConv2D_Relu", ng_add); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_relu); - return {ng_relu}; - } else if (VecStrCmp(fused_ops, {"BiasAdd", "Relu6"})) { - auto ng_relu6 = ConstructNgNode(node.get_name() + "_FusedConv2D_Relu6", ng_add, 0, 6); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_relu6); - return {ng_relu6}; - } else { - NCHWtoNHWC(node.get_name(), is_nhwc, ng_add); - return {ng_add}; - } - } else if (VecStrCmp(fused_ops, {"FusedBatchNorm"}) || VecStrCmp(fused_ops, {"FusedBatchNorm", "Relu"}) || - VecStrCmp(fused_ops, {"FusedBatchNorm", "Relu6"})) { - if (num_args != 4) { - throw errors::InvalidArgument("FusedConv2D with FusedBatchNorm has incompatible num_args"); - } - - auto ng_input = node.get_ng_input(0), ng_filter = node.get_ng_input(1), ng_scale = node.get_ng_input(2), - ng_offset = node.get_ng_input(3), ng_mean = node.get_ng_input(4), ng_variance = node.get_ng_input(5), - ng_conv = CreateNgConv(ng_input, ng_filter); - - auto tf_epsilon = node.get_attribute("epsilon"); - - auto ng_batch_norm = ConstructNgNode(node.get_name() + "_FusedConv2D_BatchNorm", - ng_conv, - ng_scale, - ng_offset, - ng_mean, - ng_variance, - tf_epsilon); - - if (VecStrCmp(fused_ops, {"FusedBatchNorm", "Relu"})) { - auto ng_relu = ConstructNgNode(node.get_name() + "_FusedConv2D_BatchNormRelu", ng_batch_norm); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_relu); - return {ng_relu}; - } else if (VecStrCmp(fused_ops, {"FusedBatchNorm", "Relu6"})) { - auto ng_relu6 = ConstructNgNode(node.get_name() + "_FusedConv2D_BatchNormRelu", ng_batch_norm, 0, 6); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_relu6); - return {ng_relu6}; - } else { - NCHWtoNHWC(node.get_name(), is_nhwc, ng_batch_norm); - return {ng_batch_norm}; - } - } else { - FRONT_END_THROW("Unsupported _FusedConv2D "); - } -} -} // namespace op -} // namespace tf -} // namespace frontend -} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/fused_mat_mul.cpp b/ngraph/frontend/tensorflow/src/op/fused_mat_mul.cpp deleted file mode 100644 index b7f9884c1b8c41..00000000000000 --- a/ngraph/frontend/tensorflow/src/op/fused_mat_mul.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -using namespace std; -using namespace ov::opset8; - -namespace ov { -namespace frontend { -namespace tf { -namespace op { - -OutputVector TranslateFusedMatMulOp(const NodeContext& node) { - // auto num_args = node.get_attribute("num_args"); // TODO: it is unused but why? - auto fused_ops = node.get_attribute>("fused_ops"); - - // Transpose arguments if requested. - auto transpose_a = node.get_attribute("transpose_a", false); - auto transpose_b = node.get_attribute("transpose_b", false); - - auto ng_lhs = node.get_ng_input(0), ng_rhs = node.get_ng_input(1), ng_bias = node.get_ng_input(2); - - Output ng_matmul = ConstructNgNode(node.get_name(), ng_lhs, ng_rhs, transpose_a, transpose_b); - - auto ng_matmul_shape = ng_matmul.get_shape(); - auto ng_bias_shape = ng_bias.get_shape(); - - if (ng_bias_shape.size() != 1) { - throw errors::InvalidArgument("Bias argument to BiasAdd does not have one dimension"); - } - - auto ng_add = ConstructNgNode(node.get_name(), ng_matmul, ng_bias); - if (fused_ops.size() == 1) { // Only fusing BiasAdd - return {ng_add}; - } else if (fused_ops.size() == 2) { // Also has activation - if (fused_ops[1] == "Relu") { - return {ConstructNgNode(node.get_name(), ng_add)}; - } else if (fused_ops[1] == "Relu6") { - return {ConstructNgNode(node.get_name(), ng_add, 0, 6)}; - } else { - throw errors::Internal("Expected activation to be Relu or Relu6 but got " + fused_ops[1]); - } - } else { - // Adding this here to catch future changes in _FusedMatMul - throw errors::Internal("Unsupported combination"); - } -} -} // namespace op -} // namespace tf -} // namespace frontend -} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/gather.cpp b/ngraph/frontend/tensorflow/src/op/gather.cpp index 64996d8028f637..c26cef15c08b26 100644 --- a/ngraph/frontend/tensorflow/src/op/gather.cpp +++ b/ngraph/frontend/tensorflow/src/op/gather.cpp @@ -2,65 +2,46 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; -// See .../tensorflow/include/tensorflow/cc/ops/array_ops.h -// and .../openvino/ngraph/core/include/ngraph/op/gather.hpp namespace ov { namespace frontend { namespace tf { namespace op { -OutputVector TranslateGatherOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0), ng_input_indices = node.get_ng_input(1); - - auto ng_axis = ConstructNgNode(node.get_name(), element::i64, Shape{}, 0); - - auto gather_op = ConstructNgNode(node.get_name(), ng_input, ng_input_indices, ng_axis); - - return {gather_op}; +OutputVector translate_gather_op(const NodeContext& node) { + auto ng_input = node.get_input(0); + auto ng_input_indices = node.get_input(1); + auto ng_axis = make_shared(element::i64, Shape{}, 0); + auto res = make_shared(ng_input, ng_input_indices, ng_axis); + set_node_name(node.get_name(), res); + return res->outputs(); } -OutputVector TranslateGatherV2Op(const NodeContext& node) { - auto ng_input = node.get_ng_input(0), ng_input_coords = node.get_ng_input(1); - - std::vector tf_axis; - GetStaticInputVector(node, 2, &tf_axis); - - if (tf_axis.size() > 1) { - std::ostringstream buf; - buf << "Found axis in GatherV2 op (" << node.get_name() << ") translation to be non scalar, of size " - << tf_axis.size(); - throw errors::Internal(buf.str()); - } - - // Negative axis is supported. Accounting for that - auto ng_input_shape = ng_input.get_shape(); - size_t ng_input_rank = ng_input_shape.size(); - int axis; - if (tf_axis[0] >= 0) { - axis = tf_axis[0]; - } else { - axis = tf_axis[0] + ng_input_rank; - } - if (axis < 0 || axis >= ng_input_rank) { - std: - ostringstream buf; - buf << "Expected axis in the range [-" << ng_input_rank << ", " << ng_input_rank << "), but got " << tf_axis[0]; - throw errors::InvalidArgument(buf.str()); - } - - auto ng_axis = ConstructNgNode(node.get_name(), element::i64, Shape{tf_axis.size()}, tf_axis); - - auto gather_op = ConstructNgNode(node.get_name(), ng_input, ng_input_coords, ng_axis); +OutputVector translate_gather_v2_op(const NodeContext& node) { + auto ng_input = node.get_input(0); + auto ng_input_coords = node.get_input(1); + auto ng_axis = node.get_input(2); + auto batch_dims = node.get_attribute("batch_dims", 0); + auto res = make_shared(ng_input, ng_input_coords, ng_axis, batch_dims); + set_node_name(node.get_name(), res); + return res->outputs(); +} - return {gather_op}; +OutputVector translate_gather_nd_op(const NodeContext& node) { + auto input = node.get_input(0); + auto input_indices = node.get_input(1); + auto batch_dims = node.get_attribute("batch_dims", 0); + auto res = make_shared(input, input_indices, batch_dims); + set_node_name(node.get_name(), res); + return res->outputs(); } + } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/identity.cpp b/ngraph/frontend/tensorflow/src/op/identity.cpp index 8509a4c658efb8..cc6bd45463bf16 100644 --- a/ngraph/frontend/tensorflow/src/op/identity.cpp +++ b/ngraph/frontend/tensorflow/src/op/identity.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,11 +13,14 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateIdentityOp(const NodeContext& node) { - return {node.get_ng_input(0)}; +OutputVector translate_identity_op(const NodeContext& node) { + auto input = node.get_input(0); + set_out_name(node.get_name(), input); + set_out_name(node.get_name() + ":" + "0", input); + return {input}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/interpolate.cpp b/ngraph/frontend/tensorflow/src/op/interpolate.cpp new file mode 100644 index 00000000000000..ed98d112ae7524 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/interpolate.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { +ov::OutputVector translate_interpolate_op(const NodeContext& node) { + auto input = node.get_input(0); + auto input_sizes = node.get_input(1); + + Interpolate::InterpolateAttrs interpolate_attrs; + interpolate_attrs.mode = Interpolate::InterpolateMode::LINEAR; + interpolate_attrs.shape_calculation_mode = Interpolate::ShapeCalcMode::SIZES; + if (node.get_attribute("align_corners", false)) + interpolate_attrs.coordinate_transformation_mode = Interpolate::CoordinateTransformMode::ALIGN_CORNERS; + + if (node.get_op_type() == "ResizeNearestNeighbor") { + interpolate_attrs.mode = Interpolate::InterpolateMode::NEAREST; + interpolate_attrs.nearest_mode = Interpolate::NearestMode::ROUND_PREFER_FLOOR; + } + + // TODO: do we need this .get_shape() actually? + auto input_shape = input.get_shape(); + std::vector spatial_shape = {static_cast(input_shape[1]), static_cast(input_shape[2])}; + auto ng_spatial_shape = make_shared(element::f32, Shape{2}, spatial_shape); + + auto ng_sizes = make_shared(input_sizes, element::f32); + auto ng_scales = make_shared(ng_sizes, ng_spatial_shape); + auto ng_axes = make_shared(element::i32, Shape{2}, std::vector({2, 3})); + + Transpose<0, 3, 1, 2>(input); + auto res = make_shared(input, input_sizes, ng_scales, ng_axes, interpolate_attrs)->output(0); + Transpose<0, 2, 3, 1>(res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/is_finite.cpp b/ngraph/frontend/tensorflow/src/op/is_finite.cpp new file mode 100644 index 00000000000000..626d3aec9bc24f --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/is_finite.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_is_finite_op(const NodeContext& node) { + // TODO: Refactor this code. Not sure about in == in. + // Implemented tf.is_finite by checking: + // (in != inf) && (in != -inf) && (in == in) + // ^^^^^^^^ checks for NaN's + + auto input = node.get_input(0); + auto el_type = input.get_element_type(); + + auto inf = make_shared(el_type, Shape{}, vector{numeric_limits::infinity()}); + auto neg_inf = make_shared(el_type, Shape{}, vector{-numeric_limits::infinity()}); + + auto neq_inf = make_shared(input, inf); + auto neq_neg_inf = make_shared(input, neg_inf); + auto eq_nan = make_shared(input, input); + + auto neq_inf_and_neq_neg_inf = make_shared(neq_inf, neq_neg_inf); + auto res = make_shared(neq_inf_and_neq_neg_inf, eq_nan); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/l2_loss.cpp b/ngraph/frontend/tensorflow/src/op/l2_loss.cpp new file mode 100644 index 00000000000000..8cad1e58958241 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/l2_loss.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_l2_loss_op(const NodeContext& node) { + auto input = node.get_input(0); + + vector val; + val.push_back(2.0); + auto const_2 = make_shared(input.get_element_type(), Shape{}, 2); + auto pow = make_shared(input, input); + auto p_shape = input.get_partial_shape(); + + Output reduction_axes; + if (p_shape.rank().is_static()) { + vector axes(p_shape.size()); + iota(axes.begin(), axes.end(), 0); + reduction_axes = make_shared(element::i64, Shape{axes.size()}, axes); + } else { + auto shape = make_shared(input); + auto rank = make_shared(shape); + auto start = make_shared(element::i64, Shape{1}, 0); + auto step = make_shared(element::i64, Shape{1}, 1); + reduction_axes = make_shared(start, rank, step, element::i64); + } + + auto sum = make_shared(pow, reduction_axes); + auto res = make_shared(sum, const_2); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/leaky_relu.cpp b/ngraph/frontend/tensorflow/src/op/leaky_relu.cpp new file mode 100644 index 00000000000000..ecba626e8550d9 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/leaky_relu.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { +ov::OutputVector translate_leaky_relu_op(const NodeContext& node) { + auto in = node.get_input(0); + auto alpha_attr = node.get_attribute("alpha", 0.f); + auto alpha_const = make_shared(element::f32, Shape{1}, alpha_attr); + + auto leaky_relu = make_shared(in, alpha_const); + return leaky_relu->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/log1p.cpp b/ngraph/frontend/tensorflow/src/op/log1p.cpp new file mode 100644 index 00000000000000..84d15a4d45ec58 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/log1p.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_log_1p_op(const NodeContext& node) { + auto n = node.get_input(0); + auto const_1 = make_shared(n.get_element_type(), Shape{}, 1); + auto add = make_shared(n, const_1); + auto res = make_shared(add); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/log_softmax.cpp b/ngraph/frontend/tensorflow/src/op/log_softmax.cpp index 2d725d09d1b544..eaf6ed06869129 100644 --- a/ngraph/frontend/tensorflow/src/op/log_softmax.cpp +++ b/ngraph/frontend/tensorflow/src/op/log_softmax.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,13 +13,11 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateLogSoftmaxOp(const NodeContext& node) { - auto ng_inp = node.get_ng_input(0); - auto inp_shape = ng_inp.get_shape(); - size_t rank = inp_shape.size(); - int64_t axes = rank - 1; - - return {ConstructNgNode(node.get_name(), ng_inp, axes)}; +OutputVector translate_log_softmax_op(const NodeContext& node) { + auto ng_inp = node.get_input(0); + auto res = make_shared(ng_inp, -1); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/lrn.cpp b/ngraph/frontend/tensorflow/src/op/lrn.cpp new file mode 100644 index 00000000000000..ea4005e761e5db --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/lrn.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_lrn_op(const NodeContext& node) { + auto input = node.get_input(0); + auto alpha = node.get_attribute("alpha"); + auto beta = node.get_attribute("beta"); + auto bias = node.get_attribute("bias"); + auto depth_radius = node.get_attribute("depth_radius"); + + // OV: Each input value is divided by (bias+(alpha/size)*sum(xi^2 for every xi + // in the local region))^beta + // TF: sqr_sum[a, b, c, d] = sum(input[a, b, c, d - depth_radius : d + + // depth_radius + 1] ** 2) + // output = input / (bias + alpha * sqr_sum) ** beta + int64_t size = depth_radius * 2 + 1; + alpha = alpha * size; + // todo: input is in NHWC, need to apply NHWC to NCHW? + auto res = make_shared(input, alpha, beta, bias, static_cast(size)); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/matmul.cpp b/ngraph/frontend/tensorflow/src/op/matmul.cpp new file mode 100644 index 00000000000000..f05c95d64b4c15 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/matmul.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_mat_mul_op(const NodeContext& node) { + auto a = node.get_input(0); + auto b = node.get_input(1); + auto transpose_a = node.get_attribute("transpose_a", false); + auto transpose_b = node.get_attribute("transpose_b", false); + + auto res = make_shared(a, b, transpose_a, transpose_b); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/max_pool.cpp b/ngraph/frontend/tensorflow/src/op/max_pool.cpp index 8ecb356767d4cc..82c72a5263c82d 100644 --- a/ngraph/frontend/tensorflow/src/op/max_pool.cpp +++ b/ngraph/frontend/tensorflow/src/op/max_pool.cpp @@ -2,9 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 // -#include #include +#include "op_table.hpp" + using namespace std; using namespace ov; using namespace ov::frontend::tf::detail; @@ -14,8 +15,8 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateMaxPoolOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0); +OutputVector translate_max_pool_op(const NodeContext& node) { + auto ng_input = node.get_input(0); auto tf_strides = node.get_attribute>("strides"); auto tf_ksize = node.get_attribute>("ksize"); @@ -33,39 +34,40 @@ OutputVector TranslateMaxPoolOp(const NodeContext& node) { Shape ng_kernel_shape(N); Shape ng_dilations(N, 1); - NHWCtoHW(is_nhwc, tf_strides, ng_strides); - NHWCtoHW(is_nhwc, ng_input.get_shape(), ng_image_shape); - NHWCtoHW(is_nhwc, tf_ksize, ng_kernel_shape); - NHWCtoNCHW(node.get_name(), is_nhwc, ng_input); + convert_nhwc_to_hw(is_nhwc, tf_strides, ng_strides); + convert_nhwc_to_hw(is_nhwc, ng_input.get_shape(), ng_image_shape); + convert_nhwc_to_hw(is_nhwc, tf_ksize, ng_kernel_shape); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, ng_input); CoordinateDiff padding_below; CoordinateDiff padding_above; - MakePadding(tf_padding_type, - ng_image_shape, - ng_kernel_shape, - ng_strides, - ng_dilations, - padding_below, - padding_above); + make_padding(tf_padding_type, + ng_image_shape, + ng_kernel_shape, + ng_strides, + ng_dilations, + padding_below, + padding_above); // TODO: remove this once nGraph supports negative padding // (CoordinateDiff) for MaxPool Shape ng_padding_below(padding_below.begin(), padding_below.end()); Shape ng_padding_above(padding_above.begin(), padding_above.end()); - auto ng_maxpool = ConstructNgNode(node.get_name(), - ng_input, - ng_strides, - ng_padding_below, - ng_padding_above, - ng_kernel_shape, - ov::op::RoundingType::FLOOR); + auto res_node = make_shared(ng_input, + ng_strides, + ng_padding_below, + ng_padding_above, + ng_kernel_shape, + ov::op::RoundingType::FLOOR); + auto res = res_node->output(0); - NCHWtoNHWC(node.get_name(), is_nhwc, ng_maxpool); - return {ng_maxpool}; + convert_nchw_to_nhwc(node.get_name(), is_nhwc, res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/no_op.cpp b/ngraph/frontend/tensorflow/src/op/no_op.cpp index 57f09a73410b5b..135b7c3a323ca8 100644 --- a/ngraph/frontend/tensorflow/src/op/no_op.cpp +++ b/ngraph/frontend/tensorflow/src/op/no_op.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,16 +13,21 @@ namespace frontend { namespace tf { namespace op { -OutputVector NoOp(const NodeContext& node) { - if (node.get_ng_input_size() == 0) { +OutputVector translate_no_op(const NodeContext& node) { + if (node.get_input_size() == 0) { return OutputVector{}; } - if (node.get_ng_input_size() != 1) { - throw errors::InvalidArgument("NoOp has " + to_string(node.get_ng_input_size()) + " inputs, should have 1"); - } - return OutputVector{node.get_ng_input(0)}; + + TF_OP_VALIDATION_CHECK(node, + node.get_input_size() == 1, + "NoOp has " + to_string(node.get_input_size()) + " inputs, should have 1"); + + auto input = node.get_input(0); + set_out_name(node.get_name(), input); + set_out_name(node.get_name() + ":" + "0", input); + return {input}; } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/non_max_suppression.cpp b/ngraph/frontend/tensorflow/src/op/non_max_suppression.cpp new file mode 100644 index 00000000000000..4f527cce2a958a --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/non_max_suppression.cpp @@ -0,0 +1,85 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_non_max_suppression_op(const NodeContext& node) { + auto boxes = node.get_input(0); + auto scores = node.get_input(1); + auto max_output_size = node.get_input(2); + auto iou_threshold = node.get_input(3); + + auto axis = make_shared(element::i64, Shape{1}, 0); + auto boxes_unsqueezed = make_shared(boxes, axis); + + auto axis_scores = make_shared(element::i64, Shape{2}, vector{0, 1}); + auto scores_unsqueezed = make_shared(scores, axis_scores); + + const auto& op_type = node.get_op_type(); + if (op_type == "NonMaxSuppressionV5") { + auto score_threshold = node.get_input(4); + auto soft_nms_sigma = node.get_input(5); + // todo: pad_to_max_output_size + auto res = make_shared(boxes_unsqueezed, + scores_unsqueezed, + max_output_size, + iou_threshold, + score_threshold, + soft_nms_sigma, + NonMaxSuppression::BoxEncodingType::CORNER, + false, + element::Type_t::i32); + set_node_name(node.get_name(), res); + return res->outputs(); + } else if (op_type == "NonMaxSuppressionV4") { + auto score_threshold = node.get_input(4); + // todo: pad_to_max_output_size + auto res = make_shared(boxes_unsqueezed, + scores_unsqueezed, + max_output_size, + iou_threshold, + score_threshold, + NonMaxSuppression::BoxEncodingType::CORNER, + false, + element::Type_t::i32); + set_node_name(node.get_name(), res); + return res->outputs(); + } else if (op_type == "NonMaxSuppressionV3") { + auto score_threshold = node.get_input(4); + auto res = make_shared(boxes_unsqueezed, + scores_unsqueezed, + max_output_size, + iou_threshold, + score_threshold, + NonMaxSuppression::BoxEncodingType::CORNER, + false, + element::Type_t::i32); + set_node_name(node.get_name(), res); + return {res->output(0)}; + } else if (op_type == "NonMaxSuppressionV2" || op_type == "NonMaxSuppression") { + auto res = make_shared(boxes_unsqueezed, + scores_unsqueezed, + max_output_size, + iou_threshold, + NonMaxSuppression::BoxEncodingType::CORNER, + false, + element::Type_t::i32); + set_node_name(node.get_name(), res); + return {res->output(0)}; + } + TF_OP_VALIDATION_CHECK(node, false, "No translator found."); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/one_hot.cpp b/ngraph/frontend/tensorflow/src/op/one_hot.cpp index f7c4a1520a21fc..79f4806941431d 100644 --- a/ngraph/frontend/tensorflow/src/op/one_hot.cpp +++ b/ngraph/frontend/tensorflow/src/op/one_hot.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,16 +13,16 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateOneHotOp(const NodeContext& node) { - auto ng_features = node.get_ng_input(0); - auto ng_depth = node.get_ng_input(1); - auto ng_on = node.get_ng_input(2); - auto ng_off = node.get_ng_input(3); +OutputVector translate_one_hot_op(const NodeContext& node) { + auto ng_features = node.get_input(0); + auto ng_depth = node.get_input(1); + auto ng_on = node.get_input(2); + auto ng_off = node.get_input(3); auto one_hot_axis = node.get_attribute("axis"); - auto ng_onehot = make_shared(ng_features, ng_depth, ng_on, ng_off, one_hot_axis); - ng_onehot->set_friendly_name(ng_onehot->get_friendly_name()); - return ng_onehot->outputs(); + auto res = make_shared(ng_features, ng_depth, ng_on, ng_off, one_hot_axis); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/pack.cpp b/ngraph/frontend/tensorflow/src/op/pack.cpp new file mode 100644 index 00000000000000..16624d8efeaf88 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/pack.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_pack_op(const NodeContext& node) { + auto axis = node.get_attribute("axis"); + auto axis_const = make_shared(element::i64, Shape{}, axis); + + OutputVector concat_inputs; + for (size_t i = 0; i < node.get_input_size(); ++i) { + auto in = node.get_input(i); + concat_inputs.push_back(make_shared(in, axis_const)); + } + + auto res = make_shared(concat_inputs, axis); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/pad.cpp b/ngraph/frontend/tensorflow/src/op/pad.cpp index dedbb3a03faeee..ef4e54b39b0b96 100644 --- a/ngraph/frontend/tensorflow/src/op/pad.cpp +++ b/ngraph/frontend/tensorflow/src/op/pad.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -17,19 +17,18 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslatePadOp(const NodeContext& node) { - auto ng_input = node.get_ng_input(0), ng_paddings_op = node.get_ng_input(1); +OutputVector translate_pad_op(const NodeContext& node) { + auto ng_input = node.get_input(0), ng_paddings_op = node.get_input(1); Output pad_val_op; // Set inputs and pad_val_op auto op_type = node.get_op_type(); if (op_type == "Pad" || op_type == "MirrorPad") { - pad_val_op = - ConstructNgNode(node.get_name(), ng_input.get_element_type(), Shape(), std::vector({0})); + pad_val_op = make_shared(ng_input.get_element_type(), Shape(), std::vector({0})); } else if (op_type == "PadV2") { - pad_val_op = node.get_ng_input(2); + pad_val_op = node.get_input(2); } else { - throw errors::InvalidArgument("Incorrect TF Pad OpType: " + node.get_op_type()); + TF_OP_VALIDATION_CHECK(node, false, "Incorrect TF Pad OpType: " + node.get_op_type()); } // Set pad_mode @@ -41,16 +40,18 @@ OutputVector TranslatePadOp(const NodeContext& node) { } else if (pad_mode_str == "SYMMETRIC") { pad_mode = ov::op::PadMode::SYMMETRIC; } else { - throw errors::InvalidArgument(pad_mode_str + " is not an allowed padding mode."); + TF_OP_VALIDATION_CHECK(node, false, pad_mode_str + " is not an allowed padding mode."); } } // Set pads_begin & pads_end (from the pad_val_op) std::vector paddings; - GetStaticInputVector(node, 1, &paddings); + get_static_input_vec(node, 1, &paddings); if (paddings.size() % 2 != 0) { - throw errors::InvalidArgument("Constant node for paddings does not have an even number of " - "elements"); + TF_OP_VALIDATION_CHECK(node, + false, + "Constant node for paddings does not have an even number of " + "elements"); } std::vector pad_begin(paddings.size() / 2); std::vector pad_end(paddings.size() / 2); @@ -58,16 +59,15 @@ OutputVector TranslatePadOp(const NodeContext& node) { pad_begin[i] = paddings[2 * i]; pad_end[i] = paddings[2 * i + 1]; } - auto pads_begin_node = ConstructNgNode(node.get_name(), element::i64, Shape{pad_begin.size()}, pad_begin); - auto pads_end_node = ConstructNgNode(node.get_name(), element::i64, Shape{pad_end.size()}, pad_end); + auto pads_begin_node = make_shared(element::i64, Shape{pad_begin.size()}, pad_begin); + auto pads_end_node = make_shared(element::i64, Shape{pad_end.size()}, pad_end); // Create final Op - auto result_pad_op = - ConstructNgNode(node.get_name(), ng_input, pads_begin_node, pads_end_node, pad_val_op, pad_mode); - - return {result_pad_op}; + auto res = make_shared(ng_input, pads_begin_node, pads_end_node, pad_val_op, pad_mode); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/placeholder.cpp b/ngraph/frontend/tensorflow/src/op/placeholder.cpp index c8b2f7f8712c3f..0277d5e7e3a14b 100644 --- a/ngraph/frontend/tensorflow/src/op/placeholder.cpp +++ b/ngraph/frontend/tensorflow/src/op/placeholder.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,12 +13,15 @@ namespace frontend { namespace tf { namespace op { -OutputVector PlaceholderOp(const NodeContext& node) { +OutputVector translate_placeholder_op(const NodeContext& node) { auto ng_et = node.get_attribute("dtype"); auto ng_shape = node.get_attribute("shape", ov::PartialShape()); - return {ConstructNgNode(node.get_name(), ng_et, ng_shape)}; + + auto res = std::make_shared(ng_et, ng_shape); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/random_uniform.cpp b/ngraph/frontend/tensorflow/src/op/random_uniform.cpp index 2087575e8325bb..9c1a050a411fed 100644 --- a/ngraph/frontend/tensorflow/src/op/random_uniform.cpp +++ b/ngraph/frontend/tensorflow/src/op/random_uniform.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -12,16 +12,28 @@ namespace ov { namespace frontend { namespace tf { namespace op { -ov::OutputVector TranslateRandomUniformOp(const NodeContext& node) { - auto data = node.get_ng_input(0); - auto seed = node.get_attribute("seed"); - auto seed2 = node.get_attribute("seed2"); +ov::OutputVector translate_random_uniform_op(const NodeContext& node) { + auto shape = node.get_input(0); + auto seed = node.get_attribute("seed", 0); + auto seed2 = node.get_attribute("seed2", 0); auto minval_const = make_shared(element::f32, Shape{}, 0); auto maxval_const = make_shared(element::f32, Shape{}, 1); auto ng_et = node.get_attribute("dtype"); - auto random_uniform = std::make_shared(data, minval_const, maxval_const, ng_et, seed, seed2); - random_uniform->set_friendly_name(node.get_name()); - return random_uniform->outputs(); + auto res = std::make_shared(shape, minval_const, maxval_const, ng_et, seed, seed2); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +ov::OutputVector translate_random_uniform_int_op(const NodeContext& node) { + auto shape = node.get_input(0); + auto minval = node.get_input(1); + auto maxval = node.get_input(2); + auto seed = node.get_attribute("seed", 0); + auto seed2 = node.get_attribute("seed2", 0); + auto ng_et = minval.get_element_type(); + auto res = std::make_shared(shape, minval, maxval, ng_et, seed, seed2); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/range.cpp b/ngraph/frontend/tensorflow/src/op/range.cpp new file mode 100644 index 00000000000000..544af501e0dac0 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/range.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_range_op(const NodeContext& node) { + auto start = node.get_input(0); + auto stop = node.get_input(1); + auto step = node.get_input(2); + auto out_type = node.get_attribute("Tidx"); + + auto res = make_shared(start, stop, step, out_type); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/rank.cpp b/ngraph/frontend/tensorflow/src/op/rank.cpp new file mode 100644 index 00000000000000..e4fc655706cd89 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/rank.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +ov::OutputVector translate_rank_op(const NodeContext& node) { + auto data = node.get_input(0); + auto shape_of_1 = make_shared(data, ov::element::i64); + auto res = make_shared(shape_of_1, ov::element::i64); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/reciprocal.cpp b/ngraph/frontend/tensorflow/src/op/reciprocal.cpp new file mode 100644 index 00000000000000..017bbddbb4c68e --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/reciprocal.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_reciprocal_op(const NodeContext& node) { + auto x = node.get_input(0); + auto ng_exponent = make_shared(x.get_element_type(), Shape{}, -1); + auto res = make_shared(x, ng_exponent); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/reduce.cpp b/ngraph/frontend/tensorflow/src/op/reduce.cpp index 5397300557481f..11c9e7f6c1b20e 100644 --- a/ngraph/frontend/tensorflow/src/op/reduce.cpp +++ b/ngraph/frontend/tensorflow/src/op/reduce.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -15,53 +15,37 @@ namespace op { OutputVector TranslateReduceOp(const NodeContext& node, std::function(Output, Output, const bool)> create_ng_node) { - Output ng_input = node.get_ng_input(0); + auto input = node.get_input(0); + auto reduction_axes = node.get_input(1); auto tf_keep_dims = node.get_attribute("keep_dims", false); - - std::vector axes; - GetStaticInputVector(node, 1, &axes); - - Shape input_shape = ng_input.get_shape(); - size_t input_rank = input_shape.size(); - - TF_RETURN_IF_ERROR(CheckAxisDimInRange(axes, input_rank)); - - std::vector ng_reduction_axes_vect(axes.size()); - std::transform(axes.begin(), axes.end(), ng_reduction_axes_vect.begin(), [input_rank](int idx) { - return idx + (idx < 0 ? (int)input_rank : 0); - }); - auto ng_reduction_axes = ConstructNgNode(node.get_name(), - element::i64, - Shape{ng_reduction_axes_vect.size()}, - ng_reduction_axes_vect); - - Output ng_node = create_ng_node(ng_input, ng_reduction_axes, tf_keep_dims); - - return {ng_node}; + auto res = create_ng_node(input, reduction_axes, tf_keep_dims); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; } template -OutputVector TranslateDirectReduceOp(const NodeContext& node) { +OutputVector translate_direct_reduce_op(const NodeContext& node) { // ensure its either an arithmetic or a logical reduction if (!(std::is_base_of::value || std::is_base_of::value)) { - throw errors::InvalidArgument("Expected node to be either a valid logical or arithmetic reduction " - "type"); + TF_OP_VALIDATION_CHECK(node, + false, + "Expected node to be either a valid logical or arithmetic reduction " + "type"); } - return TranslateReduceOp(node, - [&node](Output ng_input, Output ng_reduction_axes, const bool keep_dims) { - return ConstructNgNode(node.get_name(), ng_input, ng_reduction_axes, keep_dims); - }); + return TranslateReduceOp(node, [](Output ng_input, Output ng_reduction_axes, const bool keep_dims) { + return make_shared(ng_input, ng_reduction_axes, keep_dims); + }); } -template OutputVector TranslateDirectReduceOp(const NodeContext& node); -template OutputVector TranslateDirectReduceOp(const NodeContext& node); -template OutputVector TranslateDirectReduceOp(const NodeContext& node); -template OutputVector TranslateDirectReduceOp(const NodeContext& node); -template OutputVector TranslateDirectReduceOp(const NodeContext& node); -template OutputVector TranslateDirectReduceOp(const NodeContext& node); -template OutputVector TranslateDirectReduceOp(const NodeContext& node); +template OutputVector translate_direct_reduce_op(const NodeContext& node); +template OutputVector translate_direct_reduce_op(const NodeContext& node); +template OutputVector translate_direct_reduce_op(const NodeContext& node); +template OutputVector translate_direct_reduce_op(const NodeContext& node); +template OutputVector translate_direct_reduce_op(const NodeContext& node); +template OutputVector translate_direct_reduce_op(const NodeContext& node); +template OutputVector translate_direct_reduce_op(const NodeContext& node); } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/relu_6.cpp b/ngraph/frontend/tensorflow/src/op/relu_6.cpp index 4f9a1627213312..83692a56312b58 100644 --- a/ngraph/frontend/tensorflow/src/op/relu_6.cpp +++ b/ngraph/frontend/tensorflow/src/op/relu_6.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -12,11 +12,11 @@ namespace ov { namespace frontend { namespace tf { namespace op { -ov::OutputVector TranslateRelu6Op(const NodeContext& node) { - auto data = node.get_ng_input(0); - auto clamp = std::make_shared(data, 0.0, 6.0f); - clamp->set_friendly_name(node.get_name()); - return clamp->outputs(); +ov::OutputVector translate_relu_6_op(const NodeContext& node) { + auto data = node.get_input(0); + auto res = std::make_shared(data, 0.0, 6.0f); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/reshape.cpp b/ngraph/frontend/tensorflow/src/op/reshape.cpp new file mode 100644 index 00000000000000..b14c02b6879a5d --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/reshape.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_reshape_op(const NodeContext& node) { + auto data = node.get_input(0); + auto shape = node.get_input(1); + auto res = make_shared(data, shape, false); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/retval.cpp b/ngraph/frontend/tensorflow/src/op/retval.cpp deleted file mode 100644 index 5adca5a0ea7920..00000000000000 --- a/ngraph/frontend/tensorflow/src/op/retval.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2018-2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include -#include - -using namespace std; -using namespace ov::opset8; - -namespace ov { -namespace frontend { -namespace tf { -namespace op { - -OutputVector RetvalOp(const NodeContext& node) { - // Make sure that this _Retval only has one input node. - if (node.get_ng_input_size() != 1) { - throw errors::InvalidArgument("_Retval has " + to_string(node.get_ng_input_size()) + " inputs, should have 1"); - } - - // auto ret_val_index = node.get_attribute("index"); - // TODO: Put ret_val_index to RT info that should be later utilized to order outpus by indices - - return {ConstructNgNode(node.get_name(), node.get_ng_input(0))}; -} -} // namespace op -} // namespace tf -} // namespace frontend -} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/reverse.cpp b/ngraph/frontend/tensorflow/src/op/reverse.cpp new file mode 100644 index 00000000000000..768e1ad8f27546 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/reverse.cpp @@ -0,0 +1,51 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_reverse_op(const NodeContext& node) { + auto input = node.get_input(0); + auto axes = node.get_input(1); + + auto axes_const = dynamic_pointer_cast(axes.get_node_shared_ptr()); + TF_OP_VALIDATION_CHECK(node, axes_const != nullptr, "Axes input must be constant."); + TF_OP_VALIDATION_CHECK(node, axes_const->get_shape().size() == 1, "Axes input must be 1D."); + TF_OP_VALIDATION_CHECK(node, axes_const->get_shape()[0] == 1, "Axes input must have only one value."); + auto seq_axis = axes_const->cast_vector().at(0); + int64_t batch_axis = !seq_axis; + + Output seq_lengths; + if (input.get_partial_shape().is_static()) { + auto in_shape = input.get_shape(); + seq_lengths = make_shared(element::i64, Shape{in_shape[batch_axis]}, in_shape[seq_axis]); + } else { + auto shape = make_shared(input); + auto one = make_shared(element::i64, Shape{1}, 1); + auto gather_batch = make_shared(shape, + make_shared(element::i64, Shape{1}, batch_axis), + make_shared(element::i64, Shape{1}, 0)); + auto gather_seq = make_shared(shape, + make_shared(element::i64, Shape{1}, seq_axis), + make_shared(element::i64, Shape{1}, 0)); + auto broadcast = make_shared(one, gather_batch); + seq_lengths = make_shared(broadcast, gather_seq); + } + + auto res = make_shared(input, seq_lengths, batch_axis, seq_axis); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/roll.cpp b/ngraph/frontend/tensorflow/src/op/roll.cpp index 0676b205f87ab2..a004436b9afbcf 100644 --- a/ngraph/frontend/tensorflow/src/op/roll.cpp +++ b/ngraph/frontend/tensorflow/src/op/roll.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov; @@ -14,13 +14,13 @@ namespace ov { namespace frontend { namespace tf { namespace op { -ov::OutputVector TranslateRollOp(const NodeContext& node) { - auto data = node.get_ng_input(0); - auto shift = node.get_ng_input(1); - auto axis = node.get_ng_input(2); - auto roll = std::make_shared(data, shift, axis); - roll->set_friendly_name(node.get_name()); - return roll->outputs(); +ov::OutputVector translate_roll_op(const NodeContext& node) { + auto data = node.get_input(0); + auto shift = node.get_input(1); + auto axis = node.get_input(2); + auto res = std::make_shared(data, shift, axis); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/round.cpp b/ngraph/frontend/tensorflow/src/op/round.cpp new file mode 100644 index 00000000000000..8c2d64bc951f7f --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/round.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_round_op(const NodeContext& node) { + auto input = node.get_input(0); + // using default round mode "half_to_even" in openvino, + // as TF has only that mode + auto round_mode = Round::RoundMode::HALF_TO_EVEN; + auto res = make_shared(input, round_mode); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/rsqrt.cpp b/ngraph/frontend/tensorflow/src/op/rsqrt.cpp index a9554d46231109..a67fa255767d31 100644 --- a/ngraph/frontend/tensorflow/src/op/rsqrt.cpp +++ b/ngraph/frontend/tensorflow/src/op/rsqrt.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,12 +13,12 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateRsqrtOp(const NodeContext& node) { - auto input = node.get_ng_input(0); - auto ng_exponent = ConstructNgNode(node.get_name(), input.get_element_type(), Shape{1}, -0.5f); - auto power = make_shared(input, ng_exponent); - power->set_friendly_name(node.get_name()); - return power->outputs(); +OutputVector translate_rsqrt_op(const NodeContext& node) { + auto input = node.get_input(0); + auto ng_exponent = make_shared(input.get_element_type(), Shape{1}, -0.5f); + auto res = make_shared(input, ng_exponent); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/select.cpp b/ngraph/frontend/tensorflow/src/op/select.cpp index 51fb1bd4435ab5..9f3d9771ff06cc 100644 --- a/ngraph/frontend/tensorflow/src/op/select.cpp +++ b/ngraph/frontend/tensorflow/src/op/select.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -12,11 +12,11 @@ namespace ov { namespace frontend { namespace tf { namespace op { -OutputVector TranslateSelectOp(const NodeContext& node) { - TF_OP_VALIDATION_CHECK(node, node.get_all_ng_inputs().size() == 3, "Select op cannot be converted"); - auto in_1 = node.get_ng_input(0); - auto in_2 = node.get_ng_input(1); - auto in_3 = node.get_ng_input(2); +OutputVector translate_select_op(const NodeContext& node) { + TF_OP_VALIDATION_CHECK(node, node.get_all_inputs().size() == 3, "Select op cannot be converted"); + auto in_1 = node.get_input(0); + auto in_2 = node.get_input(1); + auto in_3 = node.get_input(2); if (in_1.get_partial_shape().is_static() && in_2.get_partial_shape().is_static()) { // select broadcast if (in_1.get_shape().size() == 1 && in_2.get_shape().size() > 1) { @@ -24,14 +24,14 @@ OutputVector TranslateSelectOp(const NodeContext& node) { std::iota(axes.begin(), axes.end(), 1); auto unsqueeze_axes = make_shared(ov::element::i64, Shape{in_2.get_shape().size() - 1}, axes); auto unsqueeze = make_shared(in_1, unsqueeze_axes); - auto ng_select = make_shared(unsqueeze, in_2, in_3); + set_node_name(node.get_name(), res); + return res->outputs(); } } - auto ng_select = make_shared(in_1, in_2, in_3); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/shape.cpp b/ngraph/frontend/tensorflow/src/op/shape.cpp new file mode 100644 index 00000000000000..511bb65bbab3af --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/shape.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +ov::OutputVector translate_shape_op(const NodeContext& node) { + auto data = node.get_input(0); + auto out_type = node.get_attribute("out_type"); + auto res = make_shared(data, out_type); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/size.cpp b/ngraph/frontend/tensorflow/src/op/size.cpp new file mode 100644 index 00000000000000..79855e0991380e --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/size.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +ov::OutputVector translate_size_op(const NodeContext& node) { + auto data = node.get_input(0); + auto out_type = node.get_attribute("out_type"); + auto shape_of = make_shared(data, out_type); + auto axis = make_shared(ov::element::i64, Shape{}, 0); + auto res = make_shared(shape_of, axis); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/slice.cpp b/ngraph/frontend/tensorflow/src/op/slice.cpp new file mode 100644 index 00000000000000..89376e9955e3cb --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/slice.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_slice_op(const NodeContext& node) { + auto input = node.get_input(0); + auto start = node.get_input(1); + auto size = node.get_input(2); + + auto stop = make_shared(start, size); + + auto one = make_shared(element::i64, Shape{1}, 1); + auto shape = make_shared(start); + auto step = make_shared(one, shape); + + auto res = make_shared(input, start, stop, step); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/softmax.cpp b/ngraph/frontend/tensorflow/src/op/softmax.cpp index 31647e549afcf1..24fc5620858ab9 100644 --- a/ngraph/frontend/tensorflow/src/op/softmax.cpp +++ b/ngraph/frontend/tensorflow/src/op/softmax.cpp @@ -2,8 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include + +#include "op_table.hpp" using namespace std; using namespace ov::opset8; @@ -12,19 +13,17 @@ namespace ov { namespace frontend { namespace tf { namespace op { -OutputVector TranslateSoftmaxOp(const NodeContext& node) { - auto ng_inp = node.get_ng_input(0); - auto inp_shape = ng_inp.get_shape(); - size_t rank = inp_shape.size(); - int64_t axes = rank - 1; - if (rank < 1) { - throw errors::InvalidArgument("TF Softmax logits must be >=1 dimension"); - } - - return {ConstructNgNode(node.get_name(), ng_inp, axes)}; +OutputVector translate_softmax_op(const NodeContext& node) { + auto ng_inp = node.get_input(0); + // todo: switch to opset8::Softmax when is ready and delete Dynamic rank limitation + TF_OP_VALIDATION_CHECK(node, ng_inp.get_partial_shape().rank().is_static(), "Dynamic rank is not supported."); + size_t axis = ng_inp.get_partial_shape().rank().get_length() - 1; + auto res = make_shared(ng_inp, axis); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/space_to_batch_nd.cpp b/ngraph/frontend/tensorflow/src/op/space_to_batch_nd.cpp new file mode 100644 index 00000000000000..d1b2897cecab52 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/space_to_batch_nd.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { +OutputVector translate_batch_nd_and_space_nd_op(const NodeContext& node) { + auto input = node.get_input(0); + auto block_shape = node.get_input(1); + auto crops = node.get_input(2); + + // ng_crops should be of shape N=[ng_input.get_shape()).size()] + // But TF's ng_crops input is limited only to the spatial dimensions (neither + // batch nor innermost), + // which would mean ngraph inputs have missing ng_crops[0] and ng_crops[N]. + // Hence, pad ng_crops with zeros at both ends + + // return with input if rank < 2 as ngraph's impl doesn't support it + const auto& input_pshape = input.get_partial_shape(); + const auto& block_shape_pshape = block_shape.get_partial_shape(); + if (input_pshape.rank().is_static() && block_shape_pshape.rank().is_static()) { + auto N = input_pshape.rank().get_length(); + if (N < 2) + return {input}; + } else { + // TODO: support dynamic rank + TF_OP_VALIDATION_CHECK(node, false, "Dynamic rank is not supported."); + } + + auto N = input_pshape.rank().get_length(); + auto M = block_shape_pshape.rank().get_length(); + auto padded_crops = + make_shared(crops, + make_shared(crops.get_element_type(), Shape{2}, std::vector{1, 0}), + make_shared(crops.get_element_type(), Shape{2}, std::vector{N - M - 1, 0}), + ov::op::PadMode::CONSTANT); + + // Padding needs to be done for block_shape as done for crops above but with + // value=1 + auto padded_block_shape = make_shared( + block_shape, + make_shared(block_shape.get_element_type(), Shape{1}, std::vector{1}), + make_shared(block_shape.get_element_type(), Shape{1}, std::vector{N - M - 1}), + make_shared(block_shape.get_element_type(), Shape{}, 1), + ov::op::PadMode::CONSTANT); + + auto target_axis = make_shared(element::i64, Shape{}, 1); + // split into two 1-D vectors crops_begin and crops_end along axis 1 + auto crops_split = make_shared(padded_crops, target_axis, 2); + + // crops: [[0, 1], [1, 2], ...] + // crops_split: [[[0], [1]], [[1], [2]], ...] + // crops_begin: [0, 1, ...], crops_end: [1, 2, ...] + auto axes = make_shared(element::i32, Shape{}, -1); + auto crops_begin = make_shared(crops_split->outputs()[0], axes); + auto crops_end = make_shared(crops_split->outputs()[1], axes); + + if (node.get_op_type() == "BatchToSpaceND") { + auto res = make_shared(input, padded_block_shape, crops_begin, crops_end); + set_node_name(node.get_name(), res); + return res->outputs(); + } else if (node.get_op_type() == "SpaceToBatchND") { + auto res = make_shared(input, padded_block_shape, crops_begin, crops_end); + set_node_name(node.get_name(), res); + return res->outputs(); + } + TF_OP_VALIDATION_CHECK(node, false, "No translator found."); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/space_to_depth.cpp b/ngraph/frontend/tensorflow/src/op/space_to_depth.cpp new file mode 100644 index 00000000000000..ac173f6120c3e7 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/space_to_depth.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_space_to_depth_op(const NodeContext& node) { + auto input = node.get_input(0); + + auto block_size = node.get_attribute("block_size"); + auto data_format = node.get_attribute("data_format"); + + TF_OP_VALIDATION_CHECK(node, data_format == "NHWC" || data_format == "NCHW", "Unsupported data format."); + + bool is_nhwc = (data_format == "NHWC"); + convert_nhwc_to_nchw(node.get_name(), is_nhwc, input); + auto ng_mode = SpaceToDepth::SpaceToDepthMode::BLOCKS_FIRST; + auto res = make_shared(input, ng_mode, block_size)->output(0); + convert_nchw_to_nhwc(node.get_name(), is_nhwc, res); + set_node_name(node.get_name(), res.get_node_shared_ptr()); + return {res}; +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/split.cpp b/ngraph/frontend/tensorflow/src/op/split.cpp new file mode 100644 index 00000000000000..20ea1ad789ee8d --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/split.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_split_op(const NodeContext& node) { + auto axes = node.get_input(0); + auto input = node.get_input(1); + auto num_split = node.get_attribute("num_split"); + + auto res = make_shared(input, axes, num_split); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +OutputVector translate_split_v_op(const NodeContext& node) { + auto input = node.get_input(0); + auto split_lengths = node.get_input(1); + auto split_dims = node.get_input(2); + + // todo(itikhono): double check split_lengths and split_dims are in supported form here + auto res = make_shared(input, split_dims, split_lengths); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/sqrt.cpp b/ngraph/frontend/tensorflow/src/op/sqrt.cpp index ffa9dec52ad299..97490a4bc3c13b 100644 --- a/ngraph/frontend/tensorflow/src/op/sqrt.cpp +++ b/ngraph/frontend/tensorflow/src/op/sqrt.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,12 +13,12 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateSqrtOp(const NodeContext& node) { - auto input = node.get_ng_input(0); - auto ng_exponent = ConstructNgNode(node.get_name(), input.get_element_type(), Shape{1}, 0.5f); - auto power = make_shared(input, ng_exponent); - power->set_friendly_name(node.get_name()); - return power->outputs(); +OutputVector translate_sqrt_op(const NodeContext& node) { + auto input = node.get_input(0); + auto ng_exponent = make_shared(input.get_element_type(), Shape{1}, 0.5f); + auto res = make_shared(input, ng_exponent); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf diff --git a/ngraph/frontend/tensorflow/src/op/square.cpp b/ngraph/frontend/tensorflow/src/op/square.cpp new file mode 100644 index 00000000000000..9a74550f1f8e4d --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/square.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_square_op(const NodeContext& node) { + auto n = node.get_input(0); + auto res = make_shared(n, n); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/squeeze.cpp b/ngraph/frontend/tensorflow/src/op/squeeze.cpp index 70cc8201e033db..1af6b5272b6180 100644 --- a/ngraph/frontend/tensorflow/src/op/squeeze.cpp +++ b/ngraph/frontend/tensorflow/src/op/squeeze.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,23 +13,16 @@ namespace frontend { namespace tf { namespace op { -OutputVector TranslateSqueezeOp(const NodeContext& node) { - Output ng_input = node.get_ng_input(0); - size_t input_dims = ng_input.get_shape().size(); - - auto tf_axis = node.get_attribute>("squeeze_dims"); - - // If input dimension is negative, make it positive - for (size_t i = 0; i < tf_axis.size(); i++) { - tf_axis[i] = tf_axis[i] < 0 ? (int32_t)(input_dims) + tf_axis[i] : tf_axis[i]; - } - - auto ng_const = ConstructNgNode(node.get_name(), element::i32, Shape{tf_axis.size()}, tf_axis); - - return {ConstructNgNode(node.get_name(), ng_input, ng_const)}; +OutputVector translate_squeeze_op(const NodeContext& node) { + auto input = node.get_input(0); + auto axes = node.get_attribute>("squeeze_dims"); + auto axes_const = make_shared(element::i32, Shape{axes.size()}, axes); + auto res = make_shared(input, axes_const); + set_node_name(node.get_name(), res); + return res->outputs(); } } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/strided_slice.cpp b/ngraph/frontend/tensorflow/src/op/strided_slice.cpp new file mode 100644 index 00000000000000..31cc7f63d91b86 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/strided_slice.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_strided_slice_op(const NodeContext& node) { + auto input = node.get_input(0); + auto begin = node.get_input(1); + auto end = node.get_input(2); + auto strides = node.get_input(3); + + auto begin_mask = node.get_attribute("begin_mask"); + auto end_mask = node.get_attribute("end_mask"); + auto new_axis_mask = node.get_attribute("new_axis_mask"); + auto ellipsis_mask = node.get_attribute("ellipsis_mask"); + auto shrink_axis_mask = node.get_attribute("shrink_axis_mask"); + + auto mask_to_vec = [](int32_t mask) { + auto length = sizeof(mask) * CHAR_BIT; + vector vec(length, 0); + if (mask == 0) { + return vec; + } + for (auto i = 0; i < length; ++i) { + if (static_cast(mask >> i & 0x01) == 1) { + vec[i] = 1; + } + } + return vec; + }; + + auto res = make_shared(input, + begin, + end, + strides, + mask_to_vec(begin_mask), + mask_to_vec(end_mask), + mask_to_vec(new_axis_mask), + mask_to_vec(shrink_axis_mask), + mask_to_vec(ellipsis_mask)); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/tile.cpp b/ngraph/frontend/tensorflow/src/op/tile.cpp new file mode 100644 index 00000000000000..b3c63ddad27048 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/tile.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_tile_op(const NodeContext& node) { + auto data = node.get_input(0); + auto repeats = node.get_input(1); + + auto res = make_shared(data, repeats); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/top_k.cpp b/ngraph/frontend/tensorflow/src/op/top_k.cpp new file mode 100644 index 00000000000000..4826a8efbcdccc --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/top_k.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_top_k_v2_op(const NodeContext& node) { + auto input = node.get_input(0); + auto k = node.get_input(1); + + TF_OP_VALIDATION_CHECK(node, input.get_partial_shape().rank().is_static(), "Input rank must be static."); + TF_OP_VALIDATION_CHECK(node, + input.get_partial_shape().rank().get_length() >= 1, + "Input rank must be greater than 0."); + // axis along which to compute top k indices + int64_t k_axis = input.get_partial_shape().rank().get_length() - 1; + bool sorted = node.get_attribute("sorted", true); + auto res = std::make_shared(input, + k, + k_axis, + TopK::Mode::MAX, + sorted ? TopK::SortType::SORT_VALUES : TopK::SortType::SORT_INDICES); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/transpose.cpp b/ngraph/frontend/tensorflow/src/op/transpose.cpp new file mode 100644 index 00000000000000..0a07c8e43c3765 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/transpose.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_transpose_op(const NodeContext& node) { + auto input = node.get_input(0); + auto order = node.get_input(1); + auto res = make_shared(input, order); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/unary_op.cpp b/ngraph/frontend/tensorflow/src/op/unary_op.cpp index 028be04342f704..e1d894027620e8 100644 --- a/ngraph/frontend/tensorflow/src/op/unary_op.cpp +++ b/ngraph/frontend/tensorflow/src/op/unary_op.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // -#include -#include +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" using namespace std; using namespace ov::opset8; @@ -13,82 +13,47 @@ namespace frontend { namespace tf { namespace op { -// Helper function to translate a unary op. -// -// Parameters: -// -// TFNodeDecoder* op - TF op being translated. Must have one input. -// const std::vector& static_input_map -// - the static input map -// Builder::OpMap& ng_op_map - The TF-to-nGraph op map. -// -// std::function(Output> -// create_unary_op - Function to construct the graph implementing -// the unary op, given the input to the unop -// as an argument. -// -// Example usage: -// -// if (n->type_string == "Square") { -// TF_RETURN_IF_ERROR(TranslateUnaryOp(n, static_input_map, ng_op_map, -// [] (Output n) { -// return -// (Output(n,n)); -// }); -// } -OutputVector TranslateUnaryOp(const NodeContext& op, std::function(Output)> create_unary_op) { - Output ng_input = op.get_ng_input(0); - auto ng_node = create_unary_op(ng_input); - if (ng_node != ng_input) { - SetTracingInfo(op.get_name(), ng_node); - } - // SaveNgOp(ng_op_map, node.get_name(), ng_node); - // return Status::OK(); - return {ng_node}; +OutputVector translate_unary_op(const NodeContext& op, + const std::function(Output)>& create_unary_op) { + auto ng_input = op.get_input(0); + auto res = create_unary_op(ng_input); + set_node_name(op.get_name(), res); + return {res}; } -// Helper function to translate a unary op in cases where there is a one-to-one -// mapping from TensorFlow ops to nGraph ops. -// -// Example usage: -// -// if (n->type_string == "Abs") { -// TF_RETURN_IF_ERROR(TranslateUnaryOp(n, static_input_map, -// ng_op_map)); -// } -// template -OutputVector TranslateUnaryOp(const NodeContext& node) { - return TranslateUnaryOp(node, [&node](Output n) { - return ConstructNgNode(node.get_name(), n); +OutputVector translate_unary_op(const NodeContext& node) { + return translate_unary_op(node, [](Output n) { + return make_shared(n); }); } -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); -template OutputVector TranslateUnaryOp(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); +template OutputVector translate_unary_op(const NodeContext& node); } // namespace op } // namespace tf } // namespace frontend -} // namespace ov +} // namespace ov \ No newline at end of file diff --git a/ngraph/frontend/tensorflow/src/op/unpack.cpp b/ngraph/frontend/tensorflow/src/op/unpack.cpp new file mode 100644 index 00000000000000..772ee493bae75b --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/unpack.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_unpack_op(const NodeContext& node) { + auto input = node.get_input(0); + auto axis = node.get_attribute("axis"); + auto num = node.get_attribute("num"); + + auto axis_const = make_shared(element::i64, Shape{}, axis); + auto res = make_shared(input, axis_const, num); + set_node_name(node.get_name(), res); + return res->outputs(); +} +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/where.cpp b/ngraph/frontend/tensorflow/src/op/where.cpp new file mode 100644 index 00000000000000..cdddb82f5dc721 --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/where.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_where_op(const NodeContext& node) { + auto x = node.get_input(0); + auto non_zero = make_shared(x); + auto transpose_order = make_shared(element::i64, Shape{2}, vector{1, 0}); + auto res = make_shared(non_zero, transpose_order); + set_node_name(node.get_name(), res); + return res->outputs(); +} + +} // namespace op +} // namespace tf +} // namespace frontend +} // namespace ov diff --git a/ngraph/frontend/tensorflow/src/op/xdivy.cpp b/ngraph/frontend/tensorflow/src/op/xdivy.cpp new file mode 100644 index 00000000000000..121efbc58ee98d --- /dev/null +++ b/ngraph/frontend/tensorflow/src/op/xdivy.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "op_table.hpp" +#include "openvino/opsets/opset8.hpp" + +using namespace std; +using namespace ov::opset8; + +namespace ov { +namespace frontend { +namespace tf { +namespace op { + +OutputVector translate_x_div_y_op(const NodeContext& node) { + auto x = node.get_input(0); + auto y = node.get_input(1); + + auto zero = make_shared(x.get_element_type(), Shape{}, 0); + auto x_is_zero = make_shared(x, zero); + auto one = make_shared(x.get_element_type(), Shape{}, 1); + auto select = make_shared + + 1 + 0 + + + 1 + 0 + + + + + 1 + 0 + + + + + + + + 1 + + + + + + + 1 + 0 + + + 1 + + + + + 0 + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ngraph/test/models/onnx/clip_no_min_no_max.prototxt b/ngraph/test/models/onnx/clip_no_min_no_max.prototxt new file mode 100644 index 00000000000000..082bdf84123d0a --- /dev/null +++ b/ngraph/test/models/onnx/clip_no_min_no_max.prototxt @@ -0,0 +1,48 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "" + input: "" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/clip_no_min_no_max_int64.prototxt b/ngraph/test/models/onnx/clip_no_min_no_max_int64.prototxt new file mode 100644 index 00000000000000..03300976a8ff9d --- /dev/null +++ b/ngraph/test/models/onnx/clip_no_min_no_max_int64.prototxt @@ -0,0 +1,48 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "" + input: "" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + input { + name: "X" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/clip_no_min_set_max.prototxt b/ngraph/test/models/onnx/clip_no_min_set_max.prototxt new file mode 100644 index 00000000000000..e5e027600e581f --- /dev/null +++ b/ngraph/test/models/onnx/clip_no_min_set_max.prototxt @@ -0,0 +1,58 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "" + input: "MAX" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + input { + name: "MAX" + type { + tensor_type { + elem_type: 1 + shape { + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 3 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/clip_no_min_set_max_int64.prototxt b/ngraph/test/models/onnx/clip_no_min_set_max_int64.prototxt new file mode 100644 index 00000000000000..08c4e2e709b6f2 --- /dev/null +++ b/ngraph/test/models/onnx/clip_no_min_set_max_int64.prototxt @@ -0,0 +1,58 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "" + input: "MAX" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + input { + name: "X" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + input { + name: "MAX" + type { + tensor_type { + elem_type: 7 + shape { + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/clip_set_min_no_max.prototxt b/ngraph/test/models/onnx/clip_set_min_no_max.prototxt new file mode 100644 index 00000000000000..10fcc2c46691ed --- /dev/null +++ b/ngraph/test/models/onnx/clip_set_min_no_max.prototxt @@ -0,0 +1,58 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "MIN" + input: "" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + input { + name: "MIN" + type { + tensor_type { + elem_type: 1 + shape { + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/clip_set_min_no_max_initializers.prototxt b/ngraph/test/models/onnx/clip_set_min_no_max_initializers.prototxt new file mode 100644 index 00000000000000..0901b86fb7af73 --- /dev/null +++ b/ngraph/test/models/onnx/clip_set_min_no_max_initializers.prototxt @@ -0,0 +1,53 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "MIN" + input: "" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + initializer { + data_type: 1 + float_data: -1.590000033378601 + name: "MIN" + } + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/clip_set_min_set_max.prototxt b/ngraph/test/models/onnx/clip_set_min_set_max.prototxt new file mode 100644 index 00000000000000..a5ad023d81dfc6 --- /dev/null +++ b/ngraph/test/models/onnx/clip_set_min_set_max.prototxt @@ -0,0 +1,68 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "MIN" + input: "MAX" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + input { + name: "MIN" + type { + tensor_type { + elem_type: 1 + shape { + } + } + } + } + input { + name: "MAX" + type { + tensor_type { + elem_type: 1 + shape { + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/clip_set_min_set_max_initializers.prototxt b/ngraph/test/models/onnx/clip_set_min_set_max_initializers.prototxt new file mode 100644 index 00000000000000..c09b604cee7e2a --- /dev/null +++ b/ngraph/test/models/onnx/clip_set_min_set_max_initializers.prototxt @@ -0,0 +1,58 @@ +ir_version: 8 +producer_name: "onnx-importer-test" +graph { + node { + input: "X" + input: "MIN" + input: "MAX" + output: "Y" + op_type: "Clip" + } + name: "test-model-clip" + initializer { + data_type: 1 + float_data: -1.590000033378601 + name: "MIN" + } + initializer { + data_type: 1 + float_data: 2.009999990463257 + name: "MAX" + } + input { + name: "X" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "Y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + domain: "" + version: 12 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention.prototxt b/ngraph/test/models/onnx/com.microsoft/attention.prototxt new file mode 100644 index 00000000000000..53ac350573b055 --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention.prototxt @@ -0,0 +1,123 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + output: "output" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_dynamic_shapes.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_dynamic_shapes.prototxt new file mode 100644 index 00000000000000..97a4f3f1f9134a --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_dynamic_shapes.prototxt @@ -0,0 +1,90 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + input: "mask" + input: "past" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + input { + name: "input" + type { + tensor_type { + elem_type: 1 + } + } + } + input { + name: "weights" + type { + tensor_type { + elem_type: 1 + } + } + } + input { + name: "bias" + type { + tensor_type { + elem_type: 1 + } + } + } + input { + name: "mask" + type { + tensor_type { + elem_type: 6 + shape { + dim {} + dim {} + } + } + } + } + input { + name: "past" + type { + tensor_type { + elem_type: 1 + } + } + } + + output { + name: "output" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_extra_add.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_extra_add.prototxt new file mode 100644 index 00000000000000..f8664f4507f459 --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_extra_add.prototxt @@ -0,0 +1,190 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + input: "mask" + input: "" + input: "extra_add" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "mask" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + input { + name: "extra_add" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_mask_index_1.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_1.prototxt new file mode 100644 index 00000000000000..56d4e1d1142a4e --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_1.prototxt @@ -0,0 +1,163 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + input: "mask_index" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "mask_index" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_mask_index_2.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_2.prototxt new file mode 100644 index 00000000000000..481d9ea86f5488 --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_2.prototxt @@ -0,0 +1,168 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + input: "mask_index" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + attribute { + name: "unidirectional" + i: 1 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "mask_index" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_mask_index_3.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_3.prototxt new file mode 100644 index 00000000000000..67558f33599282 --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_3.prototxt @@ -0,0 +1,166 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + input: "mask" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "mask" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_mask_index_4.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_4.prototxt new file mode 100644 index 00000000000000..9b9387991a9c64 --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_mask_index_4.prototxt @@ -0,0 +1,169 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + input: "mask" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "mask" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_past.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_past.prototxt new file mode 100644 index 00000000000000..7625195fa044c8 --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_past.prototxt @@ -0,0 +1,193 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + input: "mask" + input: "past" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + input { + name: "mask" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 9 + } + } + } + } + } + input { + name: "past" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 5 + } + dim { + dim_value: 2 + } + } + } + } + } + + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 9 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_qkv_hidden_sizes.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_qkv_hidden_sizes.prototxt new file mode 100644 index 00000000000000..5ee43aa5c3624a --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_qkv_hidden_sizes.prototxt @@ -0,0 +1,130 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + output: "output" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + attribute { + name: "qkv_hidden_sizes" + ints: 2 + ints: 2 + ints: 8 + type: INTS + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 8 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/com.microsoft/attention_unidirectional.prototxt b/ngraph/test/models/onnx/com.microsoft/attention_unidirectional.prototxt new file mode 100644 index 00000000000000..31a65b299d60ee --- /dev/null +++ b/ngraph/test/models/onnx/com.microsoft/attention_unidirectional.prototxt @@ -0,0 +1,154 @@ +ir_version: 6 +producer_name: "nGraph" +graph { + node { + input: "input" + input: "weights" + input: "bias" + output: "output" + output: "present" + name: "Attention_1" + op_type: "Attention" + attribute { + name: "num_heads" + i: 2 + type: INT + } + attribute { + name: "unidirectional" + i: 1 + type: INT + } + domain: "com.microsoft" + } + name: "attention-model" + initializer { + name: "weights" + dims: 3 + dims: 12 + data_type: 1 + float_data: 0.01326417364180088 + float_data: -0.017005326226353645 + float_data: 0.021556973457336426 + float_data: -0.079218357801437378 + float_data: -0.019958715885877609 + float_data: 0.066062852740287781 + float_data: -0.063465960323810577 + float_data: -0.036202378571033478 + float_data: -0.038673330098390579 + float_data: -0.050637193024158478 + float_data: 0.0024814880453050137 + float_data: -0.017267324030399323 + float_data: -0.0047671985812485218 + float_data: -0.014202062971889973 + float_data: 0.10090816766023636 + float_data: 0.044896259903907776 + float_data: 0.015443948097527027 + float_data: -0.0010053194127976894 + float_data: 0.071923978626728058 + float_data: 0.01173736434429884 + float_data: 0.034053854644298553 + float_data: -0.037060577422380447 + float_data: 0.01355923805385828 + float_data: 0.054467327892780304 + float_data: 0.088897556066513062 + float_data: 0.019563071429729462 + float_data: 0.025579970329999924 + float_data: -0.032200627028942108 + float_data: -0.0083356937393546104 + float_data: -0.10528338700532913 + float_data: 0.04967513307929039 + float_data: -0.093638911843299866 + float_data: 0.0018587876111268997 + float_data: 0.01037109550088644 + float_data: -0.011854520998895168 + float_data: 0.035907052457332611 + } + initializer { + name: "bias" + dims: 12 + data_type: 1 + float_data: -0.2587452232837677 + float_data: -0.095395378768444061 + float_data: 0.12785771489143372 + float_data: 0.16469171643257141 + float_data: -0.58997648954391479 + float_data: -0.28082749247550964 + float_data: 0.077637940645217896 + float_data: -0.03203071653842926 + float_data: 0.075582884252071381 + float_data: 0.14739133417606354 + float_data: -0.19812127947807312 + float_data: 0.50444173812866211 + } + input { + name: "input" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 3 + } + } + } + } + } + output { + name: "output" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "present" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + dim { + dim_value: 4 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 11 +} +opset_import { + domain: "com.microsoft" + version: 1 +} diff --git a/ngraph/test/models/onnx/bias_gelu.prototxt b/ngraph/test/models/onnx/com.microsoft/bias_gelu.prototxt similarity index 100% rename from ngraph/test/models/onnx/bias_gelu.prototxt rename to ngraph/test/models/onnx/com.microsoft/bias_gelu.prototxt diff --git a/ngraph/test/models/onnx/embed_layer_normalization.prototxt b/ngraph/test/models/onnx/com.microsoft/embed_layer_normalization.prototxt similarity index 100% rename from ngraph/test/models/onnx/embed_layer_normalization.prototxt rename to ngraph/test/models/onnx/com.microsoft/embed_layer_normalization.prototxt diff --git a/ngraph/test/models/onnx/dynamic_shapes/embed_layer_normalization_dynamic_shapes.prototxt b/ngraph/test/models/onnx/com.microsoft/embed_layer_normalization_dynamic_shapes.prototxt similarity index 100% rename from ngraph/test/models/onnx/dynamic_shapes/embed_layer_normalization_dynamic_shapes.prototxt rename to ngraph/test/models/onnx/com.microsoft/embed_layer_normalization_dynamic_shapes.prototxt diff --git a/ngraph/test/models/onnx/embed_layer_normalization_with_segment_embedding.prototxt b/ngraph/test/models/onnx/com.microsoft/embed_layer_normalization_with_segment_embedding.prototxt similarity index 100% rename from ngraph/test/models/onnx/embed_layer_normalization_with_segment_embedding.prototxt rename to ngraph/test/models/onnx/com.microsoft/embed_layer_normalization_with_segment_embedding.prototxt diff --git a/ngraph/test/models/onnx/embed_layer_normalization_with_segment_embedding_and_mask.prototxt b/ngraph/test/models/onnx/com.microsoft/embed_layer_normalization_with_segment_embedding_and_mask.prototxt similarity index 100% rename from ngraph/test/models/onnx/embed_layer_normalization_with_segment_embedding_and_mask.prototxt rename to ngraph/test/models/onnx/com.microsoft/embed_layer_normalization_with_segment_embedding_and_mask.prototxt diff --git a/ngraph/test/models/onnx/dynamic_shapes/skip_layer_normalization.prototxt b/ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_dynamic_shapes.prototxt similarity index 100% rename from ngraph/test/models/onnx/dynamic_shapes/skip_layer_normalization.prototxt rename to ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_dynamic_shapes.prototxt diff --git a/ngraph/test/models/onnx/skip_layer_normalization_with_gamma.prototxt b/ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_with_gamma.prototxt similarity index 100% rename from ngraph/test/models/onnx/skip_layer_normalization_with_gamma.prototxt rename to ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_with_gamma.prototxt diff --git a/ngraph/test/models/onnx/skip_layer_normalization_with_gamma_beta.prototxt b/ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_with_gamma_beta.prototxt similarity index 100% rename from ngraph/test/models/onnx/skip_layer_normalization_with_gamma_beta.prototxt rename to ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_with_gamma_beta.prototxt diff --git a/ngraph/test/models/onnx/skip_layer_normalization_with_gamma_beta_bias.prototxt b/ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_with_gamma_beta_bias.prototxt similarity index 100% rename from ngraph/test/models/onnx/skip_layer_normalization_with_gamma_beta_bias.prototxt rename to ngraph/test/models/onnx/com.microsoft/skip_layer_normalization_with_gamma_beta_bias.prototxt diff --git a/ngraph/test/models/onnx/max_pool_3d.prototxt b/ngraph/test/models/onnx/max_pool_3d.prototxt new file mode 100644 index 00000000000000..d84830a05d30ec --- /dev/null +++ b/ngraph/test/models/onnx/max_pool_3d.prototxt @@ -0,0 +1,76 @@ +ir_version: 3 +producer_name: "backend-test" +graph { + node { + input: "x" + output: "y" + output: "z" + op_type: "MaxPool" + attribute { + name: "kernel_shape" + ints: 2 + type: INTS + } + } + name: "maxpool_test" + input { + name: "x" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 3 + } + } + } + } + } + output { + name: "y" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "z" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/max_pool_4d_ceil_mode.prototxt b/ngraph/test/models/onnx/max_pool_4d_ceil_mode.prototxt new file mode 100644 index 00000000000000..456aa6df3c4773 --- /dev/null +++ b/ngraph/test/models/onnx/max_pool_4d_ceil_mode.prototxt @@ -0,0 +1,91 @@ +ir_version: 3 +producer_name: "backend-test" +graph { + node { + input: "x" + output: "y" + output: "z" + op_type: "MaxPool" + attribute { + name: "kernel_shape" + ints: 3 + ints: 3 + type: INTS + } + attribute { + name: "ceil_mode" + i: 1 + type: INT + } + } + name: "maxpool_test" + input { + name: "x" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "y" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "z" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/max_pool_4d_ceil_strides.prototxt b/ngraph/test/models/onnx/max_pool_4d_ceil_strides.prototxt new file mode 100644 index 00000000000000..dab7cfdb0908f3 --- /dev/null +++ b/ngraph/test/models/onnx/max_pool_4d_ceil_strides.prototxt @@ -0,0 +1,97 @@ +ir_version: 4 +producer_name: "backend-test" +graph { + node { + input: "x" + output: "y" + output: "z" + op_type: "MaxPool" + attribute { + name: "ceil_mode" + i: 1 + type: INT + } + attribute { + name: "kernel_shape" + ints: 3 + ints: 3 + type: INTS + } + attribute { + name: "strides" + ints: 2 + ints: 2 + type: INTS + } + } + name: "test_maxpool_2d_ceil" + input { + name: "x" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "z" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 10 +} diff --git a/ngraph/test/models/onnx/max_pool_4d_dilations.prototxt b/ngraph/test/models/onnx/max_pool_4d_dilations.prototxt new file mode 100644 index 00000000000000..12cfdbe162bb2f --- /dev/null +++ b/ngraph/test/models/onnx/max_pool_4d_dilations.prototxt @@ -0,0 +1,92 @@ +ir_version: 3 +producer_name: "backend-test" +graph { + node { + input: "x" + output: "y" + output: "z" + op_type: "MaxPool" + attribute { + name: "kernel_shape" + ints: 2 + ints: 2 + type: INTS + } + attribute { + name: "dilations" + ints: 2 + ints: 2 + type: INTS + } + } + name: "maxpool_test" + input { + name: "x" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + output { + name: "y" + type { + tensor_type { + elem_type: 6 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "z" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/max_pool_4d_strides.prototxt b/ngraph/test/models/onnx/max_pool_4d_strides.prototxt new file mode 100644 index 00000000000000..2c207a1a9c0cc7 --- /dev/null +++ b/ngraph/test/models/onnx/max_pool_4d_strides.prototxt @@ -0,0 +1,100 @@ +ir_version: 3 +producer_name: "backend-test" +graph { + node { + input: "x" + output: "y" + output: "z" + op_type: "MaxPool" + attribute { + name: "kernel_shape" + ints: 3 + ints: 3 + type: INTS + } + attribute { + name: "strides" + ints: 3 + ints: 3 + type: INTS + } + attribute { + name: "pads" + ints: 2 + ints: 2 + ints: 2 + ints: 2 + type: INTS + } + } + name: "maxpool_test" + input { + name: "x" + type { + tensor_type { + elem_type: 3 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 5 + } + dim { + dim_value: 5 + } + } + } + } + } + output { + name: "y" + type { + tensor_type { + elem_type: 3 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 3 + } + } + } + } + } + output { + name: "z" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 3 + } + } + } + } + } +} +opset_import { + version: 13 +} diff --git a/ngraph/test/models/onnx/random_normal.prototxt b/ngraph/test/models/onnx/random_normal.prototxt new file mode 100644 index 00000000000000..bebf03d10d8163 --- /dev/null +++ b/ngraph/test/models/onnx/random_normal.prototxt @@ -0,0 +1,49 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + output: "y" + op_type: "RandomNormal" + attribute { + name: "shape" + ints: 2 + ints: 2 + type: INTS + } + attribute { + name: "mean" + f: 50 + type: FLOAT + } + attribute { + name: "scale" + f: 40 + type: FLOAT + } + attribute { + name: "seed" + i: 100 + type: INT + } + } + name: "test_model" + output { + name: "y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/models/onnx/random_normal_like.prototxt b/ngraph/test/models/onnx/random_normal_like.prototxt new file mode 100644 index 00000000000000..eb901eb33a3607 --- /dev/null +++ b/ngraph/test/models/onnx/random_normal_like.prototxt @@ -0,0 +1,60 @@ +ir_version: 3 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "x" + output: "y" + op_type: "RandomNormalLike" + attribute { + name: "mean" + f: 50 + type: FLOAT + } + attribute { + name: "scale" + f: 40 + type: FLOAT + } + attribute { + name: "seed" + i: 100 + type: INT + } + } + name: "test_model" + input { + name: "x" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "y" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } +} +opset_import { + version: 1 +} diff --git a/ngraph/test/models/onnx/random_uniform.prototxt b/ngraph/test/models/onnx/random_uniform.prototxt index 00b7d8ee3a5ae9..ce8e57b867e22c 100644 --- a/ngraph/test/models/onnx/random_uniform.prototxt +++ b/ngraph/test/models/onnx/random_uniform.prototxt @@ -22,8 +22,8 @@ graph { } attribute { name: "seed" - i: 100 - type: INT + f: 100 + type: FLOAT } } name: "test_model" diff --git a/ngraph/test/models/onnx/random_uniform_like.prototxt b/ngraph/test/models/onnx/random_uniform_like.prototxt index c90a94c7eca2fc..92b6904700e4eb 100644 --- a/ngraph/test/models/onnx/random_uniform_like.prototxt +++ b/ngraph/test/models/onnx/random_uniform_like.prototxt @@ -17,8 +17,8 @@ graph { } attribute { name: "seed" - i: 100 - type: INT + f: 100 + type: FLOAT } } name: "test_model" diff --git a/ngraph/test/models/onnx/tensor_names.prototxt b/ngraph/test/models/onnx/tensor_names.prototxt index 784beb19916e04..6b5b521220e375 100644 --- a/ngraph/test/models/onnx/tensor_names.prototxt +++ b/ngraph/test/models/onnx/tensor_names.prototxt @@ -3,6 +3,12 @@ producer_name: "test_model" graph { node { input: "input" + output: "identity_on_input" + name: "identity_node_on_input" + op_type: "Identity" + } + node { + input: "identity_on_input" output: "relu_t" op_type: "Relu" name: "relu" diff --git a/ngraph/test/models/onnx/transformations/reference/softmax_crossentropy_consumed_expanded.prototxt b/ngraph/test/models/onnx/transformations/reference/softmax_crossentropy_consumed_expanded.prototxt index 307c80d8d5b511..70214b9957b5fe 100644 --- a/ngraph/test/models/onnx/transformations/reference/softmax_crossentropy_consumed_expanded.prototxt +++ b/ngraph/test/models/onnx/transformations/reference/softmax_crossentropy_consumed_expanded.prototxt @@ -2,58 +2,80 @@ ir_version: 7 producer_name: "nGraph ONNX Importer" graph { node { - output: "Func_SoftmaxCrossEntropyLoss0x557617acabe0axes" + output: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640Shape3D" op_type: "Constant" attribute { name: "value" t { - dims: 1 + dims: 3 data_type: 7 - int64_data: 1 + int64_data: 0 + int64_data: 0 + int64_data: -1 } type: TENSOR } + domain: "" } node { input: "x" - output: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Max" - op_type: "ReduceMax" + input: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640Shape3D" + output: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_NCD" + op_type: "Reshape" + domain: "" + } + node { + input: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_NCD" + output: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_NDC" + op_type: "Transpose" attribute { - name: "axes" + name: "perm" + ints: 0 + ints: 2 ints: 1 type: INTS } + domain: "" } node { - input: "x" - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Max" - output: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Sub" - op_type: "Sub" - } - node { - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Sub" - output: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Exp" - op_type: "Exp" + input: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_NDC" + output: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_LogSM" + op_type: "LogSoftmax" + attribute { + name: "axis" + i: 2 + type: INT + } + domain: "" } node { - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Exp" - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0axes" - output: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_RS" - op_type: "ReduceSum" + input: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_LogSM" + output: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_LogSM_NCD" + op_type: "Transpose" + attribute { + name: "perm" + ints: 0 + ints: 2 + ints: 1 + type: INTS + } + domain: "" } node { - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Exp" - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_RS" - output: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Div" - op_type: "Div" + input: "x" + output: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_shape" + op_type: "Shape" + domain: "" } node { - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Div" - output: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Log" - op_type: "Log" + input: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_LogSM_NCD" + input: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_shape" + output: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_Log" + op_type: "Reshape" + domain: "" } node { - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0const_zero" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640const_zero" op_type: "Constant" attribute { name: "value" @@ -64,9 +86,10 @@ graph { } type: TENSOR } + domain: "" } node { - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0const_one" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640const_one" op_type: "Constant" attribute { name: "value" @@ -77,9 +100,10 @@ graph { } type: TENSOR } + domain: "" } node { - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0axes" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640axes" op_type: "Constant" attribute { name: "value" @@ -90,45 +114,51 @@ graph { } type: TENSOR } + domain: "" } node { input: "y" - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0axes" - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0expanded_target" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640axes" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640expanded_target" op_type: "Unsqueeze" + domain: "" } node { - input: "Func_SoftmaxCrossEntropyLoss0x557617acabe0X_Log" - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0expanded_target" - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0input_gather_element" + input: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_Log" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640expanded_target" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640input_gather_element" op_type: "GatherElements" attribute { name: "axis" i: 1 type: INT } + domain: "" } node { - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0input_gather_element" - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0loss_NCdd" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640input_gather_element" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640loss_NCdd" op_type: "Neg" + domain: "" } node { - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0loss_NCdd" - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0const_zero" - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0const_one" - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0const_one" - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0loss_N1dd" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640loss_NCdd" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640const_zero" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640const_one" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640const_one" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640loss_N1dd" op_type: "Slice" + domain: "" } node { - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0loss_N1dd" - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0axes" - output: "Func_NegativeLogLikelihoodLoss0x557617d1bba0loss_Ndd" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640loss_N1dd" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640axes" + output: "Func_NegativeLogLikelihoodLoss0x7ffe150df640loss_Ndd" op_type: "Squeeze" + domain: "" } node { - input: "Func_NegativeLogLikelihoodLoss0x557617d1bba0loss_Ndd" + input: "Func_NegativeLogLikelihoodLoss0x7ffe150df640loss_Ndd" output: "z" op_type: "ReduceMean" attribute { @@ -136,6 +166,7 @@ graph { i: 0 type: INT } + domain: "" } node { input: "z" @@ -186,6 +217,126 @@ graph { } } } + value_info { + name: "z" + type { + tensor_type { + elem_type: 1 + shape { + } + } + } + } + value_info { + name: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640Shape3D" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 3 + } + } + } + } + } + value_info { + name: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_NCD" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 3 + } + dim { + dim_value: 5 + } + dim { + dim_value: 1 + } + } + } + } + } + value_info { + name: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_NDC" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 3 + } + dim { + dim_value: 1 + } + dim { + dim_value: 5 + } + } + } + } + } + value_info { + name: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_LogSM" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 3 + } + dim { + dim_value: 1 + } + dim { + dim_value: 5 + } + } + } + } + } + value_info { + name: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_LogSM_NCD" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 3 + } + dim { + dim_value: 5 + } + dim { + dim_value: 1 + } + } + } + } + } + value_info { + name: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_shape" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 2 + } + } + } + } + } + value_info { + name: "Func_SoftmaxCrossEntropyLoss0x7ffe150df640X_Log" + type { + tensor_type { + elem_type: 1 + } + } + } } opset_import { version: 13 diff --git a/ngraph/test/onnx/onnx_editor.cpp b/ngraph/test/onnx/onnx_editor.cpp index 12ac45826c4870..69521c64a79b68 100644 --- a/ngraph/test/onnx/onnx_editor.cpp +++ b/ngraph/test/onnx/onnx_editor.cpp @@ -19,8 +19,8 @@ NGRAPH_SUPPRESS_DEPRECATED_START -using namespace ngraph; -using namespace onnx_editor; +using namespace ov; +using namespace ov::onnx_editor; using namespace ngraph::test; static std::string s_manifest = "${MANIFEST}"; @@ -35,7 +35,7 @@ InputTypePred element_type_is(const element::Type et) { }; } -std::shared_ptr find_input(const ParameterVector& inputs, const std::string& name) { +std::shared_ptr find_input(const ParameterVector& inputs, const std::string& name) { const auto input_pos = std::find_if(std::begin(inputs), std::end(inputs), [&name](const ParameterVector::value_type i) { return i->get_friendly_name() == name; @@ -47,7 +47,7 @@ std::shared_ptr find_input(const ParameterVector& inputs, const s NGRAPH_TEST(onnx_editor, types__single_input_type_substitution) { // the original model contains 2 inputs with i64 data type and one f32 input - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; editor.set_input_types({{"A", element::i64}}); @@ -68,7 +68,7 @@ NGRAPH_TEST(onnx_editor, types__single_input_type_substitution) { NGRAPH_TEST(onnx_editor, types__all_inputs_type_substitution) { // the original model contains 2 inputs with i64 data type and one f32 input - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; editor.set_input_types({{"A", element::i8}, {"B", element::i8}, {"C", element::i8}}); @@ -87,34 +87,37 @@ NGRAPH_TEST(onnx_editor, types__all_inputs_type_substitution) { } NGRAPH_TEST(onnx_editor, types__missing_type_in_input_descriptor) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/invalid_input_no_type.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/invalid_input_no_type.onnx")}; // input A doesn't have the "type" field in the model and so the data type cannot be modified - EXPECT_THROW(editor.set_input_types({{"A", element::f32}}), ngraph_error); + EXPECT_THROW(editor.set_input_types({{"A", element::f32}}), ngraph::ngraph_error); } NGRAPH_TEST(onnx_editor, types__missing_tensor_type_in_input_descriptor) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/invalid_input_no_tensor_type.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/invalid_input_no_tensor_type.onnx")}; // input A doesn't have the "tensor_type" field in the model - EXPECT_THROW(editor.set_input_types({{"A", element::f32}}), ngraph_error); + EXPECT_THROW(editor.set_input_types({{"A", element::f32}}), ngraph::ngraph_error); } NGRAPH_TEST(onnx_editor, types__unsupported_data_type_passed) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; - EXPECT_THROW(editor.set_input_types({{"A", element::dynamic}}), ngraph_error); + EXPECT_THROW(editor.set_input_types({{"A", element::dynamic}}), ngraph::ngraph_error); } NGRAPH_TEST(onnx_editor, types__incorrect_input_name_passed) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_abc.onnx")}; - EXPECT_THROW(editor.set_input_types({{"ShiaLaBeouf", element::i64}}), ngraph_error); + EXPECT_THROW(editor.set_input_types({{"ShiaLaBeouf", element::i64}}), ngraph::ngraph_error); } NGRAPH_TEST(onnx_editor, types__elem_type_missing_in_input) { // the original model contains 2 inputs with i64 data type and one f32 input - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/elem_type_missing_in_input.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/elem_type_missing_in_input.onnx")}; // the "elem_type" is missing in the model but it should be possible to set the type anyway EXPECT_NO_THROW(editor.set_input_types({{"A", element::i64}})); @@ -133,7 +136,8 @@ NGRAPH_TEST(onnx_editor, types__elem_type_missing_in_input) { } NGRAPH_TEST(onnx_editor, shapes__modify_single_input) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; const auto new_shape = PartialShape{1}; @@ -146,7 +150,8 @@ NGRAPH_TEST(onnx_editor, shapes__modify_single_input) { } NGRAPH_TEST(onnx_editor, shapes__modify_all_inputs) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; const auto new_shape = PartialShape{1, 2, 3, 5, 8, 13}; @@ -162,7 +167,7 @@ NGRAPH_TEST(onnx_editor, shapes__modify_all_inputs) { NGRAPH_TEST(onnx_editor, shapes__dynamic_rank_in_model) { ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__dynamic_rank_in_model.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__dynamic_rank_in_model.onnx")}; // input A in the model doesn't have the "shape" field meaning it has dynamic rank // it should still be possible to set such input's shape to some custom value @@ -176,7 +181,8 @@ NGRAPH_TEST(onnx_editor, shapes__dynamic_rank_in_model) { } NGRAPH_TEST(onnx_editor, shapes__set_dynamic_dimension) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; const auto new_shape = PartialShape{Dimension::dynamic()}; @@ -189,7 +195,8 @@ NGRAPH_TEST(onnx_editor, shapes__set_dynamic_dimension) { } NGRAPH_TEST(onnx_editor, shapes__set_mixed_dimensions) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; const auto new_shape_A = PartialShape{21, Dimension::dynamic()}; const auto new_shape_B = PartialShape{Dimension::dynamic(), 37}; @@ -207,7 +214,8 @@ NGRAPH_TEST(onnx_editor, shapes__set_mixed_dimensions) { } NGRAPH_TEST(onnx_editor, shapes__set_scalar_inputs) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; const auto new_shape = PartialShape{}; @@ -224,7 +232,8 @@ NGRAPH_TEST(onnx_editor, shapes__set_scalar_inputs) { } NGRAPH_TEST(onnx_editor, shapes__static_to_dynamic_rank_substitution) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/shapes__add_two_inputs.onnx")}; const auto new_shape = PartialShape::dynamic(); @@ -239,12 +248,14 @@ NGRAPH_TEST(onnx_editor, shapes__static_to_dynamic_rank_substitution) { } NGRAPH_TEST(onnx_editor, subgraph__linear_model_head_cut) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; editor.cut_graph_fragment({{InputEdge(1, 0)}}, {}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__linear_model_head_cut.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_head_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -252,13 +263,15 @@ NGRAPH_TEST(onnx_editor, subgraph__linear_model_head_cut) { } NGRAPH_TEST(onnx_editor, subgraph__linear_model_head_cut_ins_and_outs) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; editor.cut_graph_fragment({{InputEdge(1, 0)}}, {{OutputEdge(2, 0)}}); // expected to behave the same way as subgraph__linear_model_head_cut const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__linear_model_head_cut.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_head_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -266,12 +279,14 @@ NGRAPH_TEST(onnx_editor, subgraph__linear_model_head_cut_ins_and_outs) { } NGRAPH_TEST(onnx_editor, subgraph__linear_model_deeper_head_cut) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; editor.cut_graph_fragment({{InputEdge(2, 0)}}, {}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__linear_model_deeper_head_cut.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_deeper_head_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -279,12 +294,14 @@ NGRAPH_TEST(onnx_editor, subgraph__linear_model_deeper_head_cut) { } NGRAPH_TEST(onnx_editor, subgraph__linear_model_tail_cut) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; editor.cut_graph_fragment({}, {{OutputEdge{1, 0}}}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__linear_model_tail_cut.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_tail_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -292,13 +309,15 @@ NGRAPH_TEST(onnx_editor, subgraph__linear_model_tail_cut) { } NGRAPH_TEST(onnx_editor, subgraph__linear_model_tail_cut_ins_and_outs) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; editor.cut_graph_fragment({{InputEdge{0, 0}}}, {{OutputEdge{1, 0}}}); // expected to behave the same way as subgraph__linear_model_tail_cut const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__linear_model_tail_cut.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_tail_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -307,13 +326,14 @@ NGRAPH_TEST(onnx_editor, subgraph__linear_model_tail_cut_ins_and_outs) { NGRAPH_TEST(onnx_editor, subgraph__linear_model_with_initializer_tail_cut) { ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head_with_initializer.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/subgraph__inception_head_with_initializer.onnx")}; editor.cut_graph_fragment({}, {{OutputEdge{1, 0}}}); - const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/subgraph__linear_model_with_initializer_tail_cut.onnx"); + const auto ref_model = ngraph::file_util::path_join( + SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_with_initializer_tail_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -322,13 +342,14 @@ NGRAPH_TEST(onnx_editor, subgraph__linear_model_with_initializer_tail_cut) { NGRAPH_TEST(onnx_editor, subgraph__initializer_without_matching_input_tail_cut) { ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__initializer_without_matching_input.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/subgraph__initializer_without_matching_input.onnx")}; editor.cut_graph_fragment({}, {{OutputEdge{1, 0}}}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__initializer_without_matching_input_tail_cut.onnx"); + const auto ref_model = ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__initializer_without_matching_input_tail_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -336,12 +357,14 @@ NGRAPH_TEST(onnx_editor, subgraph__initializer_without_matching_input_tail_cut) } NGRAPH_TEST(onnx_editor, subgraph__linear_model_deeper_tail_cut) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; editor.cut_graph_fragment({}, {{OutputEdge{0, 0}}}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__linear_model_deeper_tail_cut.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_deeper_tail_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -349,7 +372,8 @@ NGRAPH_TEST(onnx_editor, subgraph__linear_model_deeper_tail_cut) { } NGRAPH_TEST(onnx_editor, subgraph__no_input_params) { - const auto model_path = file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); + const auto model_path = + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); ONNXModelEditor editor{model_path}; @@ -362,13 +386,14 @@ NGRAPH_TEST(onnx_editor, subgraph__no_input_params) { NGRAPH_TEST(onnx_editor, subgraph__initializer_to_input_replacement) { ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head_with_initializer.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/subgraph__inception_head_with_initializer.onnx")}; editor.cut_graph_fragment({{InputEdge{0, 2}}}, {{OutputEdge{0, 0}}}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/subgraph__initializer_to_input_replacement.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__initializer_to_input_replacement.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -377,13 +402,14 @@ NGRAPH_TEST(onnx_editor, subgraph__initializer_to_input_replacement) { NGRAPH_TEST(onnx_editor, subgraph__initializer_to_input_replacement_2) { ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__initializer_without_matching_input.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/subgraph__initializer_without_matching_input.onnx")}; editor.cut_graph_fragment({{InputEdge{0, 2}}}, {{OutputEdge{0, 0}}}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/subgraph__initializer_to_input_replacement.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__initializer_to_input_replacement.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -391,12 +417,14 @@ NGRAPH_TEST(onnx_editor, subgraph__initializer_to_input_replacement_2) { } NGRAPH_TEST(onnx_editor, subgraph__multiout_op_output_edge) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({}, {{OutputEdge{5, 1}}}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__multiout_op_output_edge.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__multiout_op_output_edge.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -404,13 +432,14 @@ NGRAPH_TEST(onnx_editor, subgraph__multiout_op_output_edge) { } NGRAPH_TEST(onnx_editor, subgraph__existing_inputs_and_outputs_based_extraction) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({{InputEdge{1, 1}, InputEdge{2, 0}}}, {{OutputEdge{4, 0}}}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__existing_inputs_and_outputs_based_extraction.onnx"); + const auto ref_model = ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__existing_inputs_and_outputs_based_extraction.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -418,13 +447,14 @@ NGRAPH_TEST(onnx_editor, subgraph__existing_inputs_and_outputs_based_extraction) } NGRAPH_TEST(onnx_editor, subgraph__twice_input_edge_from_tensor_with_single_consumer) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; editor.cut_graph_fragment({InputEdge{1, 1}}, {}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__twice_input_edge_from_tensor_with_single_consumer.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__twice_input_edge_from_tensor_with_single_consumer.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -432,13 +462,15 @@ NGRAPH_TEST(onnx_editor, subgraph__twice_input_edge_from_tensor_with_single_cons } NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumers) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({{InputEdge{1, 0}, InputEdge{6, 0}}}, {{OutputEdge{6, 0}, OutputEdge{4, 0}}}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__input_edge_from_tensor_with_multiple_consumers.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__input_edge_from_tensor_with_multiple_consumers.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -446,13 +478,15 @@ NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumer } NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumers_2) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({{InputEdge{3, 0}, InputEdge{3, 1}}}, {{OutputEdge{3, 0}, OutputEdge{4, 0}}}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__input_edge_from_tensor_with_multiple_consumers_2.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__input_edge_from_tensor_with_multiple_consumers_2.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -460,13 +494,15 @@ NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumer } NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumers_3) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({{InputEdge{3, 0}, InputEdge{6, 0}}}, {{OutputEdge{6, 0}, OutputEdge{5, 1}}}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__input_edge_from_tensor_with_multiple_consumers_3.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__input_edge_from_tensor_with_multiple_consumers_3.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -474,13 +510,15 @@ NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumer } NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumers_4) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({{InputEdge{1, 0}, InputEdge{3, 0}}}, {}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__input_edge_from_tensor_with_multiple_consumers_4.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__input_edge_from_tensor_with_multiple_consumers_4.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -488,14 +526,16 @@ NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumer } NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumers_5) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({InputEdge{3, 0}}, {{OutputEdge{6, 0}, OutputEdge{5, 1}}}); // expected to behave the same way as the test above - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__input_edge_from_tensor_with_multiple_consumers_5.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__input_edge_from_tensor_with_multiple_consumers_5.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -503,15 +543,16 @@ NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumer } NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumers_custom_names) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; editor.cut_graph_fragment({{InputEdge{1, 0, "new_name_1"}, InputEdge{6, 0, "new_name_2"}}}, {{OutputEdge{6, 0}, OutputEdge{4, 0}}}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__input_edge_from_tensor_with_multiple_consumers_custom_names.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__input_edge_from_tensor_with_multiple_consumers_custom_names.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -519,13 +560,14 @@ NGRAPH_TEST(onnx_editor, subgraph__input_edge_from_tensor_with_multiple_consumer } NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_input_relu2) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; editor.cut_graph_fragment({{InputEdge{4, 0}}}, {}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__multiple_consumers_of_graph_input_relu2.onnx"); + const auto ref_model = ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__multiple_consumers_of_graph_input_relu2.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -533,13 +575,14 @@ NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_input_relu2) { } NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_initializer) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; editor.cut_graph_fragment({{InputEdge{2, 0}}}, {}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__multiple_consumers_of_graph_initializer.onnx"); + const auto ref_model = ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__multiple_consumers_of_graph_initializer.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -547,14 +590,15 @@ NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_initializer) { } NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_initializer_2) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; editor.cut_graph_fragment({{InputEdge{2, 0}, InputEdge{3, 0}}}, {}); // same as above - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__multiple_consumers_of_graph_initializer.onnx"); + const auto ref_model = ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__multiple_consumers_of_graph_initializer.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -562,14 +606,15 @@ NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_initializer_2) { } NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_initializer_relu2_and_init) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; editor.cut_graph_fragment({{InputEdge{5, 0}, InputEdge{3, 0}}}, {}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__multiple_consumers_of_graph_initializer_relu2_and_init.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__multiple_consumers_of_graph_initializer_relu2_and_init.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -577,7 +622,8 @@ NGRAPH_TEST(onnx_editor, subgraph__multiple_consumers_of_graph_initializer_relu2 } NGRAPH_TEST(onnx_editor, subgraph__invalid_edge_idx) { - const auto model_path = file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); + const auto model_path = + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); ONNXModelEditor editor{model_path}; try { @@ -590,7 +636,8 @@ NGRAPH_TEST(onnx_editor, subgraph__invalid_edge_idx) { } NGRAPH_TEST(onnx_editor, subgraph__invalid_port_idx) { - const auto model_path = file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); + const auto model_path = + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); ONNXModelEditor editor{model_path}; try { @@ -602,7 +649,8 @@ NGRAPH_TEST(onnx_editor, subgraph__invalid_port_idx) { } NGRAPH_TEST(onnx_editor, subgraph__inputs_getter) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; EXPECT_EQ(editor.model_inputs(), (std::vector{"data_0", "conv1/7x7_s2_w_0", "conv1/7x7_s2_b_0"})); @@ -612,7 +660,8 @@ NGRAPH_TEST(onnx_editor, subgraph__inputs_getter) { } NGRAPH_TEST(onnx_editor, subgraph__custom_input_name_already_exist) { - const auto model_path = file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); + const auto model_path = + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx"); ONNXModelEditor editor{model_path}; try { @@ -627,7 +676,8 @@ NGRAPH_TEST(onnx_editor, subgraph__custom_input_name_already_exist) { // HIGHT LEVEL API TESTS // INPUT EDGES TEST NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_output_name_and_input_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; const InputEdge edge = editor.find_input_edge(EditorNode{EditorOutput{"conv1/7x7_s2_2"}}, EditorInput{"conv1/7x7_s2_1"}); @@ -640,7 +690,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_output_name_and_input_n } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_output_name_and_input_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; const InputEdge edge = editor.find_input_edge(EditorNode{EditorOutput{"conv1/7x7_s2_2"}}, EditorInput{0}); EXPECT_EQ(edge.m_node_idx, 1); @@ -656,7 +707,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_output_name_and_input_i } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; const InputEdge edge = editor.find_input_edge(EditorNode{"relu1"}, EditorInput{"conv1/7x7_s2_1"}); EXPECT_EQ(edge.m_node_idx, 1); @@ -668,7 +720,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_nam } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const InputEdge edge = editor.find_input_edge(EditorNode{"relu1_name"}, EditorInput{0}); EXPECT_EQ(edge.m_node_idx, 0); @@ -680,7 +733,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_ind } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_index_custom_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const InputEdge edge = editor.find_input_edge(EditorNode{"relu1_name"}, EditorInput{0, "custom_input_name_1"}); EXPECT_EQ(edge.m_node_idx, 0); @@ -694,7 +748,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_name_and_input_ind } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const InputEdge edge = editor.find_input_edge(EditorNode{0}, EditorInput{0, "custom_input_name_1"}); EXPECT_EQ(edge.m_node_idx, 0); @@ -714,7 +769,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_node_index) { } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_empty_node_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; try { editor.find_input_edge(EditorNode{""}, EditorInput{"conv1/7x7_s2_1"}); @@ -727,7 +783,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_empty_node_name) { // OUTPUT EDGES TEST NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_output_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const OutputEdge edge = editor.find_output_edge(EditorNode{EditorOutput{"mul2"}}, EditorOutput{"mul2"}); EXPECT_EQ(edge.m_node_idx, 4); @@ -748,7 +805,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_output_name) { } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_output_name_and_output_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const OutputEdge edge = editor.find_output_edge(EditorNode{EditorOutput{"add2"}}, EditorOutput{0}); EXPECT_EQ(edge.m_node_idx, 3); @@ -764,7 +822,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_output_name_and_output } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_name_and_output_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const OutputEdge edge = editor.find_output_edge(EditorNode{"relu1_name"}, EditorOutput{"relu1"}); EXPECT_EQ(edge.m_node_idx, 0); @@ -776,7 +835,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_name_and_output_n } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_name_and_output_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const OutputEdge edge = editor.find_output_edge(EditorNode{"relu1_name"}, EditorOutput{0}); EXPECT_EQ(edge.m_node_idx, 0); @@ -788,7 +848,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_name_and_output_i } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const OutputEdge edge = editor.find_output_edge(EditorNode{5}, EditorOutput{1}); EXPECT_EQ(edge.m_node_idx, 5); @@ -803,7 +864,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_node_index) { } NGRAPH_TEST(onnx_editor, editor_api_select_edge_const_network) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; const InputEdge edge = editor.find_input_edge(EditorNode{EditorOutput{"relu4"}}, EditorInput{0}); EXPECT_EQ(edge.m_node_idx, 3); @@ -819,7 +881,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_edge_const_network) { } NGRAPH_TEST(onnx_editor, editor_api_select_edge_error_handling) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; // node with given output name not found try { @@ -874,7 +937,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_edge_error_handling) { // Nodes with ambiguous node names tests NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_but_matched_input) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; InputEdge edge = editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{"in2"}); EXPECT_EQ(edge.m_node_idx, 1); @@ -886,7 +950,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_but } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_and_not_matched_input) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; try { editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{"in3"}); @@ -908,7 +973,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_and } NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_and_input_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; try { editor.find_input_edge(EditorNode{"add_ambiguous_name"}, EditorInput{0}); @@ -921,7 +987,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_input_edge_by_ambiguous_node_name_and } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_but_matched_output) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const OutputEdge edge = editor.find_output_edge(EditorNode{"add_ambiguous_name"}, EditorOutput{"add1"}); EXPECT_EQ(edge.m_node_idx, 1); @@ -933,7 +1000,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_bu } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_the_same_node_name_and_output_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests_2.onnx")}; const OutputEdge edge = editor.find_output_edge(EditorNode{"add1"}, EditorOutput{0}); EXPECT_EQ(edge.m_node_idx, 0); @@ -945,7 +1013,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_the_same_node_name_and } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_and_not_matched_output) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; try { editor.find_output_edge(EditorNode{"add_ambiguous_name"}, EditorOutput{"split2"}); @@ -957,7 +1026,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_an } NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_and_output_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; try { editor.find_output_edge(EditorNode{"add_ambiguous_name"}, EditorOutput{0}); @@ -971,7 +1041,8 @@ NGRAPH_TEST(onnx_editor, editor_api_select_output_edge_by_ambiguous_node_name_an } NGRAPH_TEST(onnx_editor, editor_api_use_edge_mapper_with_graph_cutter) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; // InputEdge{1, "in2"} const auto input_edge_1 = editor.find_input_edge(EditorNode(EditorOutput("add1")), EditorInput(1)); @@ -982,9 +1053,9 @@ NGRAPH_TEST(onnx_editor, editor_api_use_edge_mapper_with_graph_cutter) { // OutputEdge{4, "mul2"} editor.cut_graph_fragment({input_edge_1, input_edge_2}, {output_edge}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__existing_inputs_and_outputs_based_extraction.onnx"); + const auto ref_model = ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__existing_inputs_and_outputs_based_extraction.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -1005,7 +1076,8 @@ NGRAPH_TEST(onnx_editor, editor_api_use_edge_mapper_with_graph_cutter) { } NGRAPH_TEST(onnx_editor, editor_api_use_edge_mapper_with_graph_cutter_custom_names) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const auto input_edge_1 = editor.find_input_edge(EditorNode{EditorOutput{"mul2"}}, EditorInput{1, "new_name_1"}); const auto input_edge_2 = @@ -1013,9 +1085,10 @@ NGRAPH_TEST(onnx_editor, editor_api_use_edge_mapper_with_graph_cutter_custom_nam editor.cut_graph_fragment({input_edge_1, input_edge_2}, {}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__use_edge_mapper_with_graph_cutter_custom_names.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__use_edge_mapper_with_graph_cutter_custom_names.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -1023,7 +1096,8 @@ NGRAPH_TEST(onnx_editor, editor_api_use_edge_mapper_with_graph_cutter_custom_nam } NGRAPH_TEST(onnx_editor, editor_api_find_output_consumers) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; std::vector output_consumers = editor.find_output_consumers("relu1"); EXPECT_EQ(output_consumers.size(), 3); @@ -1048,14 +1122,15 @@ NGRAPH_TEST(onnx_editor, editor_api_find_output_consumers) { } NGRAPH_TEST(onnx_editor, editor_api_find_output_consumers_empty_result) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const std::vector output_consumers = editor.find_output_consumers("not_existed"); EXPECT_EQ(output_consumers.size(), 0); } NGRAPH_TEST(onnx_editor, editor_api_inputs_with_the_same_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; std::vector output_consumers = editor.find_output_consumers("X"); EXPECT_EQ(output_consumers[0].m_node_idx, 1); @@ -1065,7 +1140,8 @@ NGRAPH_TEST(onnx_editor, editor_api_inputs_with_the_same_name) { } NGRAPH_TEST(onnx_editor, editor_api_is_correct_and_unambiguous_node) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; bool is_correct_node = editor.is_correct_and_unambiguous_node(EditorNode{EditorOutput{"relu1"}}); EXPECT_EQ(is_correct_node, true); @@ -1096,7 +1172,8 @@ NGRAPH_TEST(onnx_editor, editor_api_is_correct_and_unambiguous_node) { } NGRAPH_TEST(onnx_editor, editor_api_get_node_index) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_EQ(editor.get_node_index(EditorNode{2}), 2); EXPECT_EQ(editor.get_node_index(EditorNode{EditorOutput{"relu1"}}), 0); @@ -1122,14 +1199,15 @@ NGRAPH_TEST(onnx_editor, editor_api_get_node_index) { } NGRAPH_TEST(onnx_editor, editor_api_input_edge_from_tensor_with_single_consumer) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; const auto edge = editor.find_input_edge(EditorNode{EditorOutput{"Y"}}, EditorInput{1}); editor.cut_graph_fragment({edge}, {}); - const auto ref_model = file_util::path_join(SERIALIZED_ZOO, - "onnx/model_editor/reference/" - "subgraph__twice_input_edge_from_tensor_with_single_consumer.onnx"); + const auto ref_model = + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/" + "subgraph__twice_input_edge_from_tensor_with_single_consumer.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -1137,7 +1215,7 @@ NGRAPH_TEST(onnx_editor, editor_api_input_edge_from_tensor_with_single_consumer) } NGRAPH_TEST(onnx_editor, editor_api_input_edge_from_tensor_with_single_consumer_ambiguous) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_ab.onnx")}; try { editor.find_input_edge(EditorNode{EditorOutput{"Y"}}, EditorInput{"X"}); @@ -1147,116 +1225,117 @@ NGRAPH_TEST(onnx_editor, editor_api_input_edge_from_tensor_with_single_consumer_ } } -using TestEngine = test::INTERPRETER_Engine; +using TestEngine = ngraph::test::INTERPRETER_Engine; NGRAPH_TEST(onnx_editor, values__append_one_initializer) { - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D.onnx")}; + onnx_editor::ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D.onnx")}; std::map> in_vals; - in_vals.emplace("A", op::Constant::create(element::i64, Shape{2}, {1, 2})); + in_vals.emplace("A", ngraph::op::Constant::create(element::i64, Shape{2}, {1, 2})); editor.set_input_values(in_vals); const auto function = editor.get_function(); - auto test_case = test::TestCase(function); + auto test_case = ngraph::test::TestCase(function); test_case.add_input(Shape{2}, {5, 6}); test_case.add_expected_output(Shape{2}, {6, 8}); test_case.run(); } NGRAPH_TEST(onnx_editor, values__append_two_initializers_to_invalid) { - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_invalid.onnx")}; + onnx_editor::ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_invalid.onnx")}; std::map> in_vals; - in_vals.emplace("A", op::Constant::create(element::i64, Shape{2}, {4, 2})); - in_vals.emplace("B", op::Constant::create(element::i64, Shape{2}, {1, 3})); + in_vals.emplace("A", ngraph::op::Constant::create(element::i64, Shape{2}, {4, 2})); + in_vals.emplace("B", ngraph::op::Constant::create(element::i64, Shape{2}, {1, 3})); editor.set_input_values(in_vals); const auto function = editor.get_function(); - auto test_case = test::TestCase(function); + auto test_case = ngraph::test::TestCase(function); test_case.add_expected_output(Shape{2}, {5, 5}); test_case.run(); } NGRAPH_TEST(onnx_editor, values__modify_one_initializer) { onnx_editor::ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_with_initializers.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_with_initializers.onnx")}; std::map> in_vals; - in_vals.emplace("B", op::Constant::create(element::i64, Shape{2}, {3, 4})); + in_vals.emplace("B", ngraph::op::Constant::create(element::i64, Shape{2}, {3, 4})); editor.set_input_values(in_vals); const auto function = editor.get_function(); - auto test_case = test::TestCase(function); + auto test_case = ngraph::test::TestCase(function); test_case.add_expected_output(Shape{2}, {4, 6}); test_case.run(); } NGRAPH_TEST(onnx_editor, values__modify_two_initializers) { onnx_editor::ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_with_initializers.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_with_initializers.onnx")}; std::map> in_vals; - in_vals.emplace("A", op::Constant::create(element::i64, Shape{2}, {3, 6})); - in_vals.emplace("B", op::Constant::create(element::i64, Shape{2}, {2, 1})); + in_vals.emplace("A", ngraph::op::Constant::create(element::i64, Shape{2}, {3, 6})); + in_vals.emplace("B", ngraph::op::Constant::create(element::i64, Shape{2}, {2, 1})); editor.set_input_values(in_vals); const auto function = editor.get_function(); - auto test_case = test::TestCase(function); + auto test_case = ngraph::test::TestCase(function); test_case.add_expected_output(Shape{2}, {5, 7}); test_case.run(); } NGRAPH_TEST(onnx_editor, values__no_inputs_modify_two_initializers) { onnx_editor::ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_with_initializers_only.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D_with_initializers_only.onnx")}; std::map> in_vals; - in_vals.emplace("A", op::Constant::create(element::i64, Shape{2}, {1, 2})); - in_vals.emplace("B", op::Constant::create(element::i64, Shape{2}, {11, 22})); + in_vals.emplace("A", ngraph::op::Constant::create(element::i64, Shape{2}, {1, 2})); + in_vals.emplace("B", ngraph::op::Constant::create(element::i64, Shape{2}, {11, 22})); editor.set_input_values(in_vals); const auto function = editor.get_function(); - auto test_case = test::TestCase(function); + auto test_case = ngraph::test::TestCase(function); test_case.add_expected_output(Shape{2}, {12, 24}); test_case.run(); } NGRAPH_TEST(onnx_editor, values__append_two_initializers_change_shape_type) { - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D.onnx")}; + onnx_editor::ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/add_1D.onnx")}; std::map> in_vals; - in_vals.emplace("A", op::Constant::create(element::i8, Shape{2, 1}, {-1, 1})); - in_vals.emplace("B", op::Constant::create(element::i8, Shape{2, 1}, {-2, 2})); + in_vals.emplace("A", ngraph::op::Constant::create(element::i8, Shape{2, 1}, {-1, 1})); + in_vals.emplace("B", ngraph::op::Constant::create(element::i8, Shape{2, 1}, {-2, 2})); editor.set_input_values(in_vals); const auto function = editor.get_function(); - auto test_case = test::TestCase(function); + auto test_case = ngraph::test::TestCase(function); test_case.add_expected_output(Shape{2, 1}, {-3, 3}); test_case.run(); } NGRAPH_TEST(onnx_editor, values__append_two_initializers_mixed_types) { onnx_editor::ONNXModelEditor editor{ - file_util::path_join(SERIALIZED_ZOO, "onnx/gather_elements_float_3D_axis_2.onnx")}; + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/gather_elements_float_3D_axis_2.onnx")}; std::map> in_vals; - in_vals.emplace("data", op::Constant::create(element::i16, Shape{2, 2, 2}, {1, 2, 3, 4, 5, 6, 7, 8})); - in_vals.emplace("indices", op::Constant::create(element::i32, Shape{2, 2, 1}, {0, 1, 0, 1})); + in_vals.emplace("data", ngraph::op::Constant::create(element::i16, Shape{2, 2, 2}, {1, 2, 3, 4, 5, 6, 7, 8})); + in_vals.emplace("indices", ngraph::op::Constant::create(element::i32, Shape{2, 2, 1}, {0, 1, 0, 1})); editor.set_input_values(in_vals); const auto function = editor.get_function(); - auto test_case = test::TestCase(function); + auto test_case = ngraph::test::TestCase(function); test_case.add_expected_output(Shape{2, 2, 1}, {1, 4, 5, 8}); test_case.run(); } NGRAPH_TEST(onnx_editor, read_model_from_stream) { - std::string path = file_util::path_join(SERIALIZED_ZOO, "onnx/external_data/external_data.onnx"); + std::string path = ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/external_data/external_data.onnx"); std::ifstream stream{path, std::ios::in | std::ios::binary}; ASSERT_TRUE(stream.is_open()); ONNXModelEditor editor{stream, path}; - auto test_case = test::TestCase(editor.get_function()); + auto test_case = ngraph::test::TestCase(editor.get_function()); test_case.add_input({1.f, 2.f, 3.f, 4.f}); test_case.add_expected_output(Shape{2, 2}, {3.f, 6.f, 9.f, 12.f}); @@ -1266,14 +1345,16 @@ NGRAPH_TEST(onnx_editor, read_model_from_stream) { } NGRAPH_TEST(onnx_editor, combined__cut_and_replace_shape) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph__inception_head.onnx")}; const auto new_shape = PartialShape({1, 64, 112, 112}); editor.cut_graph_fragment({{InputEdge(1, 0)}}, {}); editor.set_input_shapes({{"conv1/7x7_s2_1", new_shape}}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/subgraph__linear_model_head_cut.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, + "onnx/model_editor/reference/subgraph__linear_model_head_cut.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -1284,12 +1365,13 @@ NGRAPH_TEST(onnx_editor, combined__cut_and_replace_shape) { } NGRAPH_TEST(onnx_editor, cut_operator_with_no_schema) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/unknown_input_value_info.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/unknown_input_value_info.onnx")}; editor.cut_graph_fragment({{InputEdge{1, 0}}}, {}); const auto ref_model = - file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/unknown_input_value_info.onnx"); + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/reference/unknown_input_value_info.onnx"); const auto result = compare_onnx_models(editor.model_string(), ref_model); @@ -1297,7 +1379,8 @@ NGRAPH_TEST(onnx_editor, cut_operator_with_no_schema) { } NGRAPH_TEST(onnx_editor, get_source_tensor_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_EQ(editor.get_source_tensor_name(InputEdge{0, 0}), "in1"); EXPECT_EQ(editor.get_source_tensor_name(InputEdge{1, 0}), "relu1"); @@ -1310,7 +1393,8 @@ NGRAPH_TEST(onnx_editor, get_source_tensor_name) { } NGRAPH_TEST(onnx_editor, is_model_input) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_TRUE(editor.is_input(InputEdge{0, 0})); const auto edge1 = editor.find_input_edge(EditorOutput{"add1"}, 1); @@ -1327,7 +1411,8 @@ NGRAPH_TEST(onnx_editor, is_model_input) { } NGRAPH_TEST(onnx_editor, get_target_tensor_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_EQ(editor.get_target_tensor_name(OutputEdge{0, 0}), "relu1"); EXPECT_EQ(editor.get_target_tensor_name(OutputEdge{1, 0}), "add1"); @@ -1338,7 +1423,8 @@ NGRAPH_TEST(onnx_editor, get_target_tensor_name) { } NGRAPH_TEST(onnx_editor, is_model_output) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_TRUE(editor.is_output(OutputEdge{4, 0})); EXPECT_TRUE(editor.is_output(OutputEdge{5, 1})); @@ -1353,28 +1439,31 @@ NGRAPH_TEST(onnx_editor, is_model_output) { } NGRAPH_TEST(onnx_editor, model_inputs) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const auto inputs = editor.model_inputs(); EXPECT_TRUE(inputs == (std::vector{"in1", "in2", "in3"})); // in4 is initializer } NGRAPH_TEST(onnx_editor, model_inputs_with_non_input_initializers) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/instance_norm_dynamic.onnx")}; + ONNXModelEditor editor{ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/instance_norm_dynamic.onnx")}; const auto inputs = editor.model_inputs(); EXPECT_TRUE(inputs == (std::vector{"input"})); } NGRAPH_TEST(onnx_editor, model_output) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const auto outputs = editor.model_outputs(); EXPECT_TRUE(outputs == (std::vector{"mul1", "split2", "mul2"})); } NGRAPH_TEST(onnx_editor, get_tensor_shape) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_EQ(editor.get_tensor_shape("mul2"), (PartialShape{1, 1, 2, 2})); EXPECT_EQ(editor.get_tensor_shape("in1"), (PartialShape{2, 2})); @@ -1391,7 +1480,8 @@ NGRAPH_TEST(onnx_editor, get_tensor_shape) { } NGRAPH_TEST(onnx_editor, get_tensor_shape_after_modification) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_EQ(editor.get_tensor_shape("in3"), (PartialShape{1, 1, 2, 2})); EXPECT_EQ(editor.get_tensor_shape("conv1"), (PartialShape{1, 1, 2, 2})); @@ -1402,7 +1492,8 @@ NGRAPH_TEST(onnx_editor, get_tensor_shape_after_modification) { } NGRAPH_TEST(onnx_editor, is_correct_tensor_name) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; EXPECT_TRUE(editor.is_correct_tensor_name("in1")); EXPECT_TRUE(editor.is_correct_tensor_name("relu1")); @@ -1416,7 +1507,8 @@ NGRAPH_TEST(onnx_editor, is_correct_tensor_name) { } NGRAPH_TEST(onnx_editor, get_input_ports) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const auto ports_1 = editor.get_input_ports(EditorNode{"relu1_name"}); EXPECT_EQ(ports_1.size(), 1); @@ -1447,7 +1539,8 @@ NGRAPH_TEST(onnx_editor, get_input_ports) { } } NGRAPH_TEST(onnx_editor, get_output_ports) { - ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; + ONNXModelEditor editor{ + ngraph::file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")}; const auto ports_1 = editor.get_output_ports(EditorNode{"relu1_name"}); EXPECT_EQ(ports_1.size(), 1); diff --git a/ngraph/test/onnx/onnx_import.in.cpp b/ngraph/test/onnx/onnx_import.in.cpp index af4a7f883d6412..8775d91e54df55 100644 --- a/ngraph/test/onnx/onnx_import.in.cpp +++ b/ngraph/test/onnx/onnx_import.in.cpp @@ -22,14 +22,16 @@ #endif // clang-format on -#include "onnx_import/core/null_node.hpp" -#include "gtest/gtest.h" -#include "onnx_import/onnx.hpp" -#include "onnx_import/onnx_utils.hpp" +#include + #include "default_opset.hpp" +#include "gtest/gtest.h" #include "ngraph/ngraph.hpp" -#include "ngraph/pass/manager.hpp" #include "ngraph/pass/constant_folding.hpp" +#include "ngraph/pass/manager.hpp" +#include "onnx_import/core/null_node.hpp" +#include "onnx_import/onnx.hpp" +#include "onnx_import/onnx_utils.hpp" #include "util/all_close.hpp" #include "util/all_close_f.hpp" #include "util/ndarray.hpp" @@ -38,7 +40,6 @@ #include "engines_util/test_engines.hpp" #include "util/test_tools.hpp" #include "util/type_prop.hpp" -#include NGRAPH_SUPPRESS_DEPRECATED_START @@ -3674,6 +3675,155 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_inbounds) { test_case.run(); } +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_no_min_no_max) { + auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/clip_no_min_no_max.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{-1.6, -0.1, 10., 0., -10., 1.99, 2.015, 3.}; + + test_case.add_input(data); + + test_case.add_expected_output(Shape{2, 4}, data); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_no_min_no_max_inf) { + auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/clip_no_min_no_max.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{std::numeric_limits::infinity(), + -std::numeric_limits::infinity(), + static_cast(std::numeric_limits::max()), + std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::lowest(), + 0, + -1}; + + const std::vector expected_output{std::numeric_limits::max(), + std::numeric_limits::lowest(), + std::numeric_limits::max(), + std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::lowest(), + 0, + -1}; + + test_case.add_input(data); + + test_case.add_expected_output(Shape{2, 4}, expected_output); + test_case.run_with_tolerance_as_fp(0); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_no_min_set_max) { + auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/clip_no_min_set_max.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{-1.6, -0.1, 10., 0., -10., 1.99, 2.015, 3.}; + const std::vector max_val{2.01}; + const std::vector output{-1.6, -0.1, 2.01, 0., -10., 1.99, 2.01, 2.01}; + + test_case.add_input(data); + test_case.add_input(max_val); + + test_case.add_expected_output(Shape{2, 4}, output); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_set_min_no_max) { + auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/clip_set_min_no_max.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{-1.6, -0.1, 10., 0., -10., 1.99, 2.015, 3.}; + const std::vector min_val{-1.59}; + const std::vector output{-1.59, -0.1, 10., 0., -1.59, 1.99, 2.015, 3.}; + + test_case.add_input(data); + test_case.add_input(min_val); + + test_case.add_expected_output(Shape{2, 4}, output); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_no_min_no_max_int64) { + auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/clip_no_min_no_max_int64.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{INT64_MAX, INT64_MIN, INT32_MAX, INT32_MIN, 0, -1, 1, 0}; + + test_case.add_input(data); + + test_case.add_expected_output(Shape{2, 4}, data); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_no_min_set_max_int64) { + auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/clip_no_min_set_max_int64.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{INT64_MAX, INT64_MIN, INT32_MAX, INT32_MIN, 0, -1, 1, 0}; + const std::vector max_val{INT32_MAX}; + const std::vector output{INT32_MAX, INT64_MIN, INT32_MAX, INT32_MIN, 0, -1, 1, 0}; + + test_case.add_input(data); + test_case.add_input(max_val); + + test_case.add_expected_output(Shape{2, 4}, output); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_set_min_no_max_initializers) { + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/clip_set_min_no_max_initializers.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{-1.6, -0.1, 10., 0., -10., 1.99, 2.015, 3.}; + const std::vector output{-1.59, -0.1, 10., 0., -1.59, 1.99, 2.015, 3.}; + + test_case.add_input(data); + + test_case.add_expected_output(Shape{2, 4}, output); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_set_min_set_max) { + auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/clip_set_min_set_max.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{-1.6, -0.1, 10., 0., -10., 1.99, 2.015, 3.}; + const std::vector min_val{-1.59}; + const std::vector max_val{2.01}; + const std::vector output{-1.59, -0.1, 2.01, 0., -1.59, 1.99, 2.01, 2.01}; + + test_case.add_input(data); + test_case.add_input(min_val); + test_case.add_input(max_val); + + test_case.add_expected_output(Shape{2, 4}, output); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_clip_set_min_set_max_initializers) { + auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/clip_set_min_set_max_initializers.onnx")); + + auto test_case = test::TestCase(function); + const std::vector data{-1.6, -0.1, 10., 0., -10., 1.99, 2.015, 3.}; + const std::vector output{-1.59, -0.1, 2.01, 0., -1.59, 1.99, 2.01, 2.01}; + + test_case.add_input(data); + + test_case.add_expected_output(Shape{2, 4}, output); + test_case.run(); +} + NGRAPH_TEST(${BACKEND_NAME}, onnx_mvn_v6) { auto function = onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/mvn_v6.onnx")); @@ -4165,14 +4315,79 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_float16_tensor_as_int32) { test_case.run(); } +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_max_pool_3d) { + const auto function = onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/max_pool_3d.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_input(Shape{1, 3, 3}, {-1, 0, 1, 20, -20, 10, 0, 2, 1}); + test_case.add_expected_output(Shape{1, 3, 2}, {0, 1, 20, 10, 2, 2}); + test_case.add_expected_output(Shape{1, 3, 2}, {1, 2, 3, 5, 7, 7}); + + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_max_pool_4d_ceil_mode) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/max_pool_4d_ceil_mode.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_input(Shape{1, 1, 4, 4}, gen_range(16, 1)); + test_case.add_expected_output(Shape{1, 1, 2, 2}, {11, 12, 15, 16}); + test_case.add_expected_output(Shape{1, 1, 2, 2}, {10, 11, 14, 15}); + + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_max_pool_4d_dilations) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/max_pool_4d_dilations.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_input(Shape{1, 1, 4, 4}, {9, 10, 11, 12, 1, 2, 3, 4, 16, 14, 15, 13, 5, 6, 8, 7}); + test_case.add_expected_output(Shape{1, 1, 2, 2}, {16, 14, 8, 7}); + test_case.add_expected_output(Shape{1, 1, 2, 2}, {8, 9, 14, 15}); + + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_max_pool_4d_strides) { + // kernel: 3x3 + // strides: 3, 3 + // explicit pads: 2, 2, 2, 2 + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/max_pool_4d_strides.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_input(Shape{1, 1, 5, 5}, gen_range(25, 1)); + test_case.add_expected_output(Shape{1, 1, 3, 3}, {1, 4, 5, 16, 19, 20, 21, 24, 25}); + test_case.add_expected_output(Shape{1, 1, 3, 3}, {0, 3, 4, 15, 18, 19, 20, 23, 24}); + + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_max_pool_4d_ceil_strides) { + // kernel: 3x3 + // strides: 2, 2 + // ceil_mode: 1 + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/max_pool_4d_ceil_strides.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_input( + Shape{1, 1, 4, 4}, + {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f}); + test_case.add_expected_output(Shape{1, 1, 2, 2}, {11.0f, 12.0f, 15.0f, 16.0f}); + test_case.add_expected_output(Shape{1, 1, 2, 2}, {10, 11, 14, 15}); + + test_case.run(); +} + NGRAPH_TEST(${BACKEND_NAME}, onnx_model_random_uniform) { const auto function = onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/random_uniform.onnx")); auto test_case = test::TestCase(function); - // These output values are unknown at this time as we don't have a reference implementation of random number - // generator - test_case.add_expected_output(Shape{2, 2}, {41, 42, 43, 44}); + test_case.add_expected_output(Shape{2, 2}, {43.45518, 48.67585, 42.227386, 40.86294}); test_case.run(); } @@ -4181,10 +4396,26 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_random_uniform_like) { onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/random_uniform_like.onnx")); auto test_case = test::TestCase(function); - test_case.add_expected_output(Shape{2, 2}, {0, 0, 0, 0}); + test_case.add_input(Shape{2, 2}, {41, 42, 43, 44}); + test_case.add_expected_output(Shape{2, 2}, {43.45518, 48.67585, 42.227386, 40.86294}); + test_case.run(); +} - // These output values are unknown at this time as we don't have a reference implementation of random number - // generator - test_case.add_input(Shape{2, 2}, {41, 42, 43, 44}); +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_random_normal) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/random_normal.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_expected_output(Shape{2, 2}, {13.459274, 41.75028, -19.311913, 131.79282}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_random_normal_like) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/random_normal_like.onnx")); + + auto test_case = test::TestCase(function); + test_case.add_input(Shape{2, 2}, {0, 0, 0, 0}); + test_case.add_expected_output(Shape{2, 2}, {13.459274, 41.75028, -19.311913, 131.79282}); test_case.run(); } diff --git a/ngraph/test/onnx/onnx_import_com_microsoft.in.cpp b/ngraph/test/onnx/onnx_import_com_microsoft.in.cpp index 63611843a27dfd..5fb5999cf6c244 100644 --- a/ngraph/test/onnx/onnx_import_com_microsoft.in.cpp +++ b/ngraph/test/onnx/onnx_import_com_microsoft.in.cpp @@ -25,13 +25,11 @@ using namespace ngraph; static std::string s_manifest = "${MANIFEST}"; -using Inputs = std::vector>; -using Outputs = std::vector>; - using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); NGRAPH_TEST(${BACKEND_NAME}, onnx_model_bias_gelu) { - const auto function = onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/bias_gelu.onnx")); + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/bias_gelu.onnx")); auto test_case = test::TestCase(function); test_case.add_input({0.5488135, @@ -52,7 +50,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_bias_gelu) { NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_with_gamma_beta_bias) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/skip_layer_normalization_with_gamma_beta_bias.onnx")); + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/skip_layer_normalization_with_gamma_beta_bias.onnx")); std::vector input = { 0.54881352, 0.71518934, 0.60276335, 0.54488319, 0.42365479, 0.64589411, 0.43758720, 0.89177299, @@ -78,7 +76,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_with_gamma_beta NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_with_gamma_beta) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/skip_layer_normalization_with_gamma_beta.onnx")); + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/skip_layer_normalization_with_gamma_beta.onnx")); std::vector input = { 0.54881352, 0.71518934, 0.60276335, 0.54488319, 0.42365479, 0.64589411, 0.43758720, 0.89177299, @@ -104,7 +102,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_with_gamma_beta NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_with_gamma) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/skip_layer_normalization_with_gamma.onnx")); + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/skip_layer_normalization_with_gamma.onnx")); std::vector input = { 0.54881352, 0.71518934, 0.60276335, 0.54488319, 0.42365479, 0.64589411, 0.43758720, 0.89177299, @@ -130,7 +128,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_with_gamma) { NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_dynamic_shapes) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/dynamic_shapes/skip_layer_normalization.onnx")); + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/skip_layer_normalization_dynamic_shapes.onnx")); std::vector input = { 0.54881352, 0.71518934, 0.60276335, 0.54488319, 0.42365479, 0.64589411, 0.43758720, 0.89177299, @@ -177,8 +175,8 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_skip_layer_normalization_dynamic_shapes) } NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization) { - const auto function = - onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/embed_layer_normalization.onnx")); + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/embed_layer_normalization.onnx")); std::vector input_ids = { 8, 1, 5, 9, 8, 9, 4, 3, 0, 3, 5, 0, 2, 3, 8, 1, 3, 3, 3, 7, 0, 1, 9, 9, @@ -209,7 +207,8 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization) { NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization_with_segment_embedding) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/embed_layer_normalization_with_segment_embedding.onnx")); + file_util::path_join(SERIALIZED_ZOO, + "onnx/com.microsoft/embed_layer_normalization_with_segment_embedding.onnx")); std::vector input_ids = { 8, 1, 5, 9, 8, 9, 4, 3, 0, 3, 5, 0, 2, 3, 8, 1, 3, 3, 3, 7, 0, 1, 9, 9, @@ -251,7 +250,8 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization_with_segment_e NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization_with_segment_embedding_and_mask) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/embed_layer_normalization_with_segment_embedding_and_mask.onnx")); + file_util::path_join(SERIALIZED_ZOO, + "onnx/com.microsoft/embed_layer_normalization_with_segment_embedding_and_mask.onnx")); std::vector input_ids = { 8, 1, 5, 9, 8, 9, 4, 3, 0, 3, 5, 0, 2, 3, 8, 1, 3, 3, 3, 7, 0, 1, 9, 9, @@ -296,7 +296,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization_with_segment_e NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization_dynamic_shapes) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/dynamic_shapes/embed_layer_normalization_dynamic_shapes.onnx")); + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/embed_layer_normalization_dynamic_shapes.onnx")); std::vector input_ids = { 8, 1, 5, 9, 8, 9, 4, 3, 0, 3, 5, 0, 2, 3, 8, 1, 3, 3, 3, 7, 0, 1, 9, 9, @@ -389,3 +389,470 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_embed_layer_normalization_dynamic_shapes test_case.add_expected_output(Shape{3}, expected_mask_index); test_case.run_with_tolerance_as_fp(1e-6); } + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.91475844, 0.91523546, 0.82536930, 0.37491974, 0.22384071, 0.05941105, 0.01902100, 0.70131350, + 0.09603709, 0.44200060, 0.53106076, 0.79464376, 0.35469049, 0.25225943, 0.25179818, 0.29592562, + 0.24836586, 0.65088797, 0.93126643, 0.67980725, 0.85708112, 0.59808528, 0.46321425, 0.19301885, + }; + std::vector output = { + 0.07966283, 0.10783536, -0.19424979, 0.54514766, 0.07965867, 0.10783093, -0.19424866, 0.54510003, + 0.07965846, 0.10783067, -0.19424550, 0.54509139, 0.07966217, 0.10783640, -0.19424903, 0.54512268, + 0.06940663, 0.10962760, -0.19698445, 0.53492010, 0.06940675, 0.10962828, -0.19698484, 0.53492326, + 0.06940714, 0.10963022, -0.19698712, 0.53494006, 0.06940673, 0.10962812, -0.19698519, 0.53492481, + }; + + test_case.add_input(input); + test_case.add_expected_output(output); + test_case.run_with_tolerance_as_fp(1e-7); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_qkv_hidden_sizes) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_qkv_hidden_sizes.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.56477863, 0.60309958, 0.35158035, 0.03123519, 0.81918180, 0.76905495, 0.47219241, 0.72016627, + 0.59377003, 0.91380632, 0.56797302, 0.34846428, 0.83839595, 0.16394103, 0.34676281, 0.09161621, + 0.45562279, 0.23317528, 0.37197968, 0.06727808, 0.08500192, 0.84915495, 0.68266946, 0.00227691, + }; + std::vector output = { + -0.59370947, -0.30300471, 0.12048547, -0.09029539, 0.08041390, 0.10250041, -0.19381392, 0.55126983, + -0.59370828, -0.30301332, 0.12049319, -0.09029691, 0.08041921, 0.10250521, -0.19381438, 0.55127531, + -0.59370869, -0.30301058, 0.12049074, -0.09029643, 0.08041564, 0.10250199, -0.19381410, 0.55127168, + -0.59370929, -0.30300608, 0.12048667, -0.09029562, 0.08041184, 0.10249855, -0.19381374, 0.55126774, + -0.59681994, -0.26327702, 0.07638434, -0.06311120, 0.06671587, 0.10916986, -0.19412412, 0.51977092, + -0.59682053, -0.26328400, 0.07638102, -0.06311222, 0.06671817, 0.10917170, -0.19412397, 0.51977223, + -0.59682077, -0.26328647, 0.07637984, -0.06311259, 0.06671739, 0.10917108, -0.19412403, 0.51977175, + -0.59682101, -0.26328778, 0.07637922, -0.06311278, 0.06671065, 0.10916568, -0.19412443, 0.51976782, + }; + + test_case.add_input(input); + test_case.add_expected_output(output); + test_case.run_with_tolerance_as_fp(1e-6); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_unidirectional) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_unidirectional.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.89578921, 0.42421508, 0.35630688, 0.77461642, 0.65753633, 0.09723099, 0.62597734, 0.72117692, + 0.57636845, 0.17104276, 0.13245547, 0.59879875, 0.15624641, 0.44903454, 0.50483286, 0.92975074, + 0.36934483, 0.29919949, 0.57185954, 0.83036488, 0.08384345, 0.20378476, 0.74684393, 0.46716982, + }; + std::vector output = { + 0.05604819, 0.09000472, -0.19437021, 0.52487367, 0.06211422, 0.08740954, -0.19139624, 0.52762908, + 0.06708897, 0.08992603, -0.19214047, 0.53631783, 0.06896879, 0.10248676, -0.19485690, 0.53477794, + 0.08577005, 0.12807365, -0.19762954, 0.54432857, 0.06929274, 0.10893210, -0.19599904, 0.53184807, + 0.07348281, 0.10215081, -0.19280069, 0.53552240, 0.07861833, 0.10517240, -0.19285706, 0.54126489, + }; + std::vector present = { + -0.60427380, -0.25958878, -0.59609234, -0.24055196, -0.59613681, -0.30088067, -0.59633607, -0.33270463, + 0.06899665, -0.09284544, 0.08059876, -0.06146053, 0.11841078, -0.10019838, 0.10605468, -0.09273906, + -0.59036821, -0.32410735, -0.60532302, -0.25127757, -0.58926487, -0.25271094, -0.58640373, -0.31730092, + 0.12509561, -0.07968873, 0.06005794, -0.08937149, 0.10523240, -0.05083811, 0.14162725, -0.07438751, + 0.05604819, 0.09000472, 0.06819826, 0.08480665, 0.07700446, 0.09494394, 0.07459175, 0.14003153, + -0.19437021, 0.52487367, -0.18843602, 0.53037173, -0.19362189, 0.55360907, -0.20299932, 0.53020388, + 0.08577005, 0.12807365, 0.05276009, 0.08972625, 0.08190014, 0.08852972, 0.09400313, 0.11423884, + -0.19762954, 0.54432857, -0.19435294, 0.51924801, -0.18643703, 0.54280555, -0.19302703, 0.55837619, + }; + + test_case.add_input(input); + test_case.add_expected_output(output); + test_case.add_expected_output(present); + test_case.run_with_tolerance_as_fp(1e-7); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_mask_index_1) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_mask_index_1.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.02841483, 0.47845092, 0.14633700, 0.54597300, 0.40160629, 0.55281311, 0.14931096, 0.64483738, + 0.96559167, 0.05262021, 0.12391864, 0.20093553, 0.74290562, 0.19367455, 0.19253619, 0.41593507, + 0.91188699, 0.61606920, 0.72673517, 0.86981291, 0.19963337, 0.22747350, 0.34308898, 0.57267183, + }; + std::vector mask_index = { + 0, + 1, + }; + std::vector output = { + 0.08298690, 0.12711772, -0.19757506, 0.54029012, 0.08298548, 0.12711433, -0.19757731, 0.54031140, + 0.08298430, 0.12711799, -0.19757695, 0.54031777, 0.08298548, 0.12711433, -0.19757444, 0.54028159, + 0.05380550, 0.10459180, -0.19593412, 0.50907606, 0.05380550, 0.10459180, -0.19593412, 0.50907606, + 0.05380550, 0.10459180, -0.19593412, 0.50907606, 0.05380550, 0.10459180, -0.19593412, 0.50907606, + }; + std::vector present = { + -0.58437425, -0.29483819, -0.59927911, -0.30336475, -0.59104657, -0.37327260, -0.59078789, -0.29863101, + 0.11751597, -0.04114649, 0.09933343, -0.09884726, 0.16250694, -0.12028439, 0.09319257, -0.05129660, + -0.60341775, -0.25221461, -0.58933026, -0.31912822, -0.59271193, -0.25470981, -0.59399152, -0.32643768, + 0.05398282, -0.07468132, 0.14743008, -0.09407346, 0.10399222, -0.06682440, 0.11632499, -0.08986320, + 0.09104910, 0.12973849, 0.06917210, 0.11059431, 0.09356256, 0.12594685, 0.07814129, 0.14221822, + -0.19329809, 0.53526556, -0.19787431, 0.53673857, -0.20045389, 0.57165766, -0.19869246, 0.51749766, + 0.05380550, 0.10459180, 0.09169570, 0.09892380, 0.07746917, 0.08042616, 0.07953370, 0.12909687, + -0.19593412, 0.50907606, -0.19202785, 0.56904894, -0.18689045, 0.54643762, -0.19969353, 0.53976399, + }; + + test_case.add_input(input); + test_case.add_input(mask_index); + test_case.add_expected_output(output); + test_case.add_expected_output(present); + test_case.run_with_tolerance_as_fp(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_mask_index_2) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_mask_index_2.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.75259578, 0.81492645, 0.46713001, 0.29483622, 0.06768602, 0.95105755, 0.32065326, 0.52417183, + 0.73136383, 0.77176476, 0.60997742, 0.64625764, 0.16311000, 0.89680773, 0.01331447, 0.42468646, + 0.58711547, 0.00345124, 0.13053808, 0.46278623, 0.13786320, 0.65182054, 0.74864876, 0.81506181, + }; + std::vector mask_index = { + 3, + 3, + 1, + 1, + }; + std::vector output = { + 0.07524174, 0.11320241, -0.19909523, 0.54785377, 0.06825337, 0.13981669, -0.20774621, 0.53718704, + 0.07531278, 0.12957911, -0.20330518, 0.54547405, 0.07531209, 0.12958010, -0.20330583, 0.54547292, + 0.08900890, 0.11150353, -0.18931937, 0.53757656, 0.07915881, 0.10416336, -0.18914750, 0.52921104, + 0.08285815, 0.11462159, -0.19115375, 0.53077918, 0.08285838, 0.11462225, -0.19115454, 0.53077984, + }; + std::vector present = { + -0.59630549, -0.28110915, -0.60274345, -0.36154836, -0.59437746, -0.33717164, -0.60134649, -0.29849592, + 0.11169122, -0.09345293, 0.11103803, -0.13096604, 0.13131849, -0.10597084, 0.10463209, -0.11332577, + -0.57949269, -0.27235535, -0.58941406, -0.25372508, -0.58658379, -0.28718373, -0.59821802, -0.32433146, + 0.13244939, -0.02865628, 0.09308393, -0.04083736, 0.10948701, -0.04423397, 0.13060363, -0.12316251, + 0.07509718, 0.08392500, 0.06825337, 0.13981669, 0.08239168, 0.11931328, 0.06770951, 0.09240761, + -0.19074154, 0.55260652, -0.20774621, 0.53718704, -0.19888818, 0.55371630, -0.19559640, 0.54754448, + 0.09983939, 0.10603377, 0.07915881, 0.10416336, 0.08655046, 0.12505992, 0.07738422, 0.09509270, + -0.18571433, 0.55095005, -0.18914750, 0.52921104, -0.19315663, 0.53234470, -0.19601485, 0.56322992, + }; + + test_case.add_input(input); + test_case.add_input(mask_index); + test_case.add_expected_output(output); + test_case.add_expected_output(present); + test_case.run_with_tolerance_as_fp(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_mask_index_3) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_mask_index_3.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.33093750, 0.39181390, 0.14586255, 0.39709702, 0.98086524, 0.03891133, 0.72234219, 0.21966648, + 0.79986620, 0.97251678, 0.04131543, 0.43971965, 0.50185394, 0.11452501, 0.88111717, 0.76076663, + 0.31870860, 0.54107893, 0.91756296, 0.58112669, 0.99117357, 0.00256292, 0.58885485, 0.93481058, + }; + std::vector mask = { + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + }; + std::vector output = { + 0.07551830, 0.10666487, -0.19357042, 0.53683108, 0.07551410, 0.10666656, -0.19356072, 0.53684169, + 0.07552745, 0.10666100, -0.19358172, 0.53682435, 0.07552218, 0.10666317, -0.19358677, 0.53681952, + 0.09727416, 0.13513327, -0.20121223, 0.57003713, 0.09727416, 0.13513327, -0.20121223, 0.57003713, + 0.09727416, 0.13513327, -0.20121223, 0.57003713, 0.09727416, 0.13513327, -0.20121223, 0.57003713, + }; + std::vector present = { + -0.59174627, -0.27471560, -0.58307797, -0.25967693, -0.60766846, -0.31754097, -0.61241394, -0.26291698, + 0.09206123, -0.05307099, 0.12491645, -0.03853742, 0.08732655, -0.13050151, 0.04073093, -0.10792807, + -0.60556883, -0.34055573, -0.60474855, -0.28785610, -0.60757709, -0.32514900, -0.58872569, -0.37967020, + 0.09779400, -0.13136166, 0.07915612, -0.10649752, 0.11043755, -0.15124020, 0.16626491, -0.11274654, + 0.07639833, 0.11762549, 0.09370039, 0.09133558, 0.05661478, 0.11096847, 0.04019671, 0.10117501, + -0.19371650, 0.52530587, -0.18429738, 0.55240726, -0.20283231, 0.53265429, -0.20036045, 0.50568837, + 0.06171235, 0.12687264, 0.05802051, 0.10266830, 0.06172965, 0.08967118, 0.09727416, 0.13513327, + -0.20576829, 0.53365225, -0.19832623, 0.52809310, -0.19971462, 0.55584043, -0.20121223, 0.57003713, + }; + + test_case.add_input(input); + test_case.add_input(mask); + test_case.add_expected_output(output); + test_case.add_expected_output(present); + test_case.run_with_tolerance_as_fp(1e-7); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_mask_index_4) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_mask_index_4.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.23565151, 0.58627969, 0.75137484, 0.68586946, 0.62750375, 0.13284931, 0.13347220, 0.36357051, + 0.56910241, 0.48275986, 0.49440190, 0.45483324, 0.63547862, 0.97893149, 0.40630588, 0.38783622, + 0.07172249, 0.46385381, 0.99764502, 0.22219376, 0.67735291, 0.40799847, 0.74337566, 0.87263006, + }; + std::vector mask = { + 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, + }; + std::vector output = { + 0.07771622, 0.10724538, -0.19453585, 0.54342043, 0.07459468, 0.10934003, -0.19561143, 0.53936625, + 0.07927690, 0.10619678, -0.19399606, 0.54543519, 0.07459468, 0.10934003, -0.19561143, 0.53936625, + 0.05485561, 0.11278091, -0.20117569, 0.52096349, 0.06629646, 0.10195158, -0.19900991, 0.54654449, + 0.06491723, 0.10292297, -0.19678673, 0.53451663, 0.06549793, 0.11126325, -0.19989857, 0.53717279, + }; + std::vector present = { + -0.59188855, -0.34495637, -0.59508181, -0.25013468, -0.59176934, -0.33229247, -0.59576762, -0.29731843, + 0.14217430, -0.10403840, 0.08584045, -0.06193545, 0.12358667, -0.08588549, 0.10515238, -0.08629489, + -0.59092808, -0.28260738, -0.60047609, -0.30411413, -0.61210287, -0.28645760, -0.59391296, -0.34649473, + 0.12789863, -0.08159252, 0.08122411, -0.08866425, 0.06395009, -0.12896645, 0.14855847, -0.11978809, + 0.08783118, 0.12152332, 0.07067389, 0.09078297, 0.08385989, 0.13306075, 0.07459468, 0.10934003, + -0.19849420, 0.55928540, -0.18948570, 0.53154731, -0.19960676, 0.54237455, -0.19561143, 0.53936625, + 0.08509844, 0.08314656, 0.06388859, 0.12990499, 0.04582624, 0.09566365, 0.08674107, 0.10823163, + -0.18808734, 0.56137776, -0.20168513, 0.51830697, -0.20066255, 0.52363914, -0.19737384, 0.56921995, + }; + + test_case.add_input(input); + test_case.add_input(mask); + test_case.add_expected_output(output); + test_case.add_expected_output(present); + test_case.run_with_tolerance_as_fp(1e-7); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_past) { + const auto function = + onnx_import::import_onnx_model(file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_past.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.82966000, 0.77751911, 0.08977074, 0.06076468, 0.40659550, 0.19995944, 0.55544919, 0.83971608, + 0.86254036, 0.30894691, 0.80156928, 0.83092463, 0.14506543, 0.32196075, 0.42209163, 0.24465553, + 0.93944097, 0.73528159, 0.23347616, 0.60544974, 0.93329269, 0.67604774, 0.56349903, 0.26199624, + }; + std::vector mask = { + 1, + 1, + 1, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 1, + 0, + 1, + 0, + 1, + 1, + 1, + 1, + }; + std::vector past = { + 0.92467678, 0.79873562, 0.00939191, 0.34891853, 0.35521412, 0.21872006, 0.89974332, 0.74132687, 0.73566031, + 0.75168055, 0.06773245, 0.85702997, 0.76256698, 0.51739877, 0.91567177, 0.66617578, 0.88056499, 0.08436447, + 0.54744655, 0.25466520, 0.08500137, 0.19271941, 0.86525357, 0.21717627, 0.97158766, 0.42288730, 0.09890039, + 0.01148765, 0.97024685, 0.19697112, 0.67671591, 0.67960924, 0.46656516, 0.30850092, 0.73536104, 0.73938161, + 0.91650903, 0.57628596, 0.51164514, 0.11695814, 0.79792547, 0.97192264, 0.29246020, 0.41030061, 0.19014873, + 0.90233624, 0.84986305, 0.26141909, 0.84528726, 0.81416380, 0.00429944, 0.31476986, 0.00440918, 0.77413058, + 0.13409913, 0.20965169, 0.61764991, 0.55266041, 0.56107825, 0.42051074, 0.16804738, 0.80362344, 0.52392679, + 0.27550557, 0.66738850, 0.39348483, 0.31801429, 0.30325863, 0.37068403, 0.92767614, 0.60799408, 0.01458820, + 0.24194679, 0.59596598, 0.81762302, 0.38094005, 0.16618672, 0.92488551, 0.84298438, 0.21752745, + }; + std::vector output = { + 0.26186451, 0.45950246, -0.04001215, 0.47680017, 0.26333901, 0.46158865, -0.04006424, 0.47588652, + 0.26875457, 0.47031689, -0.03951600, 0.47674999, 0.26851410, 0.46987134, -0.03919901, 0.47629333, + 0.18083976, 0.16579385, -0.05161894, 0.63075018, 0.18228555, 0.16642828, -0.04873618, 0.63316816, + 0.18362364, 0.16702136, -0.05045432, 0.63178891, 0.18000112, 0.16541445, -0.05139139, 0.63105792, + }; + std::vector present = { + 0.92467678, 0.79873562, 0.00939191, 0.34891853, 0.35521412, 0.21872006, 0.89974332, 0.74132687, + 0.73566031, 0.75168055, -0.59527576, -0.23625080, -0.58657664, -0.29827437, -0.59528387, -0.33578828, + -0.59068960, -0.34870598, 0.06773245, 0.85702997, 0.76256698, 0.51739877, 0.91567177, 0.66617578, + 0.88056499, 0.08436447, 0.54744655, 0.25466520, 0.08536442, -0.06134639, 0.11295843, -0.04818217, + 0.14562836, -0.12305059, 0.15695867, -0.11161390, 0.08500137, 0.19271941, 0.86525357, 0.21717627, + 0.97158766, 0.42288730, 0.09890039, 0.01148765, 0.97024685, 0.19697112, -0.59141791, -0.31600696, + -0.58647990, -0.34302223, -0.59306550, -0.36427227, -0.59695083, -0.26431620, 0.67671591, 0.67960924, + 0.46656516, 0.30850092, 0.73536104, 0.73938161, 0.91650903, 0.57628596, 0.51164514, 0.11695814, + 0.11255538, -0.07302766, 0.16620418, -0.09871224, 0.15272795, -0.12076923, 0.08827571, -0.07442430, + 0.79792547, 0.97192264, 0.29246020, 0.41030061, 0.19014873, 0.90233624, 0.84986305, 0.26141909, + 0.84528726, 0.81416380, 0.07014155, 0.07749540, 0.08745074, 0.13131952, 0.08430066, 0.09709007, + 0.09247591, 0.11065811, 0.00429944, 0.31476986, 0.00440918, 0.77413058, 0.13409913, 0.20965169, + 0.61764991, 0.55266041, 0.56107825, 0.42051074, -0.18658412, 0.53568852, -0.19482780, 0.53271860, + -0.19558203, 0.57155901, -0.19633618, 0.57260245, 0.16804738, 0.80362344, 0.52392679, 0.27550557, + 0.66738850, 0.39348483, 0.31801429, 0.30325863, 0.37068403, 0.92767614, 0.08172131, 0.13249113, + 0.09947956, 0.10781212, 0.08890627, 0.12280971, 0.06911418, 0.09499176, 0.60799408, 0.01458820, + 0.24194679, 0.59596598, 0.81762302, 0.38094005, 0.16618672, 0.92488551, 0.84298438, 0.21752745, + -0.19839945, 0.53462923, -0.19349247, 0.57778782, -0.20039621, 0.56689924, -0.19190890, 0.53286803, + }; + + test_case.add_input(input); + test_case.add_input(mask); + test_case.add_input(past); + test_case.add_expected_output(output); + test_case.add_expected_output(present); + test_case.run_with_tolerance_as_fp(1e-6); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_extra_add) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_extra_add.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.14930259, 0.11199699, 0.81292826, 0.08368169, 0.05704883, 0.41276145, 0.38760167, 0.00146112, + 0.14275745, 0.54254925, 0.07962929, 0.31023681, 0.09597706, 0.60583973, 0.90233743, 0.33360451, + 0.18193199, 0.19159532, 0.07869831, 0.86026299, 0.20683478, 0.40150928, 0.93124926, 0.31805834, + }; + std::vector mask = { + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 0, + }; + std::vector extra_add = { + 0.73230380, 0.61824518, 0.19738488, 0.57034588, 0.22331032, 0.53262889, 0.60098642, 0.72943515, + 0.09009175, 0.81116527, 0.47240964, 0.49679127, 0.41110733, 0.29418564, 0.93818313, 0.64175284, + 0.06807775, 0.66733366, 0.78848422, 0.48788327, 0.38806340, 0.14002480, 0.72263688, 0.22772972, + 0.24000823, 0.75820386, 0.64254439, 0.19385594, 0.95595860, 0.59840417, 0.93769604, 0.62474734, + 0.36690548, 0.76047903, 0.62352085, 0.58574778, 0.64251810, 0.78072041, 0.43344691, 0.75383639, + 0.73950553, 0.92625278, 0.05066428, 0.08448382, 0.25980917, 0.50312829, 0.97800279, 0.05422170, + 0.05171391, 0.82828254, 0.42234898, 0.95752198, 0.96325767, 0.97909677, 0.35578200, 0.48091716, + 0.03637243, 0.91552693, 0.43403026, 0.94275808, 0.51182085, 0.86773109, 0.38459453, 0.87822068, + }; + std::vector output = { + 0.06090815, 0.12919067, -0.19883196, 0.50295448, 0.06090815, 0.12919067, -0.19883196, 0.50295448, + 0.06090815, 0.12919067, -0.19883196, 0.50295448, 0.06090815, 0.12919067, -0.19883196, 0.50295448, + 0.08714182, 0.12259886, -0.19516067, 0.54010558, 0.08671370, 0.12369543, -0.19658084, 0.54502594, + 0.08458151, 0.12488046, -0.19519810, 0.53906947, 0.09063499, 0.12088943, -0.19583938, 0.54266596, + }; + std::vector present = { + -0.59800303, -0.35666457, -0.59420627, -0.31881350, -0.59887993, -0.27025288, -0.60216135, -0.27772796, + 0.11659990, -0.11224300, 0.09693416, -0.07304113, 0.06023501, -0.05941332, 0.06434284, -0.07978789, + -0.59005713, -0.37009716, -0.59542215, -0.27914333, -0.57998544, -0.29826957, -0.58625919, -0.28872511, + 0.15994480, -0.11288825, 0.07906821, -0.05991337, 0.14479136, -0.04415035, 0.13493451, -0.06541853, + 0.07513385, 0.14411135, 0.07505661, 0.14532046, 0.06090815, 0.12919067, 0.05788904, 0.12018456, + -0.20586906, 0.53715372, -0.20203318, 0.52092510, -0.19883196, 0.50295448, -0.19937295, 0.51055026, + 0.09417956, 0.12943678, 0.06923291, 0.12574309, 0.10221909, 0.11366953, 0.09235901, 0.09584601, + -0.20036517, 0.56818324, -0.19709785, 0.51547027, -0.18871340, 0.55736589, -0.18826833, 0.55965197, + }; + + test_case.add_input(input); + test_case.add_input(mask); + test_case.add_input(extra_add); + test_case.add_expected_output(output); + test_case.add_expected_output(present); + test_case.run_with_tolerance_as_fp(1e-7); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_attention_dynamic_shapes) { + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/com.microsoft/attention_dynamic_shapes.onnx")); + auto test_case = test::TestCase(function); + + std::vector input = { + 0.42226878, 0.50984067, 0.80440795, 0.68040705, 0.93614250, 0.45104721, 0.71767306, 0.48596525, + 0.70076728, 0.04500086, 0.28930107, 0.77435863, 0.19392140, 0.90290719, 0.91955870, 0.58811885, + 0.76795286, 0.62884814, 0.23377730, 0.49212688, 0.87256873, 0.11944817, 0.57715887, 0.91886938, + }; + std::vector weights = { + 0.99377930, 0.22733542, 0.43217131, 0.60717988, 0.97224706, 0.70020503, 0.92439449, 0.41512674, 0.47728160, + 0.40306625, 0.72619593, 0.37954643, 0.36950976, 0.84305370, 0.61671126, 0.22251014, 0.73839295, 0.73471880, + 0.37428924, 0.80240524, 0.23120961, 0.06072779, 0.92840081, 0.71558088, 0.08719950, 0.51666921, 0.53768843, + 0.48113129, 0.46389169, 0.01036468, 0.37341005, 0.67195475, 0.53599644, 0.41795707, 0.58081782, 0.97939289, + }; + std::vector bias = { + 0.77122736, + 0.75600564, + 0.86177206, + 0.69982684, + 0.74719858, + 0.78054035, + 0.80007398, + 0.74902135, + 0.81258053, + 0.01575289, + 0.08463049, + 0.39671996, + }; + std::vector mask = { + 0, + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + }; + std::vector past = { + 0.27759778, 0.18458818, 0.63114458, 0.09953160, 0.59739488, 0.63917851, 0.18828323, 0.65625650, 0.84574437, + 0.91846281, 0.55102497, 0.27506110, 0.06816208, 0.82616585, 0.85912132, 0.88682729, 0.14730524, 0.61618829, + 0.89891797, 0.27753425, 0.57438278, 0.33753166, 0.88768929, 0.35533753, 0.30193496, 0.81678063, 0.26569194, + 0.62769043, 0.61990744, 0.59077013, 0.11058200, 0.97370809, 0.81339806, 0.57207322, 0.80417949, 0.54185718, + 0.80831683, 0.29390740, 0.29051417, 0.51964313, 0.04341308, 0.05925354, 0.82397246, 0.55753845, 0.61247689, + 0.98571628, 0.07566493, 0.37537411, 0.42080343, 0.21715857, 0.57869565, 0.55962265, 0.82500041, 0.60776925, + 0.19367239, 0.88382334, 0.20328504, 0.58192456, 0.94542676, 0.98562658, 0.64355153, 0.69856495, 0.30377558, + 0.02857198, 0.96969068, 0.48450547, 0.98341352, 0.03546083, 0.84963584, 0.94460547, 0.90907097, 0.22525074, + 0.12530145, 0.52223104, 0.09549426, 0.93127102, 0.93429947, 0.01428344, 0.74249738, 0.22606593, + }; + std::vector output = { + 1.47439122, 0.50951630, 1.17974961, 1.58501005, 1.49403512, 0.51560062, 1.18972027, 1.59668207, + 1.48384988, 0.51248586, 1.18596375, 1.59219086, 1.44181466, 0.50219649, 1.15537691, 1.55348074, + 0.83429223, 0.59521818, 0.87688094, 0.13611843, 0.82936716, 0.61004817, 0.87633312, 0.13887596, + 0.83155584, 0.59382534, 0.87496555, 0.14041223, 0.83309680, 0.58982348, 0.87517864, 0.13930768, + }; + std::vector present = { + 0.27759778, 0.18458818, 0.63114458, 0.09953160, 0.59739488, 0.63917851, 0.18828323, 0.65625650, 0.84574437, + 0.91846281, 1.90736914, 1.45914197, 2.30920029, 1.94944119, 2.12886763, 1.64736962, 1.36378694, 1.03263116, + 0.55102497, 0.27506110, 0.06816208, 0.82616585, 0.85912132, 0.88682729, 0.14730524, 0.61618829, 0.89891797, + 0.27753425, 1.68161881, 1.87394094, 1.94785213, 2.08572555, 1.90705216, 1.90777159, 1.23910809, 1.52017307, + 0.57438278, 0.33753166, 0.88768929, 0.35533753, 0.30193496, 0.81678063, 0.26569194, 0.62769043, 0.61990744, + 0.59077013, 2.02901411, 1.58923888, 2.17776394, 1.76309133, 1.74264824, 1.31485105, 1.71575761, 1.29775190, + 0.11058200, 0.97370809, 0.81339806, 0.57207322, 0.80417949, 0.54185718, 0.80831683, 0.29390740, 0.29051417, + 0.51964313, 1.66065478, 2.17192268, 1.86598253, 2.03193212, 1.52620018, 1.82728052, 1.46963060, 1.87916136, + 0.04341308, 0.05925354, 0.82397246, 0.55753845, 0.61247689, 0.98571628, 0.07566493, 0.37537411, 0.42080343, + 0.21715857, 1.56316149, 0.55312467, 1.59553123, 0.53537023, 1.64308119, 0.62742490, 1.31600118, 0.37510848, + 0.57869565, 0.55962265, 0.82500041, 0.60776925, 0.19367239, 0.88382334, 0.20328504, 0.58192456, 0.94542676, + 0.98562658, 1.33183134, 1.70965421, 1.70983100, 1.76660407, 1.46399045, 1.70318413, 0.83565855, 1.37921953, + 0.64355153, 0.69856495, 0.30377558, 0.02857198, 0.96969068, 0.48450547, 0.98341352, 0.03546083, 0.84963584, + 0.94460547, 1.60677671, 0.53308368, 1.60789728, 0.56227136, 1.50563633, 0.50456268, 1.49554634, 0.48299593, + 0.90907097, 0.22525074, 0.12530145, 0.52223104, 0.09549426, 0.93127102, 0.93429947, 0.01428344, 0.74249738, + 0.22606593, 1.59781134, 2.01703453, 1.58993423, 1.78536010, 1.21809304, 1.69219351, 1.24090374, 1.75499403, + }; + + test_case.add_input(Shape{2, 4, 3}, input); + test_case.add_input(Shape{3, 12}, weights); + test_case.add_input(Shape{12}, bias); + test_case.add_input(Shape{2, 9}, mask); + test_case.add_input(Shape{2, 2, 2, 5, 2}, past); + test_case.add_expected_output(Shape{2, 4, 4}, output); + test_case.add_expected_output(Shape{2, 2, 2, 9, 2}, present); + test_case.run_with_tolerance_as_fp(1e-6); +} diff --git a/ngraph/test/onnx/onnx_import_dyn_shapes.in.cpp b/ngraph/test/onnx/onnx_import_dyn_shapes.in.cpp index df3184753be966..fdc4eab69bdb60 100644 --- a/ngraph/test/onnx/onnx_import_dyn_shapes.in.cpp +++ b/ngraph/test/onnx/onnx_import_dyn_shapes.in.cpp @@ -15,9 +15,9 @@ #include #include +#include "default_opset.hpp" #include "gtest/gtest.h" #include "ngraph/file_util.hpp" -#include "default_opset.hpp" #include "onnx_import/onnx.hpp" #include "engines_util/test_engines.hpp" #include "engines_util/test_case.hpp" @@ -333,10 +333,9 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_dyn_shapes_max_pool_with_indices_output) { 25.f, 25.f, 23.f, 24.f, 25.f, 25.f, 25.f, 23.f, 24.f, 25.f, 25.f, 25.f}; test_case.add_expected_output(Shape{1, 1, 5, 5}, expected_values); - // indices output is not supported and is ingored in current implementation - // std::vector expected_indices{12, 13, 14, 14, 14, 17, 18, 19, 19, 19, 22, 23, 24, 24, - // 24, 22, 23, 24, 24, 24, 22, 23, 24, 24, 24}; - // test_case.add_expected_output(Shape{1, 1, 5, 5}, expected_indices); + std::vector expected_indices{12, 13, 14, 14, 14, 17, 18, 19, 19, 19, 22, 23, 24, + 24, 24, 22, 23, 24, 24, 24, 22, 23, 24, 24, 24}; + test_case.add_expected_output(Shape{1, 1, 5, 5}, expected_indices); test_case.run(); } diff --git a/ngraph/test/onnx/onnx_import_library.cpp b/ngraph/test/onnx/onnx_import_library.cpp index 61df4cf84e3018..0968e59295798f 100644 --- a/ngraph/test/onnx/onnx_import_library.cpp +++ b/ngraph/test/onnx/onnx_import_library.cpp @@ -21,7 +21,7 @@ NGRAPH_TEST(onnx, check_ir_version_support) { // // The last step is to also update the details::onnx::contains_onnx_model_keys() function // in the same file to make sure that prototxt format validation also covers the changes in ONNX - EXPECT_EQ(ONNX_NAMESPACE::Version::IR_VERSION, 7) + EXPECT_EQ(ONNX_NAMESPACE::Version::IR_VERSION, 8) << "The IR_VERSION defined in ONNX does not match the version that OpenVINO supports. " "Please check the source code of this test for details and explanation how to proceed."; } diff --git a/ngraph/test/onnx/onnx_import_with_editor.in.cpp b/ngraph/test/onnx/onnx_import_with_editor.in.cpp index 88aef0c548a7d4..8f62f3228e1bfe 100644 --- a/ngraph/test/onnx/onnx_import_with_editor.in.cpp +++ b/ngraph/test/onnx/onnx_import_with_editor.in.cpp @@ -26,7 +26,7 @@ using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); // ############################################################################ CORE TESTS NGRAPH_TEST(${BACKEND_NAME}, onnx_compress_axis_0) { - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_0.onnx")}; + ov::onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_0.onnx")}; std::map> in_vals; @@ -42,7 +42,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_compress_axis_0) { } NGRAPH_TEST(${BACKEND_NAME}, onnx_compress_axis_1) { - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_1.onnx")}; + ov::onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_1.onnx")}; std::map> in_vals; @@ -58,7 +58,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_compress_axis_1) { } NGRAPH_TEST(${BACKEND_NAME}, onnx_compress_default_axis) { - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_default_axis.onnx")}; + ov::onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_default_axis.onnx")}; std::map> in_vals; @@ -74,7 +74,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_compress_default_axis) { } NGRAPH_TEST(${BACKEND_NAME}, onnx_compress_negative_axis) { - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_negative_axis.onnx")}; + ov::onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/compress_negative_axis.onnx")}; std::map> in_vals; diff --git a/ngraph/test/onnx/onnx_test_utils.in.cpp b/ngraph/test/onnx/onnx_test_utils.in.cpp index 40ce14c595636c..7ab1cb22882ad8 100644 --- a/ngraph/test/onnx/onnx_test_utils.in.cpp +++ b/ngraph/test/onnx/onnx_test_utils.in.cpp @@ -31,7 +31,7 @@ TYPED_TEST_P(ElemTypesTests, onnx_test_add_abc_set_precission) { using DataType = TypeParam; const element::Type ng_type = element::from(); - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/add_abc_3d.onnx")}; + ov::onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/add_abc_3d.onnx")}; editor.set_input_types({{"A", ng_type}, {"B", ng_type}, {"C", ng_type}}); @@ -48,7 +48,8 @@ TYPED_TEST_P(ElemTypesTests, onnx_test_split_multioutput_set_precission) { using DataType = TypeParam; const element::Type ng_type = element::from(); - onnx_editor::ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/split_equal_parts_default.onnx")}; + ov::onnx_editor::ONNXModelEditor editor{ + file_util::path_join(SERIALIZED_ZOO, "onnx/split_equal_parts_default.onnx")}; editor.set_input_types({{"input", ng_type}}); diff --git a/ngraph/test/onnx/onnx_transformations.cpp b/ngraph/test/onnx/onnx_transformations.cpp index b9c400a498d060..7cd92624de136b 100644 --- a/ngraph/test/onnx/onnx_transformations.cpp +++ b/ngraph/test/onnx/onnx_transformations.cpp @@ -13,7 +13,7 @@ static std::string s_manifest = "${MANIFEST}"; NGRAPH_SUPPRESS_DEPRECATED_START using namespace ngraph; -using namespace onnx_editor; +using namespace ov::onnx_editor; using namespace ngraph::test; namespace { diff --git a/ngraph/test/opset.cpp b/ngraph/test/opset.cpp index 90a106b1cbcf49..a4b16ac49aef87 100644 --- a/ngraph/test/opset.cpp +++ b/ngraph/test/opset.cpp @@ -196,17 +196,18 @@ TEST(opset, custom_opset) { ov::OpSet opset; #ifndef OPENVINO_STATIC_LIBRARY opset.insert(); - opset.insert(); - opset.insert(); #endif + opset.insert(); + opset.insert(); opset.insert(); #ifdef OPENVINO_STATIC_LIBRARY - ASSERT_EQ(opset.get_types_info().size(), 1); + EXPECT_EQ(opset.get_types_info().size(), 2); #else - ASSERT_EQ(opset.get_types_info().size(), 3); + EXPECT_EQ(opset.get_types_info().size(), 3); + EXPECT_TRUE(opset.contains_type("MyOpOld")); + // TODO: why is it not registered? + EXPECT_TRUE(opset.contains_type("MyOpNewFromOld")); #endif - ASSERT_TRUE(opset.contains_type("MyOpNew")); - ASSERT_TRUE(opset.contains_type("MyOpOld")); - ASSERT_TRUE(opset.contains_type("MyOpNewFromOld")); - ASSERT_FALSE(opset.contains_type("MyOpIncorrect")); + EXPECT_TRUE(opset.contains_type("MyOpNew")); + EXPECT_FALSE(opset.contains_type("MyOpIncorrect")); } diff --git a/ngraph/test/partial_shape.cpp b/ngraph/test/partial_shape.cpp index 75329b632afa7f..756f793ddcb6e9 100644 --- a/ngraph/test/partial_shape.cpp +++ b/ngraph/test/partial_shape.cpp @@ -9,6 +9,44 @@ using namespace ngraph; +TEST(partial_shape, interators) { + const PartialShape ps({1, 2, 3}); + ASSERT_TRUE(ps.is_static()); + { + auto p = ps; + for (auto& d : p) { + d = Dimension::dynamic(); + } + ASSERT_TRUE(p.is_dynamic()); + } + { + auto p = ps; + auto it = p.begin(); + *it = Dimension::dynamic(); + ASSERT_TRUE(p.is_dynamic()); + } + { + auto p = ps; + auto it = p.rbegin(); + *it = Dimension::dynamic(); + ASSERT_TRUE(p.is_dynamic()); + } + { + auto p = ps; + auto it = p.end(); + --it; + *it = Dimension::dynamic(); + ASSERT_TRUE(p.is_dynamic()); + } + { + auto p = ps; + auto it = p.rend(); + --it; + *it = Dimension::dynamic(); + ASSERT_TRUE(p.is_dynamic()); + } +} + TEST(partial_shape, ps_construction_empty) { auto ps = PartialShape{}; ASSERT_TRUE(ps.rank().is_static()); diff --git a/ngraph/test/pass/serialization/read_ir.hpp b/ngraph/test/pass/serialization/read_ir.hpp index fcc70e1a1e702a..c3d60935bf31e8 100644 --- a/ngraph/test/pass/serialization/read_ir.hpp +++ b/ngraph/test/pass/serialization/read_ir.hpp @@ -12,9 +12,9 @@ namespace ov { namespace test { inline std::shared_ptr readModel(const std::string& model_path, const std::string& weights_path) { - static ngraph::frontend::FrontEndManager manager; - ngraph::frontend::FrontEnd::Ptr FE; - ngraph::frontend::InputModel::Ptr inputModel; + static ov::frontend::FrontEndManager manager; + ov::frontend::FrontEnd::Ptr FE; + ov::frontend::InputModel::Ptr inputModel; ov::VariantVector params{ov::make_variant(model_path)}; if (!weights_path.empty()) @@ -31,9 +31,9 @@ inline std::shared_ptr readModel(const std::string& model_path, co } inline std::shared_ptr readModel(const std::string& model) { - static ngraph::frontend::FrontEndManager manager; - ngraph::frontend::FrontEnd::Ptr FE; - ngraph::frontend::InputModel::Ptr inputModel; + static ov::frontend::FrontEndManager manager; + ov::frontend::FrontEnd::Ptr FE; + ov::frontend::InputModel::Ptr inputModel; std::istringstream modelStringStream(model); std::istream& modelStream = modelStringStream; diff --git a/ngraph/test/pass/serialization/serialize.cpp b/ngraph/test/pass/serialization/serialize.cpp index 7b556a8f1cf38b..cac86facd02489 100644 --- a/ngraph/test/pass/serialization/serialize.cpp +++ b/ngraph/test/pass/serialization/serialize.cpp @@ -74,7 +74,8 @@ INSTANTIATE_TEST_SUITE_P( std::make_tuple("conv_with_rt_info.xml", ""), std::make_tuple("loop_2d_add.xml", "loop_2d_add.bin"), std::make_tuple("nms5_dynamism.xml", "nms5_dynamism.bin"), - std::make_tuple("if_diff_case.xml", "if_diff_case.bin"))); + std::make_tuple("if_diff_case.xml", "if_diff_case.bin"), + std::make_tuple("if_body_without_parameters.xml", "if_body_without_parameters.bin"))); #ifdef NGRAPH_ONNX_FRONTEND_ENABLE diff --git a/ngraph/test/preprocess.cpp b/ngraph/test/preprocess.cpp index 868a47723feb8a..aa532cd816476e 100644 --- a/ngraph/test/preprocess.cpp +++ b/ngraph/test/preprocess.cpp @@ -46,27 +46,35 @@ static std::shared_ptr create_n_inputs(element::Type type, const Parti TEST(pre_post_process, simple_mean_scale) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().mean(1.f).scale(2.f))).build(f); + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().mean(1.f).scale(2.f))).build(); + EXPECT_EQ(f->get_output_element_type(0), element::f32); +} + +TEST(pre_post_process, simple_mean_scale_getters) { + auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); + auto p = PrePostProcessor(f); + p.input("tensor_input1").preprocess().mean(1).scale(2); + f = p.build(); EXPECT_EQ(f->get_output_element_type(0), element::f32); } TEST(pre_post_process, convert_element_type_and_scale) { auto f = create_simple_function(element::i8, Shape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::i16)) .preprocess(PreProcessSteps() .convert_element_type(element::f32) .scale(2.f) .convert_element_type(element::i8))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::i16); EXPECT_EQ(f->get_output_element_type(0), element::i8); } TEST(pre_post_process, convert_element_type_implicit) { auto f = create_simple_function(element::i32, Shape{1, 3, 224, 224}); - f = PrePostProcessor().input(InputInfo().tensor(InputTensorInfo().set_element_type(element::f32))).build(f); + f = PrePostProcessor(f).input(InputInfo().tensor(InputTensorInfo().set_element_type(element::f32))).build(); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::f32); EXPECT_EQ(f->get_results().front()->get_element_type(), element::i32); } @@ -74,11 +82,11 @@ TEST(pre_post_process, convert_element_type_implicit) { TEST(pre_post_process, convert_element_type_same) { auto f = create_simple_function(element::i32, Shape{1, 3, 224, 224}); auto old_size = f->get_ops().size(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo("tensor_input1") .tensor(InputTensorInfo().set_element_type(element::i32)) .preprocess(PreProcessSteps().convert_element_type(element::i32))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::i32); EXPECT_EQ(old_size, f->get_ops().size()); } @@ -87,7 +95,7 @@ TEST(pre_post_process, convert_element_type_default) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); auto type_custom1 = element::Type(); auto type_custom2 = element::Type(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::i32)) .preprocess(PreProcessSteps() @@ -100,7 +108,7 @@ TEST(pre_post_process, convert_element_type_default) { type_custom2 = node.get_element_type(); return node; }))) - .build(f); + .build(); EXPECT_EQ(type_custom1, element::i32); EXPECT_EQ(type_custom2, element::f32); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::i32); @@ -109,7 +117,7 @@ TEST(pre_post_process, convert_element_type_default) { TEST(pre_post_process, empty_preprocess) { auto f = create_simple_function(element::i8, Shape{1, 3, 2, 2}); - f = PrePostProcessor().input(InputInfo().tensor(InputTensorInfo().set_element_type(element::i8))).build(f); + f = PrePostProcessor(f).input(InputInfo().tensor(InputTensorInfo().set_element_type(element::i8))).build(); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::i8); EXPECT_EQ(f->get_output_element_type(0), element::i8); } @@ -117,45 +125,45 @@ TEST(pre_post_process, empty_preprocess) { TEST(pre_post_process, preprocess_assert_input_without_index) { auto f = create_n_inputs<2>(element::f32, Shape{1, 3, 2, 2}); auto inp = InputInfo(); - EXPECT_ANY_THROW(f = PrePostProcessor().input(std::move(inp)).build(f)); + EXPECT_ANY_THROW(f = PrePostProcessor(f).input(std::move(inp)).build()); inp = InputInfo("some_non_existing_name"); - EXPECT_ANY_THROW(f = PrePostProcessor().input(std::move(inp)).build(f)); + EXPECT_ANY_THROW(f = PrePostProcessor(f).input(std::move(inp)).build()); } TEST(pre_post_process, convert_element_type_from_unknown) { auto f = create_simple_function(element::i32, Shape{1, 3, 224, 224}); ASSERT_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess( PreProcessSteps().convert_element_type(element::dynamic).convert_element_type(element::i32))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, scale_not_float) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); ASSERT_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess(PreProcessSteps().convert_element_type(element::i32).scale(2.0f))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, mean_not_float) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); - ASSERT_THROW(f = PrePostProcessor() + ASSERT_THROW(f = PrePostProcessor(f) .input(InputInfo().preprocess(PreProcessSteps().convert_element_type(element::i32).mean(2.0f))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, tensor_element_type_and_scale) { auto f = create_simple_function(element::i8, Shape{1, 3, 1, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::f32)) .preprocess(PreProcessSteps().scale(2.0f).convert_element_type(element::i8))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::f32); EXPECT_EQ(f->get_output_element_type(0), element::i8); @@ -166,14 +174,14 @@ TEST(pre_post_process, convert_color_nv12_rgb_single) { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 2, 2, 3}); auto name = f->get_parameters()[0]->get_friendly_name(); auto tensor_names = f->get_parameters().front()->get_output_tensor(0).get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input( InputInfo() .tensor(InputTensorInfo() .set_element_type(element::u8) .set_color_format(ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB).convert_element_type(element::f32))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().size(), 1); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::u8); @@ -187,11 +195,11 @@ TEST(pre_post_process, convert_color_nv12_bgr_single) { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 2, 2, 3}); auto name = f->get_parameters()[0]->get_friendly_name(); auto tensor_names = f->get_parameters().front()->get_output_tensor(0).get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().size(), 1); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::f32); @@ -203,11 +211,11 @@ TEST(pre_post_process, convert_color_nv12_bgr_single) { TEST(pre_post_process, convert_color_nv12_bgr_2_planes) { auto f = create_simple_function(element::f32, Shape{5, 2, 2, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES, {"TestY", "TestUV"})) .preprocess(PreProcessSteps().convert_color(ColorFormat::BGR))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().size(), 2); EXPECT_EQ(f->get_parameters()[0]->get_friendly_name(), "input1/TestY"); @@ -223,11 +231,11 @@ TEST(pre_post_process, convert_color_nv12_bgr_2_planes) { TEST(pre_post_process, convert_color_nv12_rgb_2_planes) { auto f = create_simple_function(element::f32, Shape{5, 2, 2, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().size(), 2); EXPECT_EQ(f->get_parameters()[0]->get_element_type(), element::f32); @@ -242,9 +250,9 @@ TEST(pre_post_process, convert_color_nv12_bgr_2_planes_u8_lvalue) { input_tensor_info.set_color_format(ColorFormat::NV12_TWO_PLANES); auto steps = PreProcessSteps(); steps.convert_color(ColorFormat::BGR); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().tensor(std::move(input_tensor_info)).preprocess(std::move(steps))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().size(), 2); EXPECT_EQ(f->get_parameters()[0]->get_element_type(), element::u8); @@ -256,14 +264,14 @@ TEST(pre_post_process, convert_color_nv12_bgr_2_planes_u8_lvalue) { TEST(pre_post_process, convert_color_nv12_bgr_2_planes_el_type) { auto f = create_simple_function(element::u8, Shape{1, 2, 2, 3}); EXPECT_NO_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo() .set_element_type(element::f32) .set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess( PreProcessSteps().convert_element_type(element::u8).convert_color(ColorFormat::BGR))) - .build(f)); + .build()); ASSERT_EQ(f->get_parameters().size(), 2); EXPECT_EQ(f->get_parameters()[0]->get_element_type(), element::f32); @@ -272,11 +280,11 @@ TEST(pre_post_process, convert_color_nv12_bgr_2_planes_el_type) { TEST(pre_post_process, convert_color_same_type) { auto f = create_simple_function(element::u8, Shape{1, 2, 2, 3}); - EXPECT_NO_THROW(f = PrePostProcessor() + EXPECT_NO_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::RGB)) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))) - .build(f)); + .build()); EXPECT_EQ(f->get_parameters().size(), 1); EXPECT_EQ(f->get_parameters()[0]->get_partial_shape(), (PartialShape{1, 2, 2, 3})); @@ -285,34 +293,34 @@ TEST(pre_post_process, convert_color_same_type) { TEST(pre_post_process, convert_color_unsupported) { // Feel free to update this test when more color conversions are supported in future auto f = create_simple_function(element::f32, PartialShape{1, 4, 4, 3}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_SINGLE_PLANE)) .preprocess(PreProcessSteps().convert_color(ColorFormat::UNDEFINED))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess(PreProcessSteps().convert_color(ColorFormat::UNDEFINED))) - .build(f), + .build(), ov::AssertFailure); auto colors = {ColorFormat::NV12_TWO_PLANES, ColorFormat::NV12_SINGLE_PLANE, ColorFormat::RGB, ColorFormat::BGR}; for (const auto& color : colors) { - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::UNDEFINED)) .preprocess(PreProcessSteps().convert_color(color))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(color)) .preprocess(PreProcessSteps().convert_color(ColorFormat::UNDEFINED))) - .build(f), + .build(), ov::AssertFailure); } } @@ -320,23 +328,23 @@ TEST(pre_post_process, convert_color_unsupported) { TEST(pre_post_process, convert_color_incorrect_subnames) { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 2, 2, 3}); EXPECT_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_SINGLE_PLANE, {"Test"})) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))) - .build(f), + .build(), ov::AssertFailure); EXPECT_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES, {"Test"}))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo().tensor( InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES, {"1", "2", "3"}))) - .build(f), + .build(), ov::AssertFailure); } @@ -344,12 +352,12 @@ TEST(pre_post_process, convert_color_duplicate_subnames) { auto f = create_n_inputs<2>(element::f32, PartialShape{1, 2, 2, 3}); f->get_parameters()[0]->get_output_tensor(0).set_names({"tensor_input1"}); f->get_parameters()[1]->get_output_tensor(0).set_names({"tensor_input1/CustomUV"}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_SINGLE_PLANE, {"CustomY", "CustomUV"})) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))) - .build(f), + .build(), ov::AssertFailure); } @@ -357,22 +365,22 @@ TEST(pre_post_process, convert_color_duplicate_internal_subnames_mean) { auto f = create_simple_function(element::f32, PartialShape{1, 2, 2, 3}); for (int i = 0; i < 10; i++) { // Create preprocessing step several times (try to duplicate internal node names this way) - EXPECT_NO_THROW(f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().mean(0.1f))).build(f)); - EXPECT_NO_THROW(f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().scale(1.1f))).build(f)); + EXPECT_NO_THROW(f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().mean(0.1f))).build()); + EXPECT_NO_THROW(f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().scale(1.1f))).build()); EXPECT_NO_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess( PreProcessSteps().convert_element_type(element::u8).convert_element_type(element::f32))) - .build(f)); + .build()); } f = create_simple_function(element::f32, PartialShape{1, 2, 2, 3}); for (int i = 0; i < 10; i++) { - (f = PrePostProcessor() + (f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NHWC")) .preprocess(PreProcessSteps().convert_layout("NCHW")) .network(InputNetworkInfo().set_layout("NHWC"))) - .build(f)); + .build()); } f = create_simple_function(element::f32, PartialShape{1, 2, 2, 3}); auto p = PreProcessSteps(); @@ -380,56 +388,56 @@ TEST(pre_post_process, convert_color_duplicate_internal_subnames_mean) { p.resize(ResizeAlgorithm::RESIZE_LINEAR, i, i); } p.resize(ResizeAlgorithm::RESIZE_LINEAR); - EXPECT_NO_THROW(f = PrePostProcessor() + EXPECT_NO_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_spatial_static_shape(480, 640)) .preprocess(std::move(p)) .network(InputNetworkInfo().set_layout("NHWC"))) - .build(f)); + .build()); } TEST(pre_post_process, unsupported_network_color_format) { auto f = create_simple_function(element::f32, PartialShape{1, 4, 4, 3}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo().tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_SINGLE_PLANE))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo().tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES))) - .build(f), + .build(), ov::AssertFailure); EXPECT_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess(PreProcessSteps().convert_layout("NCHW").convert_color(ColorFormat::RGB))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess(PreProcessSteps().mean(0.1f).convert_color(ColorFormat::RGB))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES)) .preprocess(PreProcessSteps().scale(2.1f).convert_color(ColorFormat::RGB))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, custom_preprocessing) { auto f = create_simple_function(element::i32, Shape{1, 3, 1, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess(PreProcessSteps().custom([](const Output& node) { return std::make_shared(node); }))) - .build(f); + .build(); EXPECT_EQ(f->get_output_element_type(0), element::i32); } @@ -437,7 +445,7 @@ TEST(pre_post_process, test_lvalue) { auto f = create_simple_function(element::i8, Shape{1, 3, 1, 1}); auto name = f->get_parameters()[0]->get_friendly_name(); auto tensor_names = f->get_parameters().front()->get_output_tensor(0).get_names(); - auto p = PrePostProcessor(); + auto p = PrePostProcessor(f); auto p1 = std::move(p); p = std::move(p1); auto inputInfo = InputInfo(); @@ -466,7 +474,7 @@ TEST(pre_post_process, test_lvalue) { inputInfo.preprocess(std::move(same)); } p.input(std::move(inputInfo)); - f = p.build(f); + f = p.build(); EXPECT_EQ(f->get_parameters().front()->get_element_type(), element::f32); EXPECT_EQ(f->get_parameters().front()->get_friendly_name(), name); EXPECT_EQ(f->get_parameters().front()->get_layout(), "?CHW"); @@ -476,7 +484,7 @@ TEST(pre_post_process, test_lvalue) { TEST(pre_post_process, test_2_inputs_basic) { auto f = create_n_inputs<2>(element::f32, Shape{1, 3, 1, 1}); - { f = PrePostProcessor().input(InputInfo(1).preprocess(PreProcessSteps().mean(1.f).scale(2.0f))).build(f); } + { f = PrePostProcessor(f).input(InputInfo(1).preprocess(PreProcessSteps().mean(1.f).scale(2.0f))).build(); } EXPECT_EQ(f->get_output_element_type(0), element::f32); EXPECT_EQ(f->get_output_element_type(1), element::f32); } @@ -484,23 +492,23 @@ TEST(pre_post_process, test_2_inputs_basic) { TEST(pre_post_process, reuse_network_layout_no_tensor_info) { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 3, 2, 1}); f->get_parameters().front()->set_layout("NC??"); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess(PreProcessSteps().mean({1.f, 2.f, 3.f}).scale({2.f, 3.f, 4.f}))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().front()->get_layout(), "NC??"); } TEST(pre_post_process, reuse_network_layout_tensor_info) { auto f = create_simple_function(element::u8, PartialShape{Dimension::dynamic(), 3, 2, 1}); f->get_parameters().front()->set_layout("NC??"); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_element_type(element::f32)) .preprocess(PreProcessSteps() .mean({1.f, 2.f, 3.f}) .scale({2.f, 3.f, 4.f}) .convert_element_type(element::u8))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().front()->get_layout(), "NC??"); } @@ -508,11 +516,11 @@ TEST(pre_post_process, mean_scale_vector_tensor_layout) { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 3, 2, 1}); auto name = f->get_parameters().front()->get_friendly_name(); auto tensor_names = f->get_parameters().front()->get_output_tensor(0).get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NC??")) .preprocess(PreProcessSteps().mean({1.f, 2.f, 3.f}).scale({2.f, 3.f, 4.f}))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().front()->get_friendly_name(), name); EXPECT_EQ(f->get_parameters().front()->get_layout(), "NC??"); EXPECT_EQ(f->get_parameters().front()->get_output_tensor(0).get_names(), tensor_names); @@ -524,11 +532,11 @@ TEST(pre_post_process, mean_scale_dynamic_layout) { PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), 3}); auto name = f->get_parameters().front()->get_friendly_name(); auto tensor_names = f->get_parameters().front()->get_output_tensor(0).get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("N...C")) .preprocess(PreProcessSteps().mean({1.f, 2.f, 3.f}).scale({2.f, 3.f, 4.f}))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters().front()->get_friendly_name(), name); EXPECT_EQ(f->get_parameters().front()->get_layout(), "N...C"); @@ -539,33 +547,33 @@ TEST(pre_post_process, mean_scale_dynamic_layout) { TEST(pre_post_process, scale_vector_no_channels_layout) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); EXPECT_EQ(f->get_output_element_type(0), element::f32); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("N?HW")) .preprocess(PreProcessSteps().scale({0.1f, 0.2f, 0.3f}))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, scale_vector_dim_mismatch) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); EXPECT_EQ(f->get_output_element_type(0), element::f32); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW")) .preprocess(PreProcessSteps().scale({0.1f, 0.2f, 0.3f, 0.4f}))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, scale_vector_channels_out_of_range) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); ASSERT_EQ(f->get_output_element_type(0), element::f32); - ASSERT_THROW(f = PrePostProcessor() + ASSERT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("0123C")) .preprocess(PreProcessSteps().scale({0.1f, 0.2f, 0.3f}))) - .build(f), + .build(), ov::AssertFailure); } @@ -573,7 +581,7 @@ TEST(pre_post_process, mean_vector_no_layout) { auto f = create_simple_function(element::f32, PartialShape{Dimension::dynamic(), 3, 224, 224}); ASSERT_EQ(f->get_output_element_type(0), element::f32); ASSERT_THROW( - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().mean({0.1f, 0.2f, 0.3f}))).build(f), + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().mean({0.1f, 0.2f, 0.3f}))).build(), ov::AssertFailure); } @@ -582,71 +590,61 @@ TEST(pre_post_process, mean_vector_dynamic_channels_shape) { element::f32, PartialShape{Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic(), Dimension::dynamic()}); EXPECT_EQ(f->get_output_element_type(0), element::f32); - EXPECT_NO_THROW(f = PrePostProcessor() + EXPECT_NO_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW")) .preprocess(PreProcessSteps().mean({0.1f, 0.2f, 0.3f}))) - .build(f)); + .build()); EXPECT_EQ(f->get_output_element_type(0), element::f32); } // Error cases for 'resize' TEST(pre_post_process, resize_no_network_layout) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NHWC")) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_CUBIC))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, tensor_spatial_shape_no_layout_dims) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NC?W").set_spatial_static_shape(480, 640)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_CUBIC))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NCH?").set_spatial_static_shape(480, 640)) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_CUBIC))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, resize_no_tensor_height) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("N?WC")) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NHWC"))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, resize_no_tensor_width) { auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NH?C")) .preprocess(PreProcessSteps().resize(ResizeAlgorithm::RESIZE_LINEAR)) .network(InputNetworkInfo().set_layout("NHWC"))) - .build(f), - ov::AssertFailure); -} - -TEST(pre_post_process, double_input_info) { - auto f = create_simple_function(element::f32, Shape{1, 3, 224, 224}); - // Parameter is replaced during first pre-processing, parameter for second step will not be resolved properly - EXPECT_THROW(f = PrePostProcessor() - .input(InputInfo().tensor(InputTensorInfo().set_element_type(element::u8))) - .input(InputInfo().tensor(InputTensorInfo().set_element_type(element::u8))) - .build(f), + .build(), ov::AssertFailure); } @@ -656,10 +654,10 @@ TEST(pre_post_process, preprocess_convert_layout_implicit) { auto name_last_op = f->get_results().front()->get_input_source_output(0).get_node_shared_ptr()->get_friendly_name(); auto tensor_names = f->output().get_tensor().get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input( InputInfo().tensor(InputTensorInfo().set_layout("NHWC")).network(InputNetworkInfo().set_layout("NCHW"))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters()[0]->get_layout(), "NHWC"); EXPECT_EQ(f->get_parameters()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 2, 2, 3})); EXPECT_EQ(name, f->get_results().front()->get_friendly_name()); @@ -671,12 +669,12 @@ TEST(pre_post_process, preprocess_convert_layout_implicit) { TEST(pre_post_process, preprocess_convert_layout_default) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NHWC")) .preprocess(PreProcessSteps().convert_layout()) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters()[0]->get_layout(), "NHWC"); EXPECT_EQ(f->get_parameters()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 2, 2, 3})); } @@ -685,12 +683,12 @@ TEST(pre_post_process, preprocess_convert_layout_same) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); auto size_old = f->get_ordered_ops().size(); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("NCHW")) .preprocess(PreProcessSteps().convert_layout("NCHW")) .network(InputNetworkInfo().set_layout("NCHW"))) - .build(f); + .build(); EXPECT_EQ(f->get_parameters()[0]->get_layout(), "NCHW"); EXPECT_EQ(f->get_parameters()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 3, 2, 2})); // Verify that redundant ops were not added @@ -700,7 +698,7 @@ TEST(pre_post_process, preprocess_convert_layout_same) { TEST(pre_post_process, preprocess_convert_layout_dims) { auto f = create_simple_function(element::f32, Shape{1, 3, 480, 640}); - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 1, 2}))).build(f); + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 1, 2}))).build(); EXPECT_EQ(f->input().get_partial_shape(), (PartialShape{1, 480, 640, 3})); } @@ -708,9 +706,9 @@ TEST(pre_post_process, preprocess_convert_layout_dims) { TEST(pre_post_process, preprocess_convert_layout_dims_empty) { auto f = create_simple_function(element::f32, Shape{1, 3, 480, 640}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo().preprocess(PreProcessSteps().convert_layout(std::vector{}))) - .build(f); + .build(); EXPECT_EQ(f->input().get_partial_shape(), (PartialShape{1, 3, 480, 640})); } @@ -718,7 +716,7 @@ TEST(pre_post_process, preprocess_convert_layout_dims_empty) { TEST(pre_post_process, preprocess_convert_layout_dims_dyn_shape) { auto f = create_simple_function(element::f32, PartialShape::dynamic()); - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 1, 2}))).build(f); + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 1, 2}))).build(); EXPECT_EQ(f->input().get_partial_shape(), (PartialShape::dynamic())); } @@ -726,47 +724,47 @@ TEST(pre_post_process, preprocess_convert_layout_dims_dyn_shape) { TEST(pre_post_process, preprocess_convert_layout_invalid_dims) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); EXPECT_THROW( - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 2, 2}))).build(f), + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 2, 2}))).build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo().preprocess( PreProcessSteps().convert_layout({0, 3, 1, std::numeric_limits::max()}))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, preprocess_convert_layout_invalid_dims_dyn_shape) { auto f = create_simple_function(element::f32, PartialShape::dynamic()); EXPECT_THROW( - f = PrePostProcessor().input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 2, 2}))).build(f), + f = PrePostProcessor(f).input(InputInfo().preprocess(PreProcessSteps().convert_layout({0, 3, 2, 2}))).build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo().preprocess( PreProcessSteps().convert_layout({0, 3, 1, std::numeric_limits::max()}))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, preprocess_reverse_channels_multiple_planes) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); EXPECT_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES, {"Y", "UV"})) .preprocess(PreProcessSteps().reverse_channels())) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, preprocess_reverse_channels_no_c_dim) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo() .tensor(InputTensorInfo().set_layout("N?HW")) .preprocess(PreProcessSteps().reverse_channels())) - .build(f), + .build(), ov::AssertFailure); } @@ -777,9 +775,9 @@ TEST(pre_post_process, postprocess_convert_element_type_explicit) { auto name = f->output().get_node_shared_ptr()->get_friendly_name(); auto name_last_op = f->get_results().front()->get_input_source_output(0).get_node_shared_ptr()->get_friendly_name(); auto old_names = f->output().get_tensor().get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo().postprocess(PostProcessSteps().convert_element_type(element::u8))) - .build(f); + .build(); EXPECT_EQ(f->get_results().size(), 1); EXPECT_EQ(f->get_results()[0]->get_element_type(), element::u8); EXPECT_EQ(f->output().get_tensor().get_names(), old_names); @@ -803,11 +801,11 @@ TEST(pre_post_process, postprocess_convert_element_type_default) { auto name = f->output(1).get_node_shared_ptr()->get_friendly_name(); auto name_last_op = f->get_results().front()->get_input_source_output(0).get_node_shared_ptr()->get_friendly_name(); auto tensor_names = f->output(1).get_tensor().get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo(1) .postprocess(PostProcessSteps().convert_element_type()) .tensor(OutputTensorInfo().set_element_type(element::u8))) - .build(f); + .build(); EXPECT_EQ(f->get_results()[0]->get_element_type(), element::f32); EXPECT_EQ(f->get_results()[1]->get_element_type(), element::u8); EXPECT_EQ(name, f->output(1).get_node_shared_ptr()->get_friendly_name()); @@ -819,11 +817,11 @@ TEST(pre_post_process, postprocess_convert_element_type_default) { TEST(pre_post_process, postprocess_convert_element_type_same) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); auto size_old = f->get_ordered_ops().size(); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo("tensor_output1") .postprocess(PostProcessSteps().convert_element_type(element::f32)) .tensor(OutputTensorInfo().set_element_type(element::f32))) - .build(f); + .build(); EXPECT_EQ(f->get_results()[0]->get_element_type(), element::f32); // Verify that redundant ops were not added @@ -833,19 +831,19 @@ TEST(pre_post_process, postprocess_convert_element_type_same) { TEST(pre_post_process, postprocess_convert_element_type_default_error) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); EXPECT_THROW( - f = PrePostProcessor().output(OutputInfo().postprocess(PostProcessSteps().convert_element_type())).build(f), + f = PrePostProcessor(f).output(OutputInfo().postprocess(PostProcessSteps().convert_element_type())).build(), ov::AssertFailure); } TEST(pre_post_process, postprocess_convert_element_type_implicit) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor().output(OutputInfo().tensor(OutputTensorInfo().set_element_type(element::u8))).build(f); + f = PrePostProcessor(f).output(OutputInfo().tensor(OutputTensorInfo().set_element_type(element::u8))).build(); EXPECT_EQ(f->get_results()[0]->get_element_type(), element::u8); } TEST(pre_post_process, preprocess_keep_params_order) { auto f = create_n_inputs<3>(element::f32, Shape{1, 2, 2, 3}); - f = PrePostProcessor() + f = PrePostProcessor(f) .input(InputInfo(1) .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES, {"Y", "UV"})) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))) @@ -853,7 +851,7 @@ TEST(pre_post_process, preprocess_keep_params_order) { .input(InputInfo(2) .tensor(InputTensorInfo().set_color_format(ColorFormat::NV12_TWO_PLANES, {"Y", "UV"})) .preprocess(PreProcessSteps().convert_color(ColorFormat::RGB))) - .build(f); + .build(); ASSERT_EQ(f->get_parameters().size(), 5); EXPECT_EQ(f->get_parameters()[0]->get_layout(), "NCHW"); EXPECT_EQ(f->get_parameters()[1]->get_layout(), "NHWC"); @@ -877,29 +875,29 @@ TEST(pre_post_process, preprocess_keep_params_order) { // --- PostProcess - set/convert layout --- TEST(pre_post_process, postprocess_set_layout_network) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor().output(OutputInfo().network(OutputNetworkInfo().set_layout("NCHW"))).build(f); + f = PrePostProcessor(f).output(OutputInfo().network(OutputNetworkInfo().set_layout("NCHW"))).build(); EXPECT_EQ(f->get_results()[0]->get_layout(), "NCHW"); } TEST(pre_post_process, postprocess_convert_layout_implicit) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo() .network(OutputNetworkInfo().set_layout("NCHW")) .tensor(OutputTensorInfo().set_layout("NHWC"))) - .build(f); + .build(); EXPECT_EQ(f->get_results()[0]->get_layout(), "NHWC"); EXPECT_EQ(f->get_results()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 2, 2, 3})); } TEST(pre_post_process, postprocess_convert_layout_explicit_no_target) { auto f = create_n_inputs<2>(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo(1) .network(OutputNetworkInfo().set_layout("NCHW")) .postprocess(PostProcessSteps().convert_layout("NHWC"))) - .build(f); + .build(); EXPECT_EQ(f->get_results()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 3, 2, 2})); EXPECT_EQ(f->get_results()[1]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 2, 2, 3})); } @@ -907,12 +905,25 @@ TEST(pre_post_process, postprocess_convert_layout_explicit_no_target) { TEST(pre_post_process, postprocess_convert_layout_default) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo() .network(OutputNetworkInfo().set_layout("NCHW")) .postprocess(PostProcessSteps().convert_layout()) .tensor(OutputTensorInfo().set_layout("NHWC"))) - .build(f); + .build(); + EXPECT_EQ(f->get_results()[0]->get_layout(), "NHWC"); + EXPECT_EQ(f->get_results()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 2, 2, 3})); +} + +TEST(pre_post_process, postprocess_convert_layout_default_getters) { + auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); + + auto p = PrePostProcessor(f); + auto& out = p.output(); + out.network().set_layout("NCHW"); + out.postprocess().convert_layout(); + out.tensor().set_layout("NHWC"); + f = p.build(); EXPECT_EQ(f->get_results()[0]->get_layout(), "NHWC"); EXPECT_EQ(f->get_results()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 2, 2, 3})); } @@ -921,12 +932,12 @@ TEST(pre_post_process, postprocess_convert_layout_same) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); auto size_old = f->get_ordered_ops().size(); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo() .network(OutputNetworkInfo().set_layout("NCHW")) .postprocess(PostProcessSteps().convert_layout("NCHW")) .tensor(OutputTensorInfo().set_layout("NCHW"))) - .build(f); + .build(); EXPECT_EQ(f->get_results()[0]->get_layout(), "NCHW"); EXPECT_EQ(f->get_results()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 3, 2, 2})); // Verify that redundant ops were not added @@ -936,7 +947,7 @@ TEST(pre_post_process, postprocess_convert_layout_same) { TEST(pre_post_process, postprocess_convert_layout_dims) { auto f = create_simple_function(element::f32, Shape{1, 3, 480, 640}); - f = PrePostProcessor().output(OutputInfo().postprocess(PostProcessSteps().convert_layout({0, 2, 3, 1}))).build(f); + f = PrePostProcessor(f).output(OutputInfo().postprocess(PostProcessSteps().convert_layout({0, 2, 3, 1}))).build(); EXPECT_EQ(f->output().get_partial_shape(), (PartialShape{1, 480, 640, 3})); } @@ -944,9 +955,9 @@ TEST(pre_post_process, postprocess_convert_layout_dims) { TEST(pre_post_process, postprocess_convert_layout_dims_empty) { auto f = create_simple_function(element::f32, Shape{1, 3, 480, 640}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo().postprocess(PostProcessSteps().convert_layout(std::vector{}))) - .build(f); + .build(); EXPECT_EQ(f->output().get_partial_shape(), (PartialShape{1, 3, 480, 640})); } @@ -956,9 +967,9 @@ TEST(pre_post_process, postprocess_convert_layout_has_layout) { auto p = PostProcessSteps(); p.convert_layout({0, 2, 3, 1}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo().network(OutputNetworkInfo().set_layout("NC??")).postprocess(std::move(p))) - .build(f); + .build(); EXPECT_EQ(f->output().get_partial_shape(), (PartialShape{1, 480, 640, 3})); EXPECT_EQ(f->get_results()[0]->get_layout(), "N??C"); @@ -966,29 +977,29 @@ TEST(pre_post_process, postprocess_convert_layout_has_layout) { TEST(pre_post_process, postprocess_convert_layout_invalid_dims) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .output(OutputInfo().postprocess(PostProcessSteps().convert_layout({0, 3, 2, 2}))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .output(OutputInfo().postprocess( PostProcessSteps().convert_layout({0, 3, 1, std::numeric_limits::max()}))) - .build(f), + .build(), ov::AssertFailure); } TEST(pre_post_process, postprocess_convert_layout_invalid_dims_dyn_shape) { auto f = create_simple_function(element::f32, PartialShape::dynamic()); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .output(OutputInfo().postprocess(PostProcessSteps().convert_layout({0, 3, 2, 2}))) - .build(f), + .build(), ov::AssertFailure); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .output(OutputInfo().postprocess( PostProcessSteps().convert_layout({0, 3, 1, std::numeric_limits::max()}))) - .build(f), + .build(), ov::AssertFailure); } @@ -997,13 +1008,13 @@ TEST(pre_post_process, postprocess_convert_layout_invalid_dims_dyn_shape) { TEST(pre_post_process, postprocess_custom_step) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); bool hit = false; - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo().postprocess(PostProcessSteps().custom([&hit](const ov::Output& node) { auto abs = std::make_shared(node); hit = true; return abs; }))) - .build(f); + .build(); EXPECT_TRUE(hit); EXPECT_EQ(std::string(f->get_results()[0]->get_input_source_output(0).get_node()->get_type_name()), @@ -1012,11 +1023,11 @@ TEST(pre_post_process, postprocess_custom_step) { TEST(pre_post_process, postprocess_implicit_convert_element_type_and_layout) { auto f = create_simple_function(element::f32, Shape{1, 3, 2, 2}); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo() .network(OutputNetworkInfo().set_layout("NCHW")) .tensor(OutputTensorInfo().set_layout("NHWC").set_element_type(element::u8))) - .build(f); + .build(); EXPECT_EQ(f->get_results()[0]->get_element_type(), element::u8); EXPECT_EQ(f->get_results()[0]->get_layout(), "NHWC"); EXPECT_EQ(f->get_results()[0]->get_output_tensor(0).get_partial_shape(), (PartialShape{1, 2, 2, 3})); @@ -1025,9 +1036,9 @@ TEST(pre_post_process, postprocess_implicit_convert_element_type_and_layout) { TEST(pre_post_process, postprocess_assert_output_without_index) { auto f = create_n_inputs<2>(element::f32, Shape{1, 3, 2, 2}); auto out = OutputInfo(); - EXPECT_ANY_THROW(f = PrePostProcessor().output(std::move(out)).build(f)); + EXPECT_ANY_THROW(f = PrePostProcessor(f).output(std::move(out)).build()); out = OutputInfo("some_non_existing_name"); - EXPECT_ANY_THROW(f = PrePostProcessor().output(std::move(out)).build(f)); + EXPECT_ANY_THROW(f = PrePostProcessor(f).output(std::move(out)).build()); } TEST(pre_post_process, postprocess_keep_results_order) { @@ -1035,12 +1046,12 @@ TEST(pre_post_process, postprocess_keep_results_order) { auto names0 = f->output(0).get_tensor().get_names(); auto names1 = f->output(1).get_tensor().get_names(); auto names2 = f->output(2).get_tensor().get_names(); - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo(0).network(OutputNetworkInfo().set_layout("NCHW"))) .output(OutputInfo(1) .network(OutputNetworkInfo().set_layout("NCHW")) .tensor(OutputTensorInfo().set_layout("NHWC").set_element_type(element::u8))) - .build(f); + .build(); ASSERT_EQ(f->get_results().size(), 3); EXPECT_EQ(f->output(0).get_element_type(), element::f32); EXPECT_EQ(f->output(1).get_element_type(), element::u8); @@ -1083,10 +1094,10 @@ TEST(pre_post_process, postprocess_lvalues_1) { outputInfo.postprocess(std::move(steps)); outputInfo.tensor(std::move(tensorInfo)); - auto p = PrePostProcessor(); + auto p = PrePostProcessor(f); p.output(std::move(outputInfo)); - f = p.build(f); + f = p.build(); EXPECT_EQ(f->get_results().size(), 1); EXPECT_EQ(f->output().get_tensor().get_names().count("tensor_output1"), 1); EXPECT_EQ(f->output().get_node_shared_ptr()->get_friendly_name(), "Result1"); @@ -1106,7 +1117,7 @@ TEST(pre_post_process, exception_safety) { auto out_tensor_names0 = f->output(0).get_tensor().get_names(); auto out_name1 = f->output(1).get_node_shared_ptr()->get_friendly_name(); auto out_tensor_names1 = f->output(1).get_tensor().get_names(); - EXPECT_THROW(f = PrePostProcessor() + EXPECT_THROW(f = PrePostProcessor(f) .input(InputInfo(0) // this one is correct .tensor(InputTensorInfo().set_element_type(element::u8)) .preprocess(PreProcessSteps().convert_element_type(element::f32))) @@ -1115,18 +1126,18 @@ TEST(pre_post_process, exception_safety) { .preprocess(PreProcessSteps().custom([](const Output& node) -> Output { throw ngraph::ngraph_error("test error"); }))) - .build(f), + .build(), ov::AssertFailure); EXPECT_THROW( - f = PrePostProcessor() + f = PrePostProcessor(f) .output(OutputInfo(0) // this one is correct .tensor(OutputTensorInfo().set_element_type(element::u8))) .output(OutputInfo(1) // This one is not .postprocess(PostProcessSteps().custom([](const Output& node) -> Output { throw ngraph::ngraph_error("test error"); }))) - .build(f), + .build(), ngraph::ngraph_error); EXPECT_EQ(f->get_parameters().size(), 2); diff --git a/ngraph/test/runtime/CMakeLists.txt b/ngraph/test/runtime/CMakeLists.txt index 3b562478e706bc..3d26cd6b42535f 100644 --- a/ngraph/test/runtime/CMakeLists.txt +++ b/ngraph/test/runtime/CMakeLists.txt @@ -38,17 +38,19 @@ target_compile_definitions(ngraph_backend SHARED_LIB_PREFIX="${CMAKE_SHARED_LIBRARY_PREFIX}" SHARED_LIB_SUFFIX="${IE_BUILD_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}" ) -target_link_libraries(ngraph_backend PUBLIC ngraph - ngraph::builder - ngraph::reference) -if (NOT WIN32) - target_link_libraries(ngraph_backend PRIVATE ${CMAKE_DL_LIBS}) -endif() -target_include_directories(ngraph_backend PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(ngraph_backend PUBLIC ngraph ngraph::builder ngraph::reference + PRIVATE ${CMAKE_DL_LIBS} openvino::util) + +target_include_directories(ngraph_backend PUBLIC $) install(TARGETS ngraph_backend RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT tests EXCLUDE_FROM_ALL LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT tests EXCLUDE_FROM_ALL) +if(NOT BUILD_SHARED_LIBS) + install(TARGETS ngraph_backend + RUNTIME DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL + LIBRARY DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL) +endif() add_subdirectory(interpreter) add_subdirectory(ie) diff --git a/ngraph/test/runtime/backend.cpp b/ngraph/test/runtime/backend.cpp index 8bc4d3cfe92b86..e74687915c7997 100644 --- a/ngraph/test/runtime/backend.cpp +++ b/ngraph/test/runtime/backend.cpp @@ -21,6 +21,7 @@ #include "dynamic/dynamic_backend.hpp" #include "ngraph/file_util.hpp" #include "ngraph/util.hpp" +#include "openvino/util/file_util.hpp" using namespace std; using namespace ngraph; @@ -45,7 +46,7 @@ static string find_my_pathname() { #elif defined(__linux) || defined(__APPLE__) Dl_info dl_info; dladdr(reinterpret_cast(ngraph::to_lower), &dl_info); - return dl_info.dli_fname; + return ov::util::get_absolute_file_path(dl_info.dli_fname); #else # error "Unsupported OS" #endif diff --git a/ngraph/test/runtime/ie/CMakeLists.txt b/ngraph/test/runtime/ie/CMakeLists.txt index d89b723ee24981..fe0e79eab83c01 100644 --- a/ngraph/test/runtime/ie/CMakeLists.txt +++ b/ngraph/test/runtime/ie/CMakeLists.txt @@ -31,3 +31,8 @@ target_link_libraries(ie_backend PUBLIC ngraph_backend inference_engine) install(TARGETS ie_backend RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT tests EXCLUDE_FROM_ALL LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT tests EXCLUDE_FROM_ALL) +if(NOT BUILD_SHARED_LIBS) + install(TARGETS ie_backend + RUNTIME DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL + LIBRARY DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL) +endif() diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index b7e86e39791de0..6042755ad67ad7 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -24,9 +24,6 @@ IE_CPU.onnx_model_dequantize_linear_1d_zero_scale_int8 # C++ exception with description "Input data precision not supported. Expected float. IE_CPU.onnx_model_dequantize_linear_1d_zero_scale_int8_4d -# No support yet for RandomUniform -onnx_model_random_uniform -onnx_model_random_uniform_like # Result mismatch onnx_model_shape @@ -113,6 +110,10 @@ onnx_model_scatterND_param_i64_indices IE_CPU.onnx_constant_sparse_tensor_int64_3x4 IE_CPU.onnx_constant_sparse_tensor_uint64_3x4 +# I64 ONNX Clip Failing on ubuntu18/20_release CI +IE_CPU.onnx_clip_no_min_no_max_int64 # -2147483648 is not close to 2147483647 at index 2 +IE_CPU.onnx_clip_no_min_set_max_int64 # -1 is not close to 2147483647 at index 0 + # TopK Incorrect input data/index values precision onnx_model_argmax_int32 onnx_model_argmin_int32 @@ -374,14 +375,12 @@ tile_3d_few_repeats # Result mismatch sum_large_1d_to_scalar sum_stable_acc -max_pool_3d avg_pool_2d_2channel_2image_padded_only_above_include_in_computation avg_pool_3d_uneven_strided_padded multiple_result lrn_across_all_dims elu elu_negative_alpha -max_pool_2d_1channel_1image_overpadded grn_2d_with_bias erf divide_adjoint_stability @@ -389,8 +388,6 @@ notequal less sum_3d_to_scalar_int32 sum_2d_to_scalar_int8 -max_pool_uint8 -max_pool_int8 avg_pool_uint8 avg_pool_int8 max_to_scalar_int8 @@ -435,6 +432,12 @@ onnx_constant_integer_array adaptive_max_pool_1d adaptive_max_pool_2d adaptive_max_pool_3d +onnx_dyn_shapes_max_pool_with_indices_output +onnx_model_max_pool_3d +onnx_model_max_pool_4d_ceil_mode +onnx_model_max_pool_4d_dilations +onnx_model_max_pool_4d_strides +onnx_model_max_pool_4d_ceil_strides # Unsupported primitive of type: SigmoidBackprop sigmoid_bprop_n1c1h4 @@ -557,9 +560,6 @@ product_to_scalar_int8 min_to_scalar_int8 # Pooling layer. Unsupported mode. Only 4D and 5D blobs are supported as input. -max_pool_1d_1channel_1image -max_pool_1d_1channel_2image -max_pool_1d_2channel_2image avg_pool_1d_1channel_1image avg_pool_1d_1channel_2image avg_pool_1d_2channel_2image @@ -1568,3 +1568,5 @@ IE_CPU.onnx_model_gather_float_2D_neg_indices onnx_model_skip_layer_normalization_dynamic_shapes # Doesn't support op with dynamic shapes onnx_model_embed_layer_normalization_dynamic_shapes +# CPU plug-in doesn't support operation with dynamic rank +onnx_model_attention_dynamic_shapes diff --git a/ngraph/test/runtime/interpreter/CMakeLists.txt b/ngraph/test/runtime/interpreter/CMakeLists.txt index 2b99d191106094..dc39db0fc28ff0 100644 --- a/ngraph/test/runtime/interpreter/CMakeLists.txt +++ b/ngraph/test/runtime/interpreter/CMakeLists.txt @@ -26,3 +26,8 @@ target_link_libraries(interpreter_backend PUBLIC ngraph_backend PRIVATE ngraph_r install(TARGETS interpreter_backend RUNTIME DESTINATION ${IE_CPACK_RUNTIME_PATH} COMPONENT tests EXCLUDE_FROM_ALL LIBRARY DESTINATION ${IE_CPACK_LIBRARY_PATH} COMPONENT tests EXCLUDE_FROM_ALL) +if(NOT BUILD_SHARED_LIBS) + install(TARGETS interpreter_backend + RUNTIME DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL + LIBRARY DESTINATION tests COMPONENT tests EXCLUDE_FROM_ALL) +endif() diff --git a/ngraph/test/runtime/interpreter/evaluates_map.cpp b/ngraph/test/runtime/interpreter/evaluates_map.cpp index 3cbb4e238403eb..c6d6a1e499f1fc 100644 --- a/ngraph/test/runtime/interpreter/evaluates_map.cpp +++ b/ngraph/test/runtime/interpreter/evaluates_map.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -67,9 +69,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -1684,6 +1688,42 @@ bool evaluate(const shared_ptr& op, const HostTensorVector& outputs return true; } +template +bool evaluate(const shared_ptr& op, const HostTensorVector& outputs, const HostTensorVector& inputs) { + using T = typename element_type_traits::value_type; + runtime::reference::sigmoid(inputs[0]->get_data_ptr(), + outputs[0]->get_data_ptr(), + shape_size(inputs[0]->get_shape())); + return true; +} + +template +bool evaluate(const shared_ptr& op, const HostTensorVector& outputs, const HostTensorVector& inputs) { + using T = typename element_type_traits::value_type; + runtime::reference::exp(inputs[0]->get_data_ptr(), + outputs[0]->get_data_ptr(), + shape_size(inputs[0]->get_shape())); + return true; +} + +template +bool evaluate(const shared_ptr& op, const HostTensorVector& outputs, const HostTensorVector& inputs) { + using T = typename element_type_traits::value_type; + runtime::reference::tanh(inputs[0]->get_data_ptr(), + outputs[0]->get_data_ptr(), + shape_size(inputs[0]->get_shape())); + return true; +} + +template +bool evaluate(const shared_ptr& op, const HostTensorVector& outputs, const HostTensorVector& inputs) { + using T = typename element_type_traits::value_type; + runtime::reference::log(inputs[0]->get_data_ptr(), + outputs[0]->get_data_ptr(), + shape_size(inputs[0]->get_shape())); + return true; +} + namespace ctc_loss_v4 { template inline void evaluate(const shared_ptr& op, @@ -2476,17 +2516,42 @@ bool evaluate(const shared_ptr& op, const HostTensorVector& ou runtime::reference::gather_nd(inputs[0]->get_data_ptr(), inputs[1]->get_data_ptr(), outputs[0]->get_data_ptr(), - op->get_input_shape(0), - op->get_input_shape(1), - op->get_output_shape(0), + inputs[0]->get_shape(), + inputs[1]->get_shape(), + outputs[0]->get_shape(), + op->get_batch_dims()); + } else if (op->get_input_element_type(1) == element::i32) { + runtime::reference::gather_nd(inputs[0]->get_data_ptr(), + inputs[1]->get_data_ptr(), + outputs[0]->get_data_ptr(), + inputs[0]->get_shape(), + inputs[1]->get_shape(), + outputs[0]->get_shape(), + op->get_batch_dims()); + } else { + throw ngraph_error("Unexpected indices type for GatherND operation"); + } + return true; +} + +template +bool evaluate(const shared_ptr& op, const HostTensorVector& outputs, const HostTensorVector& inputs) { + using T = typename element_type_traits::value_type; + if (op->get_input_element_type(1) == element::i64) { + runtime::reference::gather_nd(inputs[0]->get_data_ptr(), + inputs[1]->get_data_ptr(), + outputs[0]->get_data_ptr(), + inputs[0]->get_shape(), + inputs[1]->get_shape(), + outputs[0]->get_shape(), op->get_batch_dims()); } else if (op->get_input_element_type(1) == element::i32) { runtime::reference::gather_nd(inputs[0]->get_data_ptr(), inputs[1]->get_data_ptr(), outputs[0]->get_data_ptr(), - op->get_input_shape(0), - op->get_input_shape(1), - op->get_output_shape(0), + inputs[0]->get_shape(), + inputs[1]->get_shape(), + outputs[0]->get_shape(), op->get_batch_dims()); } else { throw ngraph_error("Unexpected indices type for GatherND operation"); diff --git a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp index b5e6584febe822..706c606c83a703 100644 --- a/ngraph/test/runtime/interpreter/opset_int_tbl.hpp +++ b/ngraph/test/runtime/interpreter/opset_int_tbl.hpp @@ -106,3 +106,9 @@ NGRAPH_OP(MulticlassNms, op::v8) NGRAPH_OP(Slice, op::v8) NGRAPH_OP(DeformableConvolution, ngraph::op::v8) NGRAPH_OP(If, ngraph::op::v8) +NGRAPH_OP(GatherND, op::v8) + +NGRAPH_OP(Sigmoid, op::v0) +NGRAPH_OP(Tanh, op::v0) +NGRAPH_OP(Exp, op::v0) +NGRAPH_OP(Log, op::v0) diff --git a/ngraph/test/runtime/interpreter/unit_test.manifest b/ngraph/test/runtime/interpreter/unit_test.manifest index eeb1970a214bd7..9ace71fff4a21d 100644 --- a/ngraph/test/runtime/interpreter/unit_test.manifest +++ b/ngraph/test/runtime/interpreter/unit_test.manifest @@ -125,7 +125,3 @@ onnx_model_deformable_conv_2d # No support for unsigned types INTERPRETER.zero_sized_negative - -# No support yet for RandomUniform -INTERPRETER.onnx_model_random_uniform -INTERPRETER.onnx_model_random_uniform_like diff --git a/ngraph/test/threading.cpp b/ngraph/test/threading.cpp index 1cfb462c654086..5e9cd3e3ee247a 100644 --- a/ngraph/test/threading.cpp +++ b/ngraph/test/threading.cpp @@ -2,36 +2,95 @@ // SPDX-License-Identifier: Apache-2.0 // +#include + #include #include +#include #include #include #include "atomic_guard.hpp" -#include "gtest/gtest.h" -#include "ngraph/ngraph.hpp" +#include "ngraph_ops/type_relaxed.hpp" +#include "openvino/core/function.hpp" +#include "openvino/core/node.hpp" +#include "openvino/core/node_vector.hpp" +#include "openvino/opsets/opset8.hpp" using namespace ngraph; using namespace std; +std::shared_ptr create_complex_function(size_t wide = 50) { + const auto& split_subgraph = [](const ov::Output& input) -> ov::OutputVector { + auto relu = std::make_shared(input); + auto type_relaxed = + std::make_shared>(std::vector{element::f32}, + std::vector{element::f32}, + relu); + auto axis_node = ov::opset8::Constant::create(ov::element::i64, Shape{}, {1}); + auto split = std::make_shared(type_relaxed, axis_node, 2); + return split->outputs(); + }; + const auto& concat_subgraph = [](const ov::OutputVector& inputs) -> ov::Output { + auto concat = std::make_shared(inputs, 1); + auto type_relaxed = + std::make_shared>(std::vector{element::f32}, + std::vector{element::f32}, + concat); + auto relu = std::make_shared(concat); + return relu->output(0); + }; + + auto parameter = std::make_shared(ov::element::f32, ov::PartialShape::dynamic(4)); + std::queue> nodes; + { + auto outputs = split_subgraph(parameter->output(0)); + for (const auto& out : outputs) { + nodes.push(out); + } + } + + while (nodes.size() < wide) { + auto first = nodes.front(); + nodes.pop(); + auto outputs = split_subgraph(first); + + for (const auto& out : outputs) { + nodes.push(out); + } + } + + while (nodes.size() > 1) { + auto first = nodes.front(); + nodes.pop(); + auto second = nodes.front(); + nodes.pop(); + auto out = concat_subgraph(ov::OutputVector{first, second}); + + nodes.push(out); + } + auto result = std::make_shared(nodes.front()); + return std::make_shared(ov::ResultVector{result}, ov::ParameterVector{parameter}); +} + TEST(threading, get_friendly_name) { const size_t number = 20; Shape shape{}; - auto a = make_shared(element::i32, shape); - auto iconst0 = op::Constant::create(element::i32, Shape{}, {0}); - auto add_a1 = make_shared(a, iconst0); - auto add_a2 = make_shared(add_a1, iconst0); - auto add_a3 = make_shared(add_a2, iconst0); - auto abs_add_a3 = std::make_shared(add_a3); + auto a = make_shared(element::i32, shape); + auto iconst0 = ov::opset8::Constant::create(element::i32, Shape{}, {0}); + auto add_a1 = make_shared(a, iconst0); + auto add_a2 = make_shared(add_a1, iconst0); + auto add_a3 = make_shared(add_a2, iconst0); + auto abs_add_a3 = std::make_shared(add_a3); auto b = make_shared(element::i32, shape); - auto add_b1 = make_shared(b, iconst0); - auto add_b2 = make_shared(add_b1, iconst0); - auto abs_add_b2 = std::make_shared(add_b2); + auto add_b1 = make_shared(b, iconst0); + auto add_b2 = make_shared(add_b1, iconst0); + auto abs_add_b2 = std::make_shared(add_b2); - auto graph = make_shared(abs_add_a3, abs_add_b2); + auto graph = make_shared(abs_add_a3, abs_add_b2); - auto f = std::make_shared(ngraph::NodeVector{graph}, ParameterVector{a, b}); + auto f = std::make_shared(ov::NodeVector{graph}, ParameterVector{a, b}); const auto compare_names = [](const std::vector& names) { static std::unordered_set ref_names; @@ -87,3 +146,39 @@ TEST(threading, check_atomic_guard) { } ASSERT_EQ(result, 15); } + +TEST(threading, clone_with_new_inputs) { + auto function = create_complex_function(100); + const auto cloneNodes = [&](const std::shared_ptr& f) { + auto orderedOps = function->get_ordered_ops(); + std::vector> nodes; + for (const auto& op : orderedOps) { + ngraph::OutputVector inputsForShapeInfer; + std::shared_ptr opToShapeInfer; + + const auto inSize = op->get_input_size(); + for (size_t i = 0; i < inSize; i++) { + if (dynamic_cast(op->get_input_node_ptr(i))) { + inputsForShapeInfer.push_back(op->get_input_node_ptr(i)->clone_with_new_inputs(ov::OutputVector{})); + } else { + inputsForShapeInfer.push_back( + std::make_shared(op->get_input_element_type(i), + op->get_input_partial_shape(i))); + } + } + + opToShapeInfer = op->clone_with_new_inputs(inputsForShapeInfer); + nodes.push_back(opToShapeInfer); + } + }; + + const size_t numThreads = 6; + std::vector threads(numThreads); + + for (auto&& thread : threads) + thread = std::thread(cloneNodes, function); + + for (auto&& th : threads) { + th.join(); + } +} diff --git a/ngraph/test/type_info.cpp b/ngraph/test/type_info.cpp index 45b2ae47d89762..ddba89fc5d33c0 100644 --- a/ngraph/test/type_info.cpp +++ b/ngraph/test/type_info.cpp @@ -5,6 +5,8 @@ #include #include "openvino/core/type.hpp" +#include "openvino/opsets/opset.hpp" +#include "openvino/util/common_util.hpp" TEST(type_info, compare_old_type) { ov::DiscreteTypeInfo type1("type1", 0); @@ -47,3 +49,75 @@ TEST(type_info, compare_new_with_old_type) { ov::DiscreteTypeInfo type1_o("type1", 0); ASSERT_TRUE(type1 == type1_o); } + +TEST(type_info, check_hash_value) { + const auto& hash_val = [](const char* name, const char* version_id, uint64_t version) -> size_t { + size_t name_hash = name ? std::hash()(std::string(name)) : 0; + size_t version_hash = std::hash()(version); + size_t version_id_hash = version_id ? std::hash()(std::string(version_id)) : 0; + // don't use parent for hash calculation, it is not a part of type (yet) + return ov::util::hash_combine(std::vector{name_hash, version_hash, version_id_hash}); + }; + ov::DiscreteTypeInfo type("type1", 0, "version1"); + ov::DiscreteTypeInfo type_old("type1", 1); + ov::DiscreteTypeInfo type_with_version("type1", 1, "version1"); + ov::DiscreteTypeInfo type_empty_name("", 0); + ov::DiscreteTypeInfo type_empty_ver("type", 0, ""); + EXPECT_EQ(hash_val(type.name, type.version_id, type.version), type.hash()); + EXPECT_EQ(hash_val(type_old.name, type_old.version_id, type_old.version), type_old.hash()); + EXPECT_EQ(hash_val(type_with_version.name, type_with_version.version_id, type_with_version.version), + type_with_version.hash()); + EXPECT_EQ(hash_val(type_empty_name.name, type_empty_name.version_id, type_empty_name.version), + type_empty_name.hash()); + EXPECT_EQ(hash_val(type_empty_ver.name, type_empty_ver.version_id, type_empty_ver.version), type_empty_ver.hash()); +} + +TEST(type_info, find_in_map) { + std::vector vector_names; + ov::DiscreteTypeInfo a("Mod", 1, "opset1"); + ov::DiscreteTypeInfo b("Prelu", 0, "opset1"); + ov::DiscreteTypeInfo c("Vector", 0); + ov::DiscreteTypeInfo d("Mod", 1, "opset3"); + ov::DiscreteTypeInfo f("Mod", 2); + + std::map test_map; + test_map[a] = 1; + test_map[b] = 1; + test_map[c] = 1; + + const auto& opset = ov::get_opset8(); + // Reserve memory to avoid reallocation and copy of strings + // because type info uses pointers from the original memory + vector_names.reserve(opset.size() * 3); + for (const auto& type : opset.get_types_info()) { + test_map[type] = 2; + std::string name = type.name; + vector_names.emplace_back(name); + ov::DiscreteTypeInfo t(vector_names.rbegin()->c_str(), 1000); + ov::DiscreteTypeInfo t2(vector_names.rbegin()->c_str(), 0); + test_map[t] = 3; + test_map[t2] = 4; + std::string name1 = "a" + name; + vector_names.emplace_back(name1); + ov::DiscreteTypeInfo t3(vector_names.rbegin()->c_str(), 1000); + ov::DiscreteTypeInfo t4(vector_names.rbegin()->c_str(), 0); + test_map[t3] = 5; + test_map[t4] = 6; + std::string name2 = name + "z"; + vector_names.emplace_back(name2); + ov::DiscreteTypeInfo t5(vector_names.rbegin()->c_str(), 1000); + ov::DiscreteTypeInfo t6(vector_names.rbegin()->c_str(), 0); + test_map[t5] = 7; + test_map[t6] = 8; + } + + for (const auto& it : test_map) { + ASSERT_NE(test_map.end(), test_map.find(it.first)); + } + + ASSERT_NE(test_map.end(), test_map.find(a)); + ASSERT_NE(test_map.end(), test_map.find(b)); + ASSERT_NE(test_map.end(), test_map.find(c)); + ASSERT_EQ(test_map.end(), test_map.find(d)); + ASSERT_EQ(test_map.end(), test_map.find(f)); +} diff --git a/ngraph/test/type_prop/gather_nd.cpp b/ngraph/test/type_prop/gather_nd.cpp index e05c23a52b3dc8..ab3ab01d2b8c25 100644 --- a/ngraph/test/type_prop/gather_nd.cpp +++ b/ngraph/test/type_prop/gather_nd.cpp @@ -316,3 +316,135 @@ TEST(type_prop, gather_nd_fail_indices_element_type) { FAIL() << "Deduced type check failed for unexpected reason"; } } + +// ------------------------------ V8 ------------------------------ + +TEST(type_prop, gather_nd_8_slices_from_4d_batch_dims0) { + Shape params_shape{2, 3, 11, 12}; + Shape indices_shape{2, 3, 2}; + Shape out_shape{2, 3, 11, 12}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + auto G5 = make_shared(P, I, 0); + ASSERT_EQ(G5->get_element_type(), element::f32); + ASSERT_EQ(G5->get_shape(), out_shape); +} + +TEST(type_prop, gather_nd_8_scalars_from_4d_batch_dims2) { + Shape params_shape{2, 3, 11, 12}; + Shape indices_shape{2, 3, 2}; + Shape out_shape{2, 3}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + auto G5 = make_shared(P, I, 2); + ASSERT_EQ(G5->get_element_type(), element::f32); + ASSERT_EQ(G5->get_shape(), out_shape); +} + +TEST(type_prop, gather_nd_8_slices_from_5d_batch_dims2) { + Shape params_shape{7, 5, 11, 12, 32}; + Shape indices_shape{7, 5, 3, 1}; + Shape out_shape{7, 5, 3, 12, 32}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + auto G5 = make_shared(P, I, 2); + ASSERT_EQ(G5->get_element_type(), element::f32); + ASSERT_EQ(G5->get_shape(), out_shape); +} + +TEST(type_prop, gather_nd_8_batch_dim2_with_dyn_dim) { + PartialShape params_shape{7, Dimension::dynamic(), 11, 12, 32}; + Shape indices_shape{7, 5, 3, 1}; + Shape out_shape{7, 5, 3, 12, 32}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + auto G5 = make_shared(P, I, 2); + ASSERT_EQ(G5->get_element_type(), element::f32); + ASSERT_EQ(G5->get_shape(), out_shape); +} + +TEST(type_prop, gather_nd_8_batch_dim2_with_dyn_dim2) { + PartialShape params_shape{7, Dimension::dynamic(), Dimension::dynamic(), 12, 32}; + Shape indices_shape{7, 5, 3, 1}; + Shape out_shape{7, 5, 3, 12, 32}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + auto G5 = make_shared(P, I, 2); + ASSERT_EQ(G5->get_element_type(), element::f32); + ASSERT_EQ(G5->get_shape(), out_shape); +} + +TEST(type_prop, gather_nd_8_batch_dim2_with_dyn_dim3) { + PartialShape params_shape{7, Dimension::dynamic(), Dimension::dynamic(), 12, Dimension::dynamic()}; + Shape indices_shape{7, 5, 3, 1}; + PartialShape out_shape{7, 5, 3, 12, Dimension::dynamic()}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + auto G5 = make_shared(P, I, 2); + ASSERT_EQ(G5->get_element_type(), element::f32); + ASSERT_TRUE(G5->get_output_partial_shape(0).same_scheme(out_shape)); +} + +TEST(type_prop, gather_nd_8_batch_dim0_with_dyn_ind_dim) { + PartialShape params_shape{7, Dimension::dynamic(), Dimension::dynamic(), 12, Dimension::dynamic()}; + PartialShape indices_shape{7, 5, 3, Dimension::dynamic()}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + auto G5 = make_shared(P, I, 0); + ASSERT_EQ(G5->get_element_type(), element::f32); + ASSERT_TRUE(G5->get_output_partial_shape(0).same_scheme(PartialShape::dynamic())); +} + +TEST(type_prop, gather_nd_8_fail_batch_dims_greater_indices_rank) { + Shape params_shape{2, 3, 4, 5}; + Shape indices_shape{2, 1}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + + try { + auto G5 = make_shared(P, I, 3); + // Should have thrown, so fail if it didn't + FAIL() << "Incorrect indices rank"; + } catch (const NodeValidationFailure& error) { + EXPECT_HAS_SUBSTRING(error.what(), + std::string("Number of batch dimensions must not exceed a rank of indices.")); + } catch (...) { + FAIL() << "Deduced type check failed for unexpected reason"; + } +} + +TEST(type_prop, gather_nd_8_fail_unequal_batch_dims) { + Shape params_shape{2, 3, 4, 5}; + Shape indices_shape{2, 1, 4}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + + try { + auto G5 = make_shared(P, I, 2); + // Should have thrown, so fail if it didn't + FAIL() << "Incorrect indices rank"; + } catch (const NodeValidationFailure& error) { + EXPECT_HAS_SUBSTRING(error.what(), std::string("Batch dimensions of data and indices must be the same.")); + } catch (...) { + FAIL() << "Deduced type check failed for unexpected reason"; + } +} + +TEST(type_prop, gather_nd_8_fail_indices_tuple_greater_data_rank_batch_dims2) { + Shape params_shape{2, 1, 4, 5}; + Shape indices_shape{2, 1, 5, 3}; + auto P = make_shared(element::f32, params_shape); + auto I = make_shared(element::i32, indices_shape); + + try { + auto G5 = make_shared(P, I, 2); + // Should have thrown, so fail if it didn't + FAIL() << "Incorrect indices rank"; + } catch (const NodeValidationFailure& error) { + EXPECT_HAS_SUBSTRING(error.what(), + std::string("Length of a tuple with indices must not exceed a rank of " + "data tensor excluding batch dimensions.")); + } catch (...) { + FAIL() << "Deduced type check failed for unexpected reason"; + } +} diff --git a/ngraph/test/type_prop/lstm_sequence.cpp b/ngraph/test/type_prop/lstm_sequence.cpp index 320268864a8c69..c815f7cdfd1815 100644 --- a/ngraph/test/type_prop/lstm_sequence.cpp +++ b/ngraph/test/type_prop/lstm_sequence.cpp @@ -324,3 +324,22 @@ TEST(type_prop, lstm_sequence_invalid_input_dynamic_rank) { EXPECT_EQ(check_dynamic_lstm(lstm_sequence), true); } } + +TEST(type_prop, lstm_sequence_invalid_input_direction) { + recurrent_sequence_parameters param; + + param.batch_size = 24; + param.num_directions = 3; + param.seq_length = 12; + param.input_size = 8; + param.hidden_size = 256; + param.et = element::f32; + + auto lstm_sequence = lstm_seq_tensor_initialization(param); + try { + lstm_sequence->validate_and_infer_types(); + } catch (const NodeValidationFailure& error) { + EXPECT_HAS_SUBSTRING(error.what(), + std::string("Parameter direction must be Forward or Reverse or Bidirectional")); + } +} diff --git a/ngraph/test/util/test_tools.hpp b/ngraph/test/util/test_tools.hpp index 1a3dc91ad0d959..f559fe3c48f75b 100644 --- a/ngraph/test/util/test_tools.hpp +++ b/ngraph/test/util/test_tools.hpp @@ -55,3 +55,12 @@ std::vector read_binary_file(const std::string& path) { inputs_fs.read(reinterpret_cast(file_content.data()), size); return file_content; } + +template +std::vector gen_range(const size_t elements, const T start = T{0}) { + std::vector range; + range.resize(elements); + std::iota(range.begin(), range.end(), start); + + return range; +} diff --git a/ngraph/test/visitors/op/ctc_greedy_decoder.cpp b/ngraph/test/visitors/op/ctc_greedy_decoder.cpp new file mode 100644 index 00000000000000..4c1bc7fd9750ad --- /dev/null +++ b/ngraph/test/visitors/op/ctc_greedy_decoder.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/opsets/opset1.hpp" +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(attributes, ctc_greedy_decoder_op) { + NodeBuilder::get_ops().register_factory(); + bool m_ctc_merge_repeated = false; + auto data = make_shared(element::f32, Shape{3, 1, 3}); + auto masks = make_shared(element::i32, Shape{3, 1}); + auto decoder = make_shared(data, masks, m_ctc_merge_repeated); + + NodeBuilder builder(decoder); + auto g_decoder = ov::as_type_ptr(builder.create()); + + EXPECT_EQ(g_decoder->get_ctc_merge_repeated(), decoder->get_ctc_merge_repeated()); +} diff --git a/ngraph/test/visitors/op/ctc_greedy_decoder_seq_len.cpp b/ngraph/test/visitors/op/ctc_greedy_decoder_seq_len.cpp new file mode 100644 index 00000000000000..b4536a93fd4115 --- /dev/null +++ b/ngraph/test/visitors/op/ctc_greedy_decoder_seq_len.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/opsets/opset1.hpp" +#include "ngraph/opsets/opset6.hpp" +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(attributes, ctc_greedy_decoder_seq_len_op) { + NodeBuilder::get_ops().register_factory(); + bool merge_repeated = false; + auto data = make_shared(element::f32, Shape{1, 3, 3}); + auto seq_len = make_shared(element::i32, Shape{1}); + auto blank_index = op::Constant::create(element::i32, Shape{}, {2}); + auto decoder = make_shared(data, seq_len, blank_index, merge_repeated); + + NodeBuilder builder(decoder); + auto g_decoder = ov::as_type_ptr(builder.create()); + + EXPECT_EQ(g_decoder->get_merge_repeated(), decoder->get_merge_repeated()); +} diff --git a/ngraph/test/visitors/op/embedding_segments_sum.cpp b/ngraph/test/visitors/op/embedding_segments_sum.cpp new file mode 100644 index 00000000000000..df1a0ed704664f --- /dev/null +++ b/ngraph/test/visitors/op/embedding_segments_sum.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset3.hpp" +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(visitor_without_attribute, embedding_segments_sum_op) { + NodeBuilder::get_ops().register_factory(); + auto emb_table = make_shared(element::f32, Shape{5, 2, 3}); + + auto indices = make_shared(element::i64, Shape{4}); + auto segment_ids = make_shared(element::i64, Shape{4}); + auto num_segments = make_shared(element::i64, Shape{}); + auto per_sample_weights = make_shared(element::f32, Shape{4}); + auto default_index = make_shared(element::i64, Shape{}); + + auto ess = make_shared(emb_table, + indices, + segment_ids, + num_segments, + default_index, + per_sample_weights); + NodeBuilder builder(ess); + + const auto expected_attr_count = 0; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); +} diff --git a/ngraph/test/visitors/op/embeddingbag_offsetssum.cpp b/ngraph/test/visitors/op/embeddingbag_offsetssum.cpp new file mode 100644 index 00000000000000..f2b60a51b09701 --- /dev/null +++ b/ngraph/test/visitors/op/embeddingbag_offsetssum.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset3.hpp" +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(visitor_without_attribute, embedding_bag_offsets_sum_op) { + NodeBuilder::get_ops().register_factory(); + auto emb_table = make_shared(element::f32, Shape{5, 2, 3}); + + auto indices = make_shared(element::i64, Shape{4}); + auto offsets = make_shared(element::i64, Shape{4}); + auto default_index = make_shared(element::i64, Shape{}); + auto per_sample_weights = make_shared(element::f32, Shape{4}); + + auto ebos = + make_shared(emb_table, indices, offsets, default_index, per_sample_weights); + NodeBuilder builder(ebos); + + const auto expected_attr_count = 0; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); +} diff --git a/ngraph/test/visitors/op/embeddingbag_packedsum.cpp b/ngraph/test/visitors/op/embeddingbag_packedsum.cpp new file mode 100644 index 00000000000000..b74da5949a20b6 --- /dev/null +++ b/ngraph/test/visitors/op/embeddingbag_packedsum.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset3.hpp" +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(visitor_without_attribute, embedding_bag_packed_sum_op) { + NodeBuilder::get_ops().register_factory(); + auto emb_table = make_shared(element::f32, Shape{5, 2}); + auto indices = make_shared(element::i64, Shape{3, 4}); + auto per_sample_weights = make_shared(element::f32, Shape{3, 4}); + + auto ebos = make_shared(emb_table, indices, per_sample_weights); + NodeBuilder builder(ebos); + + const auto expected_attr_count = 0; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); +} diff --git a/ngraph/test/visitors/op/experimental_detectron_topkrois.cpp b/ngraph/test/visitors/op/experimental_detectron_topkrois.cpp new file mode 100644 index 00000000000000..8f77ffed7416cf --- /dev/null +++ b/ngraph/test/visitors/op/experimental_detectron_topkrois.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/opsets/opset1.hpp" +#include "ngraph/opsets/opset6.hpp" +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; +using ngraph::test::ValueMap; + +TEST(attributes, experimental_detectron_topkrois_op) { + NodeBuilder::get_ops().register_factory(); + size_t num_rois = 1; + auto input_rois = std::make_shared(element::f32, Shape{2, 4}); + auto input_probs = std::make_shared(element::f32, Shape{2}); + auto topkrois = std::make_shared(input_rois, input_probs, num_rois); + + NodeBuilder builder(topkrois); + auto g_topkrois = ov::as_type_ptr(builder.create()); + + EXPECT_EQ(g_topkrois->get_max_rois(), topkrois->get_max_rois()); +} diff --git a/ngraph/test/visitors/op/gather_nd.cpp b/ngraph/test/visitors/op/gather_nd.cpp index 6195a2e14e434c..5bfba312e0c78e 100644 --- a/ngraph/test/visitors/op/gather_nd.cpp +++ b/ngraph/test/visitors/op/gather_nd.cpp @@ -6,6 +6,7 @@ #include "ngraph/ngraph.hpp" #include "ngraph/opsets/opset1.hpp" #include "ngraph/opsets/opset5.hpp" +#include "ngraph/opsets/opset8.hpp" #include "util/visitor.hpp" using namespace std; @@ -13,7 +14,7 @@ using namespace ngraph; using ngraph::test::NodeBuilder; using ngraph::test::ValueMap; -TEST(attributes, gather_nd_op) { +TEST(attributes, gather_nd_v5_op) { NodeBuilder::get_ops().register_factory(); int batch_dims = 1; auto P = make_shared(element::f32, Shape{2, 3, 4}); @@ -25,3 +26,16 @@ TEST(attributes, gather_nd_op) { EXPECT_EQ(g_G->get_batch_dims(), G->get_batch_dims()); } + +TEST(attributes, gather_nd_v8_op) { + NodeBuilder::get_ops().register_factory(); + int batch_dims = 1; + auto P = make_shared(element::f32, Shape{2, 3, 4}); + auto I = make_shared(element::i32, Shape{2, 1}); + auto G = make_shared(P, I, batch_dims); + + NodeBuilder builder(G); + auto g_G = ov::as_type_ptr(builder.create()); + + EXPECT_EQ(g_G->get_batch_dims(), G->get_batch_dims()); +} diff --git a/ngraph/test/visitors/op/roll.cpp b/ngraph/test/visitors/op/roll.cpp new file mode 100644 index 00000000000000..af2a043bbd9aed --- /dev/null +++ b/ngraph/test/visitors/op/roll.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "gtest/gtest.h" +#include "ngraph/ngraph.hpp" +#include "ngraph/op/util/attr_types.hpp" +#include "ngraph/opsets/opset7.hpp" +#include "util/visitor.hpp" + +using namespace std; +using namespace ngraph; +using ngraph::test::NodeBuilder; + +TEST(attributes, roll_op) { + NodeBuilder::get_ops().register_factory(); + const auto A = make_shared(element::f32, Shape{4, 3}); + const auto B = make_shared(element::i32, Shape{3}); + const auto C = make_shared(element::i32, Shape{3}); + + const auto roll = make_shared(A, B, C); + NodeBuilder builder(roll); + + const auto expected_attr_count = 0; + EXPECT_EQ(builder.get_value_map_size(), expected_attr_count); +} diff --git a/openvino/conditional_compilation/CMakeLists.txt b/openvino/conditional_compilation/CMakeLists.txt index 6c786d401a28a7..70fb4484e7692f 100644 --- a/openvino/conditional_compilation/CMakeLists.txt +++ b/openvino/conditional_compilation/CMakeLists.txt @@ -10,7 +10,8 @@ add_library(openvino::conditional_compilation ALIAS ${TARGET_NAME}) target_link_libraries(${TARGET_NAME} INTERFACE openvino::itt) -target_include_directories(${TARGET_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(${TARGET_NAME} INTERFACE + $) if(SELECTIVE_BUILD STREQUAL "COLLECT") target_compile_definitions(${TARGET_NAME} INTERFACE SELECTIVE_BUILD_ANALYZER) @@ -45,5 +46,7 @@ elseif(SELECTIVE_BUILD STREQUAL "ON") ov_force_include(${TARGET_NAME} INTERFACE ${GENERATED_HEADER}) endif() +ov_install_static_lib(${TARGET_NAME} ngraph) + file(GLOB_RECURSE hdrs ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp) add_cpplint_target(${TARGET_NAME}_cpplint FOR_SOURCES ${hdrs}) diff --git a/openvino/itt/CMakeLists.txt b/openvino/itt/CMakeLists.txt index d45b9857ada43a..fbeab9f3e0d2eb 100644 --- a/openvino/itt/CMakeLists.txt +++ b/openvino/itt/CMakeLists.txt @@ -30,6 +30,9 @@ if (CMAKE_COMPILER_IS_GNUCXX) target_compile_options(${TARGET_NAME} PRIVATE -Wall) endif() -target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(${TARGET_NAME} PUBLIC + $) + +ov_install_static_lib(${TARGET_NAME} openvino_common) add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME}) diff --git a/openvino/pp/CMakeLists.txt b/openvino/pp/CMakeLists.txt index 9583171dcbce60..e2060db6b3fae3 100644 --- a/openvino/pp/CMakeLists.txt +++ b/openvino/pp/CMakeLists.txt @@ -8,4 +8,7 @@ add_library(${TARGET_NAME} INTERFACE) add_library(openvino::pp ALIAS ${TARGET_NAME}) -target_include_directories(${TARGET_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(${TARGET_NAME} INTERFACE + $) + +ov_install_static_lib(${TARGET_NAME} ngraph) diff --git a/openvino/util/CMakeLists.txt b/openvino/util/CMakeLists.txt index 54c9082810c67e..547e77783ec59e 100644 --- a/openvino/util/CMakeLists.txt +++ b/openvino/util/CMakeLists.txt @@ -33,7 +33,10 @@ add_library(${TARGET_NAME} STATIC ${LIBRARY_SRC} ${PUBLIC_HEADERS}) add_library(openvino::util ALIAS ${TARGET_NAME}) target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_DL_LIBS}) -target_include_directories(${TARGET_NAME} PUBLIC ${UTIL_INCLUDE_DIR}) +target_include_directories(${TARGET_NAME} PUBLIC + $) + +ov_install_static_lib(${TARGET_NAME} ngraph) add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) ov_ncc_naming_style(FOR_TARGET ${TARGET_NAME} diff --git a/openvino/util/include/openvino/util/common_util.hpp b/openvino/util/include/openvino/util/common_util.hpp index 6c519f06611b13..60ee9e6e2a181d 100644 --- a/openvino/util/include/openvino/util/common_util.hpp +++ b/openvino/util/include/openvino/util/common_util.hpp @@ -37,6 +37,8 @@ std::string to_lower(const std::string& s); std::string to_upper(const std::string& s); +size_t hash_combine(const std::vector& list); + /** * @brief trim from start (in place) * @param s - string to trim diff --git a/openvino/util/src/common_util.cpp b/openvino/util/src/common_util.cpp index b3aba13d41f9fb..82872c486f1040 100644 --- a/openvino/util/src/common_util.cpp +++ b/openvino/util/src/common_util.cpp @@ -40,3 +40,11 @@ std::vector ov::util::split(const std::string& src, char delimiter, } return rc; } + +size_t ov::util::hash_combine(const std::vector& list) { + size_t seed = 0; + for (size_t v : list) { + seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } + return seed; +} diff --git a/openvino/util/src/file_util.cpp b/openvino/util/src/file_util.cpp index 9b0bf1a553f02b..7732fcebe31115 100644 --- a/openvino/util/src/file_util.cpp +++ b/openvino/util/src/file_util.cpp @@ -328,7 +328,7 @@ static std::string get_ov_library_path_a() { #elif defined(__APPLE__) || defined(__linux__) Dl_info info; dladdr(reinterpret_cast(ov::util::get_ov_lib_path), &info); - std::string result = get_path_name(std::string(info.dli_fname)).c_str(); + std::string result = get_path_name(ov::util::get_absolute_file_path(info.dli_fname)).c_str(); if (!ov::util::ends_with(result, "/lib") && !ov::util::ends_with(result, "/lib/")) result = ov::util::path_join({result, "lib"}); return result; diff --git a/runtime/bindings/python/CMakeLists.txt b/runtime/bindings/python/CMakeLists.txt index c3e3786579b19c..5cf2653ff3baa4 100644 --- a/runtime/bindings/python/CMakeLists.txt +++ b/runtime/bindings/python/CMakeLists.txt @@ -6,6 +6,10 @@ cmake_minimum_required (VERSION 3.13) project(OpenVINOPython DESCRIPTION "OpenVINO Runtime Python bindings") +if(NOT DEFINED OpenVINO_SOURCE_DIR) + find_package(InferenceEngineDeveloperPackage REQUIRED) +endif() + add_subdirectory(thirdparty/pybind11 EXCLUDE_FROM_ALL) set(LIBRARY_OUTPUT_DIRECTORY_BIN ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) @@ -24,3 +28,7 @@ if(NGRAPH_UNIT_TEST_ENABLE) add_subdirectory(tests/mock/pyngraph_fe_mock_api) add_dependencies(_pyngraph pybind_mock_frontend) endif() + +if(InferenceEngineDeveloperPackage_FOUND) + ie_cpack(${IE_CPACK_COMPONENTS_ALL}) +endif() diff --git a/runtime/bindings/python/setup.py b/runtime/bindings/python/setup.py index 6a4dd6268b335b..83c84174e6e1bf 100644 --- a/runtime/bindings/python/setup.py +++ b/runtime/bindings/python/setup.py @@ -33,7 +33,6 @@ "ngraph.opset5", "ngraph.opset6", "ngraph.opset7", - "ngraph.opset8", "ngraph.utils", "ngraph.impl", "ngraph.impl.op", @@ -41,6 +40,8 @@ "ngraph.impl.passes", "ngraph.frontend", "openvino", + # TODO: change the module name according to the description in 69196 + "openvino.offline_transformations_pybind", "openvino.opset1", "openvino.opset2", "openvino.opset3", @@ -168,13 +169,13 @@ def build_cmake(self, extension: Extension): bin_dir = os.path.join(OPENVINO_ROOT_DIR, "bin") if os.environ.get("OpenVINO_DIR") is not None: root_dir = PYTHON_API_ROOT_DIR - bin_dir = build_dir self.announce("Configuring cmake project", level=3) ext_args = self.cmake_args.split() if self.cmake_args else [] + ov_build_dir = os.path.join(OPENVINO_ROOT_DIR, "build") self.spawn(["cmake", "-S" + root_dir, "-B" + self.build_temp, f"-DCMAKE_BUILD_TYPE={self.config}", - f"-DInferenceEngine_DIR={os.path.join(OPENVINO_ROOT_DIR, 'build')}", + f"-DInferenceEngineDeveloperPackage_DIR={ov_build_dir}", "-DENABLE_PYTHON=ON", "-DNGRAPH_ONNX_FRONTEND_ENABLE=ON"] + ext_args) diff --git a/runtime/bindings/python/src/compatibility/ngraph/__init__.py b/runtime/bindings/python/src/compatibility/ngraph/__init__.py index 8b12a3c7ff9d82..a19e06c7a1a486 100644 --- a/runtime/bindings/python/src/compatibility/ngraph/__init__.py +++ b/runtime/bindings/python/src/compatibility/ngraph/__init__.py @@ -27,164 +27,159 @@ from ngraph.helpers import function_from_cnn from ngraph.helpers import function_to_cnn from ngraph.helpers import partial_shape_from_data -from ngraph.opset8 import absolute -from ngraph.opset8 import absolute as abs -from ngraph.opset8 import acos -from ngraph.opset8 import acosh -from ngraph.opset8 import adaptive_avg_pool -from ngraph.opset8 import adaptive_max_pool -from ngraph.opset8 import add -from ngraph.opset8 import asin -from ngraph.opset8 import asinh -from ngraph.opset8 import assign -from ngraph.opset8 import atan -from ngraph.opset8 import atanh -from ngraph.opset8 import avg_pool -from ngraph.opset8 import batch_norm_inference -from ngraph.opset8 import batch_to_space -from ngraph.opset8 import binary_convolution -from ngraph.opset8 import broadcast -from ngraph.opset8 import bucketize -from ngraph.opset8 import ceiling -from ngraph.opset8 import ceiling as ceil -from ngraph.opset8 import clamp -from ngraph.opset8 import concat -from ngraph.opset8 import constant -from ngraph.opset8 import convert -from ngraph.opset8 import convert_like -from ngraph.opset8 import convolution -from ngraph.opset8 import convolution_backprop_data -from ngraph.opset8 import cos -from ngraph.opset8 import cosh -from ngraph.opset8 import ctc_greedy_decoder -from ngraph.opset8 import ctc_greedy_decoder_seq_len -from ngraph.opset8 import ctc_loss -from ngraph.opset8 import cum_sum -from ngraph.opset8 import cum_sum as cumsum -from ngraph.opset8 import deformable_convolution -from ngraph.opset8 import deformable_psroi_pooling -from ngraph.opset8 import depth_to_space -from ngraph.opset8 import detection_output -from ngraph.opset8 import dft -from ngraph.opset8 import divide -from ngraph.opset8 import einsum -from ngraph.opset8 import elu -from ngraph.opset8 import embedding_bag_offsets_sum -from ngraph.opset8 import embedding_bag_packed_sum -from ngraph.opset8 import embedding_segments_sum -from ngraph.opset8 import extract_image_patches -from ngraph.opset8 import equal -from ngraph.opset8 import erf -from ngraph.opset8 import exp -from ngraph.opset8 import fake_quantize -from ngraph.opset8 import floor -from ngraph.opset8 import floor_mod -from ngraph.opset8 import gather -from ngraph.opset8 import gather_elements -from ngraph.opset8 import gather_nd -from ngraph.opset8 import gather_tree -from ngraph.opset8 import gelu -from ngraph.opset8 import greater -from ngraph.opset8 import greater_equal -from ngraph.opset8 import grn -from ngraph.opset8 import group_convolution -from ngraph.opset8 import group_convolution_backprop_data -from ngraph.opset8 import gru_cell -from ngraph.opset8 import gru_sequence -from ngraph.opset8 import hard_sigmoid -from ngraph.opset8 import hsigmoid -from ngraph.opset8 import hswish -from ngraph.opset8 import idft -from ngraph.opset8 import interpolate -from ngraph.opset8 import less -from ngraph.opset8 import less_equal -from ngraph.opset8 import log -from ngraph.opset8 import logical_and -from ngraph.opset8 import logical_not -from ngraph.opset8 import logical_or -from ngraph.opset8 import logical_xor -from ngraph.opset8 import log_softmax -from ngraph.opset8 import loop -from ngraph.opset8 import lrn -from ngraph.opset8 import lstm_cell -from ngraph.opset8 import lstm_sequence -from ngraph.opset8 import matmul -from ngraph.opset8 import matrix_nms -from ngraph.opset8 import max_pool -from ngraph.opset8 import maximum -from ngraph.opset8 import minimum -from ngraph.opset8 import mish -from ngraph.opset8 import mod -from ngraph.opset8 import multiclass_nms -from ngraph.opset8 import multiply -from ngraph.opset8 import mvn -from ngraph.opset8 import negative -from ngraph.opset8 import non_max_suppression -from ngraph.opset8 import non_zero -from ngraph.opset8 import normalize_l2 -from ngraph.opset8 import not_equal -from ngraph.opset8 import one_hot -from ngraph.opset8 import pad -from ngraph.opset8 import parameter -from ngraph.opset8 import power -from ngraph.opset8 import prelu -from ngraph.opset8 import prior_box -from ngraph.opset8 import prior_box_clustered -from ngraph.opset8 import psroi_pooling -from ngraph.opset8 import proposal -from ngraph.opset8 import random_uniform -from ngraph.opset8 import range -from ngraph.opset8 import read_value -from ngraph.opset8 import reduce_l1 -from ngraph.opset8 import reduce_l2 -from ngraph.opset8 import reduce_logical_and -from ngraph.opset8 import reduce_logical_or -from ngraph.opset8 import reduce_max -from ngraph.opset8 import reduce_mean -from ngraph.opset8 import reduce_min -from ngraph.opset8 import reduce_prod -from ngraph.opset8 import reduce_sum -from ngraph.opset8 import region_yolo -from ngraph.opset8 import reorg_yolo -from ngraph.opset8 import relu -from ngraph.opset8 import reshape -from ngraph.opset8 import result -from ngraph.opset8 import reverse_sequence -from ngraph.opset8 import rnn_cell -from ngraph.opset8 import rnn_sequence -from ngraph.opset8 import roi_align -from ngraph.opset8 import roi_pooling -from ngraph.opset8 import roll -from ngraph.opset8 import round -from ngraph.opset8 import scatter_elements_update -from ngraph.opset8 import scatter_update -from ngraph.opset8 import select -from ngraph.opset8 import selu -from ngraph.opset8 import shape_of -from ngraph.opset8 import shuffle_channels -from ngraph.opset8 import sigmoid -from ngraph.opset8 import sign -from ngraph.opset8 import sin -from ngraph.opset8 import sinh -from ngraph.opset8 import softmax -from ngraph.opset8 import softplus -from ngraph.opset8 import space_to_batch -from ngraph.opset8 import space_to_depth -from ngraph.opset8 import split -from ngraph.opset8 import sqrt -from ngraph.opset8 import squared_difference -from ngraph.opset8 import squeeze -from ngraph.opset8 import strided_slice -from ngraph.opset8 import subtract -from ngraph.opset8 import swish -from ngraph.opset8 import tan -from ngraph.opset8 import tanh -from ngraph.opset8 import tensor_iterator -from ngraph.opset8 import tile -from ngraph.opset8 import topk -from ngraph.opset8 import transpose -from ngraph.opset8 import unsqueeze -from ngraph.opset8 import variadic_split +from ngraph.opset7 import absolute +from ngraph.opset7 import absolute as abs +from ngraph.opset7 import acos +from ngraph.opset7 import acosh +from ngraph.opset7 import add +from ngraph.opset7 import asin +from ngraph.opset7 import asinh +from ngraph.opset7 import assign +from ngraph.opset7 import atan +from ngraph.opset7 import atanh +from ngraph.opset7 import avg_pool +from ngraph.opset7 import batch_norm_inference +from ngraph.opset7 import batch_to_space +from ngraph.opset7 import binary_convolution +from ngraph.opset7 import broadcast +from ngraph.opset7 import bucketize +from ngraph.opset7 import ceiling +from ngraph.opset7 import ceiling as ceil +from ngraph.opset7 import clamp +from ngraph.opset7 import concat +from ngraph.opset7 import constant +from ngraph.opset7 import convert +from ngraph.opset7 import convert_like +from ngraph.opset7 import convolution +from ngraph.opset7 import convolution_backprop_data +from ngraph.opset7 import cos +from ngraph.opset7 import cosh +from ngraph.opset7 import ctc_greedy_decoder +from ngraph.opset7 import ctc_greedy_decoder_seq_len +from ngraph.opset7 import ctc_loss +from ngraph.opset7 import cum_sum +from ngraph.opset7 import cum_sum as cumsum +from ngraph.opset7 import deformable_convolution +from ngraph.opset7 import deformable_psroi_pooling +from ngraph.opset7 import depth_to_space +from ngraph.opset7 import detection_output +from ngraph.opset7 import dft +from ngraph.opset7 import divide +from ngraph.opset7 import einsum +from ngraph.opset7 import elu +from ngraph.opset7 import embedding_bag_offsets_sum +from ngraph.opset7 import embedding_bag_packed_sum +from ngraph.opset7 import embedding_segments_sum +from ngraph.opset7 import extract_image_patches +from ngraph.opset7 import equal +from ngraph.opset7 import erf +from ngraph.opset7 import exp +from ngraph.opset7 import fake_quantize +from ngraph.opset7 import floor +from ngraph.opset7 import floor_mod +from ngraph.opset7 import gather +from ngraph.opset7 import gather_elements +from ngraph.opset7 import gather_nd +from ngraph.opset7 import gather_tree +from ngraph.opset7 import gelu +from ngraph.opset7 import greater +from ngraph.opset7 import greater_equal +from ngraph.opset7 import grn +from ngraph.opset7 import group_convolution +from ngraph.opset7 import group_convolution_backprop_data +from ngraph.opset7 import gru_cell +from ngraph.opset7 import gru_sequence +from ngraph.opset7 import hard_sigmoid +from ngraph.opset7 import hsigmoid +from ngraph.opset7 import hswish +from ngraph.opset7 import idft +from ngraph.opset7 import interpolate +from ngraph.opset7 import less +from ngraph.opset7 import less_equal +from ngraph.opset7 import log +from ngraph.opset7 import logical_and +from ngraph.opset7 import logical_not +from ngraph.opset7 import logical_or +from ngraph.opset7 import logical_xor +from ngraph.opset7 import log_softmax +from ngraph.opset7 import loop +from ngraph.opset7 import lrn +from ngraph.opset7 import lstm_cell +from ngraph.opset7 import lstm_sequence +from ngraph.opset7 import matmul +from ngraph.opset7 import max_pool +from ngraph.opset7 import maximum +from ngraph.opset7 import minimum +from ngraph.opset7 import mish +from ngraph.opset7 import mod +from ngraph.opset7 import multiply +from ngraph.opset7 import mvn +from ngraph.opset7 import negative +from ngraph.opset7 import non_max_suppression +from ngraph.opset7 import non_zero +from ngraph.opset7 import normalize_l2 +from ngraph.opset7 import not_equal +from ngraph.opset7 import one_hot +from ngraph.opset7 import pad +from ngraph.opset7 import parameter +from ngraph.opset7 import power +from ngraph.opset7 import prelu +from ngraph.opset7 import prior_box +from ngraph.opset7 import prior_box_clustered +from ngraph.opset7 import psroi_pooling +from ngraph.opset7 import proposal +from ngraph.opset7 import range +from ngraph.opset7 import read_value +from ngraph.opset7 import reduce_l1 +from ngraph.opset7 import reduce_l2 +from ngraph.opset7 import reduce_logical_and +from ngraph.opset7 import reduce_logical_or +from ngraph.opset7 import reduce_max +from ngraph.opset7 import reduce_mean +from ngraph.opset7 import reduce_min +from ngraph.opset7 import reduce_prod +from ngraph.opset7 import reduce_sum +from ngraph.opset7 import region_yolo +from ngraph.opset7 import reorg_yolo +from ngraph.opset7 import relu +from ngraph.opset7 import reshape +from ngraph.opset7 import result +from ngraph.opset7 import reverse_sequence +from ngraph.opset7 import rnn_cell +from ngraph.opset7 import rnn_sequence +from ngraph.opset7 import roi_align +from ngraph.opset7 import roi_pooling +from ngraph.opset7 import roll +from ngraph.opset7 import round +from ngraph.opset7 import scatter_elements_update +from ngraph.opset7 import scatter_update +from ngraph.opset7 import select +from ngraph.opset7 import selu +from ngraph.opset7 import shape_of +from ngraph.opset7 import shuffle_channels +from ngraph.opset7 import sigmoid +from ngraph.opset7 import sign +from ngraph.opset7 import sin +from ngraph.opset7 import sinh +from ngraph.opset7 import softmax +from ngraph.opset7 import softplus +from ngraph.opset7 import space_to_batch +from ngraph.opset7 import space_to_depth +from ngraph.opset7 import split +from ngraph.opset7 import sqrt +from ngraph.opset7 import squared_difference +from ngraph.opset7 import squeeze +from ngraph.opset7 import strided_slice +from ngraph.opset7 import subtract +from ngraph.opset7 import swish +from ngraph.opset7 import tan +from ngraph.opset7 import tanh +from ngraph.opset7 import tensor_iterator +from ngraph.opset7 import tile +from ngraph.opset7 import topk +from ngraph.opset7 import transpose +from ngraph.opset7 import unsqueeze +from ngraph.opset7 import variadic_split # Extend Node class to support binary operators diff --git a/runtime/bindings/python/src/compatibility/ngraph/opset8/__init__.py b/runtime/bindings/python/src/compatibility/ngraph/opset8/__init__.py deleted file mode 100644 index f0d0dfdd2dbf64..00000000000000 --- a/runtime/bindings/python/src/compatibility/ngraph/opset8/__init__.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -from ngraph.opset1.ops import absolute -from ngraph.opset1.ops import absolute as abs -from ngraph.opset1.ops import acos -from ngraph.opset4.ops import acosh -from ngraph.opset8.ops import adaptive_avg_pool -from ngraph.opset8.ops import adaptive_max_pool -from ngraph.opset1.ops import add -from ngraph.opset1.ops import asin -from ngraph.opset4.ops import asinh -from ngraph.opset3.ops import assign -from ngraph.opset1.ops import atan -from ngraph.opset4.ops import atanh -from ngraph.opset1.ops import avg_pool -from ngraph.opset5.ops import batch_norm_inference -from ngraph.opset2.ops import batch_to_space -from ngraph.opset1.ops import binary_convolution -from ngraph.opset3.ops import broadcast -from ngraph.opset3.ops import bucketize -from ngraph.opset1.ops import ceiling -from ngraph.opset1.ops import ceiling as ceil -from ngraph.opset1.ops import clamp -from ngraph.opset1.ops import concat -from ngraph.opset1.ops import constant -from ngraph.opset1.ops import convert -from ngraph.opset1.ops import convert_like -from ngraph.opset1.ops import convolution -from ngraph.opset1.ops import convolution_backprop_data -from ngraph.opset1.ops import cos -from ngraph.opset1.ops import cosh -from ngraph.opset1.ops import ctc_greedy_decoder -from ngraph.opset6.ops import ctc_greedy_decoder_seq_len -from ngraph.opset4.ops import ctc_loss -from ngraph.opset3.ops import cum_sum -from ngraph.opset3.ops import cum_sum as cumsum -from ngraph.opset8.ops import deformable_convolution -from ngraph.opset1.ops import deformable_psroi_pooling -from ngraph.opset1.ops import depth_to_space -from ngraph.opset1.ops import detection_output -from ngraph.opset7.ops import dft -from ngraph.opset1.ops import divide -from ngraph.opset7.ops import einsum -from ngraph.opset1.ops import elu -from ngraph.opset3.ops import embedding_bag_offsets_sum -from ngraph.opset3.ops import embedding_bag_packed_sum -from ngraph.opset3.ops import embedding_segments_sum -from ngraph.opset3.ops import extract_image_patches -from ngraph.opset1.ops import equal -from ngraph.opset1.ops import erf -from ngraph.opset1.ops import exp -from ngraph.opset1.ops import fake_quantize -from ngraph.opset1.ops import floor -from ngraph.opset1.ops import floor_mod -from ngraph.opset8.ops import gather -from ngraph.opset6.ops import gather_elements -from ngraph.opset5.ops import gather_nd -from ngraph.opset1.ops import gather_tree -from ngraph.opset7.ops import gelu -from ngraph.opset1.ops import greater -from ngraph.opset1.ops import greater_equal -from ngraph.opset1.ops import grn -from ngraph.opset1.ops import group_convolution -from ngraph.opset1.ops import group_convolution_backprop_data -from ngraph.opset3.ops import gru_cell -from ngraph.opset5.ops import gru_sequence -from ngraph.opset1.ops import hard_sigmoid -from ngraph.opset5.ops import hsigmoid -from ngraph.opset4.ops import hswish -from ngraph.opset7.ops import idft -from ngraph.opset1.ops import interpolate -from ngraph.opset1.ops import less -from ngraph.opset1.ops import less_equal -from ngraph.opset1.ops import log -from ngraph.opset1.ops import logical_and -from ngraph.opset1.ops import logical_not -from ngraph.opset1.ops import logical_or -from ngraph.opset1.ops import logical_xor -from ngraph.opset5.ops import log_softmax -from ngraph.opset5.ops import loop -from ngraph.opset1.ops import lrn -from ngraph.opset4.ops import lstm_cell -from ngraph.opset1.ops import lstm_sequence -from ngraph.opset1.ops import matmul -from ngraph.opset8.ops import matrix_nms -from ngraph.opset8.ops import max_pool -from ngraph.opset1.ops import maximum -from ngraph.opset1.ops import minimum -from ngraph.opset4.ops import mish -from ngraph.opset1.ops import mod -from ngraph.opset8.ops import multiclass_nms -from ngraph.opset1.ops import multiply -from ngraph.opset6.ops import mvn -from ngraph.opset1.ops import negative -from ngraph.opset5.ops import non_max_suppression -from ngraph.opset3.ops import non_zero -from ngraph.opset1.ops import normalize_l2 -from ngraph.opset1.ops import not_equal -from ngraph.opset1.ops import one_hot -from ngraph.opset1.ops import pad -from ngraph.opset1.ops import parameter -from ngraph.opset1.ops import power -from ngraph.opset1.ops import prelu -from ngraph.opset1.ops import prior_box -from ngraph.opset1.ops import prior_box_clustered -from ngraph.opset1.ops import psroi_pooling -from ngraph.opset4.ops import proposal -from ngraph.opset8.ops import random_uniform -from ngraph.opset1.ops import range -from ngraph.opset3.ops import read_value -from ngraph.opset4.ops import reduce_l1 -from ngraph.opset4.ops import reduce_l2 -from ngraph.opset1.ops import reduce_logical_and -from ngraph.opset1.ops import reduce_logical_or -from ngraph.opset1.ops import reduce_max -from ngraph.opset1.ops import reduce_mean -from ngraph.opset1.ops import reduce_min -from ngraph.opset1.ops import reduce_prod -from ngraph.opset1.ops import reduce_sum -from ngraph.opset1.ops import region_yolo -from ngraph.opset2.ops import reorg_yolo -from ngraph.opset1.ops import relu -from ngraph.opset1.ops import reshape -from ngraph.opset1.ops import result -from ngraph.opset1.ops import reverse_sequence -from ngraph.opset3.ops import rnn_cell -from ngraph.opset5.ops import rnn_sequence -from ngraph.opset3.ops import roi_align -from ngraph.opset2.ops import roi_pooling -from ngraph.opset7.ops import roll -from ngraph.opset5.ops import round -from ngraph.opset3.ops import scatter_elements_update -from ngraph.opset3.ops import scatter_update -from ngraph.opset1.ops import select -from ngraph.opset1.ops import selu -from ngraph.opset3.ops import shape_of -from ngraph.opset3.ops import shuffle_channels -from ngraph.opset1.ops import sigmoid -from ngraph.opset1.ops import sign -from ngraph.opset1.ops import sin -from ngraph.opset1.ops import sinh -from ngraph.opset1.ops import softmax -from ngraph.opset4.ops import softplus -from ngraph.opset2.ops import space_to_batch -from ngraph.opset1.ops import space_to_depth -from ngraph.opset1.ops import split -from ngraph.opset1.ops import sqrt -from ngraph.opset1.ops import squared_difference -from ngraph.opset1.ops import squeeze -from ngraph.opset1.ops import strided_slice -from ngraph.opset1.ops import subtract -from ngraph.opset4.ops import swish -from ngraph.opset1.ops import tan -from ngraph.opset1.ops import tanh -from ngraph.opset1.ops import tensor_iterator -from ngraph.opset1.ops import tile -from ngraph.opset3.ops import topk -from ngraph.opset1.ops import transpose -from ngraph.opset1.ops import unsqueeze -from ngraph.opset1.ops import variadic_split diff --git a/runtime/bindings/python/src/compatibility/ngraph/opset8/ops.py b/runtime/bindings/python/src/compatibility/ngraph/opset8/ops.py deleted file mode 100644 index 6c355930b7c021..00000000000000 --- a/runtime/bindings/python/src/compatibility/ngraph/opset8/ops.py +++ /dev/null @@ -1,369 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -"""Factory functions for all ngraph ops.""" -from functools import partial -from typing import Callable, Iterable, List, Optional, Set, Union - -import numpy as np -from ngraph.impl import Node, Shape -from ngraph.impl.op import Constant, Parameter -from ngraph.opset_utils import _get_node_factory -from ngraph.utils.decorators import binary_op, nameable_op, unary_op -from ngraph.utils.input_validation import ( - assert_list_of_ints, - check_valid_attributes, - is_non_negative_value, - is_positive_value, -) -from ngraph.utils.node_factory import NodeFactory -from ngraph.utils.tensor_iterator_types import ( - GraphBody, - TensorIteratorSliceInputDesc, - TensorIteratorMergedInputDesc, - TensorIteratorInvariantInputDesc, - TensorIteratorBodyOutputDesc, - TensorIteratorConcatOutputDesc, -) -from ngraph.utils.types import ( - NodeInput, - NumericData, - NumericType, - ScalarData, - TensorShape, - as_node, - as_nodes, - get_dtype, - get_element_type, - get_element_type_str, - make_constant_node, -) - -_get_node_factory_opset8 = partial(_get_node_factory, "opset8") - - -# -------------------------------------------- ops ------------------------------------------------ - - -@nameable_op -def deformable_convolution( - data: NodeInput, - offsets: NodeInput, - filters: NodeInput, - strides: List[int], - pads_begin: List[int], - pads_end: List[int], - dilations: List[int], - mask: Optional[NodeInput] = None, - auto_pad: str = "EXPLICIT", - group: int = 1, - deformable_group: int = 1, - bilinear_interpolation_pad: bool = False, - name: Optional[str] = None, -) -> Node: - """Return a node which performs deformable convolution operation. - - @param data: The node providing data batch tensor. - @param offsets: The node providing offset tensor. - @param filters: The node providing filters tensor. - @param strides: The distance (in pixels) to slide the filter on the feature map over the axes. - @param pads_begin: The number of pixels to add to the beginning along each axis. - @param pads_end: The number of pixels to add to the end along each axis. - @param dilations: The distance in width and height between elements (weights) in the filter. - @param mask: The node providing modulation scalar (mask) tensor. - @param auto_pad: The type of padding. Range of values: explicit, same_upper, same_lower, valid. - @param group: The number of groups which both output and input should be split into. - @param deformable_group: The number of groups which deformable values and output should be split - into along the channel axis. - @param bilinear_interpolation_pad: The flag that determines the mode of bilinear interpolation - execution. - @param name: The optional new name for output node. - @return New node performing deformable convolution operation. - """ - if mask is None: - inputs = as_nodes(data, offsets, filters) - else: - inputs = as_nodes(data, offsets, filters, mask) - - return _get_node_factory_opset8().create( - "DeformableConvolution", - inputs, - { - "strides": strides, - "pads_begin": pads_begin, - "pads_end": pads_end, - "dilations": dilations, - "auto_pad": auto_pad, - "group": group, - "deformable_group": deformable_group, - "bilinear_interpolation_pad": bilinear_interpolation_pad - }, - ) - - -@nameable_op -def adaptive_avg_pool( - data: NodeInput, - output_shape: NodeInput -) -> Node: - """Return a node which performs AdaptiveAvgPool operation. - - @param data: The list of input nodes - @param output_shape: the shape of spatial dimentions after operation - @return: The new node performing AdaptiveAvgPool operation on the data - """ - inputs = as_nodes(data, output_shape) - return _get_node_factory_opset8().create("AdaptiveAvgPool", inputs) - - -@nameable_op -def adaptive_max_pool( - data: NodeInput, - output_shape: NodeInput, - index_element_type: str = "i64" -) -> Node: - """Return a node which performs AdaptiveMaxPool operation. - - @param data: The list of input nodes - @param output_shape: the shape of spatial dimentions after operation - @param index_element_type: Type of indices output. - @return: The new node performing AdaptiveMaxPool operation on the data - """ - inputs = as_nodes(data, output_shape) - - attributes = { - "index_element_type": index_element_type, - } - - return _get_node_factory_opset8().create("AdaptiveMaxPool", inputs, attributes) - - -@nameable_op -def multiclass_nms( - boxes: NodeInput, - scores: NodeInput, - sort_result_type: str = "none", - sort_result_across_batch: bool = False, - output_type: str = "i64", - iou_threshold: float = 0.0, - score_threshold: float = 0.0, - nms_top_k: int = -1, - keep_top_k: int = -1, - background_class: int = -1, - nms_eta: float = 1.0, - normalized: bool = True -) -> Node: - """Return a node which performs MulticlassNms. - - @param boxes: Tensor with box coordinates. - @param scores: Tensor with box scores. - @param sort_result_type: Specifies order of output elements, possible values: - 'class': sort selected boxes by class id (ascending) - 'score': sort selected boxes by score (descending) - 'none': do not guarantee the order. - @param sort_result_across_batch: Specifies whenever it is necessary to sort selected boxes - across batches or not - @param output_type: Specifies the output tensor type, possible values: - 'i64', 'i32' - @param iou_threshold: Specifies intersection over union threshold - @param score_threshold: Specifies minimum score to consider box for the processing - @param nms_top_k: Specifies maximum number of boxes to be selected per class, -1 meaning - to keep all boxes - @param keep_top_k: Specifies maximum number of boxes to be selected per batch element, -1 - meaning to keep all boxes - @param background_class: Specifies the background class id, -1 meaning to keep all classes - @param nms_eta: Specifies eta parameter for adpative NMS, in close range [0, 1.0] - @param normalized: Specifies whether boxes are normalized or not - @return: The new node which performs MuticlassNms - """ - inputs = as_nodes(boxes, scores) - - attributes = { - "sort_result_type": sort_result_type, - "sort_result_across_batch": sort_result_across_batch, - "output_type": output_type, - "iou_threshold": iou_threshold, - "score_threshold": score_threshold, - "nms_top_k": nms_top_k, - "keep_top_k": keep_top_k, - "background_class": background_class, - "nms_eta": nms_eta, - "normalized": normalized - } - - return _get_node_factory_opset8().create("MulticlassNms", inputs, attributes) - - -@nameable_op -def matrix_nms( - boxes: NodeInput, - scores: NodeInput, - sort_result_type: str = "none", - sort_result_across_batch: bool = False, - output_type: str = "i64", - score_threshold: float = 0.0, - nms_top_k: int = -1, - keep_top_k: int = -1, - background_class: int = -1, - decay_function: str = "linear", - gaussian_sigma: float = 2.0, - post_threshold: float = 0.0, - normalized: bool = True -) -> Node: - """Return a node which performs MatrixNms. - - @param boxes: Tensor with box coordinates. - @param scores: Tensor with box scores. - @param sort_result_type: Specifies order of output elements, possible values: - 'class': sort selected boxes by class id (ascending) - 'score': sort selected boxes by score (descending) - 'none': do not guarantee the order. - @param sort_result_across_batch: Specifies whenever it is necessary to sort selected boxes - across batches or not - @param output_type: Specifies the output tensor type, possible values: - 'i64', 'i32' - @param score_threshold: Specifies minimum score to consider box for the processing - @param nms_top_k: Specifies maximum number of boxes to be selected per class, -1 meaning - to keep all boxes - @param keep_top_k: Specifies maximum number of boxes to be selected per batch element, -1 - meaning to keep all boxes - @param background_class: Specifies the background class id, -1 meaning to keep all classes - @param decay_function: Specifies decay function used to decay scores, possible values: - 'gaussian', 'linear' - @param gaussian_sigma: Specifies gaussian_sigma parameter for gaussian decay_function - @param post_threshold: Specifies threshold to filter out boxes with low confidence score - after decaying - @param normalized: Specifies whether boxes are normalized or not - @return: The new node which performs MatrixNms - """ - inputs = as_nodes(boxes, scores) - - attributes = { - "sort_result_type": sort_result_type, - "sort_result_across_batch": sort_result_across_batch, - "output_type": output_type, - "score_threshold": score_threshold, - "nms_top_k": nms_top_k, - "keep_top_k": keep_top_k, - "background_class": background_class, - "decay_function": decay_function, - "gaussian_sigma": gaussian_sigma, - "post_threshold": post_threshold, - "normalized": normalized - } - - return _get_node_factory_opset8().create("MatrixNms", inputs, attributes) - - -@nameable_op -def gather( - data: NodeInput, - indices: NodeInput, - axis: NodeInput, - batch_dims: Optional[int] = 0, -) -> Node: - """Return a node which performs Gather with support of negative indices. - - @param data: N-D tensor with data for gathering - @param indices: N-D tensor with indices by which data is gathered. Negative indices - indicate reverse indexing from the end - @param axis: axis along which elements are gathered - @param batch_dims: number of batch dimensions - @return: The new node which performs Gather - """ - inputs = as_nodes(data, indices, axis) - attributes = { - "batch_dims": batch_dims - } - return _get_node_factory_opset8().create("Gather", inputs, attributes) - - -@nameable_op -def max_pool( - data: NodeInput, - strides: List[int], - dilations: List[int], - pads_begin: List[int], - pads_end: List[int], - kernel_shape: TensorShape, - rounding_type: str = "floor", - auto_pad: Optional[str] = None, - index_element_type: Optional[str] = "i64", - axis: Optional[int] = 0, - name: Optional[str] = None, -) -> Node: - """Perform max pooling operation and return both values and indices of the selected elements. - - @param data: The node providing input data. - @param strides: The distance (in pixels) to slide the filter on the feature map - over the axes. - @param dilations: The dilation of filter elements(distance between elements). - @param pads_begin: The number of pixels to add at the beginning along each axis. - @param pads_end: The number of pixels to add at the end along each axis. - @param kernel_shape: The pooling operation kernel shape. - @param rounding_type: Determines used rounding schema when computing output shape. - Acceptable values are: ['floor', 'ceil']. Defaults to 'floor'. - @param auto_pad: Determines how the padding is calculated. Acceptable values: - [None, 'same_upper', 'same_lower', 'valid']. Defaults to None. - @param index_element_type: The data type used for the indices output of this operator. - Defaults to i64. - @param axis: The first dimension in the data shape used to determine the maximum - returned index value. The value is the product of all dimensions - starting at the provided axis. Defaults to 0. - @param name: The optional name for the created output node. - - @return The new node performing max pooling operation. - """ - if auto_pad is None: - auto_pad = "explicit" - return _get_node_factory_opset8().create( - "MaxPool", - [as_node(data)], - { - "strides": strides, - "dilations": dilations, - "pads_begin": pads_begin, - "pads_end": pads_end, - "kernel": kernel_shape, - "rounding_type": rounding_type.upper(), - "auto_pad": auto_pad.upper(), - "index_element_type": index_element_type, - "axis": axis, - }, - ) - - -@nameable_op -def random_uniform( - output_shape: NodeInput, - min_val: NodeInput, - max_val: NodeInput, - output_type: str, - global_seed: int = 0, - op_seed: int = 0 -) -> Node: - """Return a node which generates sequence of random values from uniform distribution. - - @param output_shape: Tensor with shape of the output tensor. - @param min_val: Tensor with the lower bound on the range of random values to generate. - @param max_val: Tensor with the upper bound on the range of random values to generate. - @param output_type: Specifies the output tensor type, possible values: - 'i64', 'i32', 'f64', 'f32', 'f16', 'bf16'. - @param global_seed: Specifies global seed value. Required to be a positive integer or 0. - @param op_seed: Specifies operational seed value. Required to be a positive integer or 0. - @return The new node which performs generation of random values from uniform distribution. - """ - inputs = as_nodes(output_shape, min_val, max_val) - - if global_seed < 0: - raise RuntimeError("global_seed should be positive or 0. Got: {}".format(global_seed)) - - if op_seed < 0: - raise RuntimeError("op_seed should be positive or 0. Got: {}".format(op_seed)) - - attributes = { - "output_type": output_type, - "global_seed": global_seed, - "op_seed": op_seed, - } - return _get_node_factory_opset8().create("RandomUniform", inputs, attributes) diff --git a/runtime/bindings/python/src/compatibility/ngraph/utils/node_factory.py b/runtime/bindings/python/src/compatibility/ngraph/utils/node_factory.py index ffb0c3d861ccc8..83cb9e094b0887 100644 --- a/runtime/bindings/python/src/compatibility/ngraph/utils/node_factory.py +++ b/runtime/bindings/python/src/compatibility/ngraph/utils/node_factory.py @@ -12,7 +12,7 @@ from ngraph.exceptions import UserInputError -DEFAULT_OPSET = "opset8" +DEFAULT_OPSET = "opset7" class NodeFactory(object): diff --git a/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend.cpp b/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend.cpp index db3dccfc44b63f..b028a7f3665e9c 100644 --- a/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend.cpp +++ b/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend.cpp @@ -14,15 +14,15 @@ namespace py = pybind11; void regclass_pyngraph_FrontEnd(py::module m) { - py::class_> fem(m, - "FrontEnd", - py::dynamic_attr(), - py::module_local()); + py::class_> fem(m, + "FrontEnd", + py::dynamic_attr(), + py::module_local()); fem.doc() = "ngraph.impl.FrontEnd wraps ngraph::frontend::FrontEnd"; fem.def( "load", - [](ngraph::frontend::FrontEnd& self, const std::string& s) { + [](ov::frontend::FrontEnd& self, const std::string& s) { return self.load(s); }, py::arg("path"), @@ -40,11 +40,12 @@ void regclass_pyngraph_FrontEnd(py::module m) { Loaded input model. )"); - fem.def("convert", - static_cast (ngraph::frontend::FrontEnd::*)( - ngraph::frontend::InputModel::Ptr) const>(&ngraph::frontend::FrontEnd::convert), - py::arg("model"), - R"( + fem.def( + "convert", + static_cast (ov::frontend::FrontEnd::*)(ov::frontend::InputModel::Ptr) const>( + &ov::frontend::FrontEnd::convert), + py::arg("model"), + R"( Completely convert and normalize entire function, throws if it is not possible. Parameters @@ -59,8 +60,8 @@ void regclass_pyngraph_FrontEnd(py::module m) { )"); fem.def("convert", - static_cast) const>( - &ngraph::frontend::FrontEnd::convert), + static_cast) const>( + &ov::frontend::FrontEnd::convert), py::arg("function"), R"( Completely convert the remaining, not converted part of a function. @@ -77,7 +78,7 @@ void regclass_pyngraph_FrontEnd(py::module m) { )"); fem.def("convert_partially", - &ngraph::frontend::FrontEnd::convert_partially, + &ov::frontend::FrontEnd::convert_partially, py::arg("model"), R"( Convert only those parts of the model that can be converted leaving others as-is. @@ -96,7 +97,7 @@ void regclass_pyngraph_FrontEnd(py::module m) { )"); fem.def("decode", - &ngraph::frontend::FrontEnd::decode, + &ov::frontend::FrontEnd::decode, py::arg("model"), R"( Convert operations with one-to-one mapping with decoding nodes. @@ -115,7 +116,7 @@ void regclass_pyngraph_FrontEnd(py::module m) { )"); fem.def("normalize", - &ngraph::frontend::FrontEnd::normalize, + &ov::frontend::FrontEnd::normalize, py::arg("function"), R"( Runs normalization passes on function that was loaded with partial conversion. @@ -127,7 +128,7 @@ void regclass_pyngraph_FrontEnd(py::module m) { )"); fem.def("get_name", - &ngraph::frontend::FrontEnd::get_name, + &ov::frontend::FrontEnd::get_name, R"( Gets name of this FrontEnd. Can be used by clients if frontend is selected automatically by FrontEndManager::load_by_model. @@ -138,7 +139,7 @@ void regclass_pyngraph_FrontEnd(py::module m) { Current frontend name. Empty string if not implemented. )"); - fem.def("__repr__", [](const ngraph::frontend::FrontEnd& self) -> std::string { + fem.def("__repr__", [](const ov::frontend::FrontEnd& self) -> std::string { return ""; }); } diff --git a/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend_manager.cpp b/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend_manager.cpp index 250e80e69e5d74..a4c4d76a7e5235 100644 --- a/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend_manager.cpp +++ b/runtime/bindings/python/src/compatibility/pyngraph/frontend/frontend_manager.cpp @@ -14,26 +14,25 @@ namespace py = pybind11; void regclass_pyngraph_FrontEndManager(py::module m) { - py::class_> fem( - m, - "FrontEndManager", - py::dynamic_attr(), - py::module_local()); + py::class_> fem(m, + "FrontEndManager", + py::dynamic_attr(), + py::module_local()); fem.doc() = "ngraph.impl.FrontEndManager wraps ngraph::frontend::FrontEndManager"; fem.def(py::init<>()); // Empty pickle dumps are supported as FrontEndManager doesn't have any state fem.def(py::pickle( - [](const ngraph::frontend::FrontEndManager&) { + [](const ov::frontend::FrontEndManager&) { return py::make_tuple(0); }, [](py::tuple t) { - return ngraph::frontend::FrontEndManager(); + return ov::frontend::FrontEndManager(); })); fem.def("get_available_front_ends", - &ngraph::frontend::FrontEndManager::get_available_front_ends, + &ov::frontend::FrontEndManager::get_available_front_ends, R"( Gets list of registered frontends. @@ -44,7 +43,7 @@ void regclass_pyngraph_FrontEndManager(py::module m) { )"); fem.def("load_by_framework", - &ngraph::frontend::FrontEndManager::load_by_framework, + &ov::frontend::FrontEndManager::load_by_framework, py::arg("framework"), R"( Loads frontend by name of framework and capabilities. @@ -62,7 +61,7 @@ void regclass_pyngraph_FrontEndManager(py::module m) { fem.def( "load_by_model", - [](const std::shared_ptr& fem, const std::string& model_path) { + [](const std::shared_ptr& fem, const std::string& model_path) { return fem->load_by_model(model_path); }, py::arg("model_path"), @@ -80,66 +79,66 @@ void regclass_pyngraph_FrontEndManager(py::module m) { Frontend interface for further loading of models. 'None' if no suitable frontend is found )"); - fem.def("__repr__", [](const ngraph::frontend::FrontEndManager& self) -> std::string { + fem.def("__repr__", [](const ov::frontend::FrontEndManager& self) -> std::string { return ""; }); } void regclass_pyngraph_GeneralFailureFrontEnd(py::module m) { - static py::exception exc(std::move(m), "GeneralFailure"); + static py::exception exc(std::move(m), "GeneralFailure"); py::register_exception_translator([](std::exception_ptr p) { try { if (p) std::rethrow_exception(p); - } catch (const ngraph::frontend::GeneralFailure& e) { + } catch (const ov::frontend::GeneralFailure& e) { exc(e.what()); } }); } void regclass_pyngraph_OpValidationFailureFrontEnd(py::module m) { - static py::exception exc(std::move(m), "OpValidationFailure"); + static py::exception exc(std::move(m), "OpValidationFailure"); py::register_exception_translator([](std::exception_ptr p) { try { if (p) std::rethrow_exception(p); - } catch (const ngraph::frontend::OpValidationFailure& e) { + } catch (const ov::frontend::OpValidationFailure& e) { exc(e.what()); } }); } void regclass_pyngraph_OpConversionFailureFrontEnd(py::module m) { - static py::exception exc(std::move(m), "OpConversionFailure"); + static py::exception exc(std::move(m), "OpConversionFailure"); py::register_exception_translator([](std::exception_ptr p) { try { if (p) std::rethrow_exception(p); - } catch (const ngraph::frontend::OpConversionFailure& e) { + } catch (const ov::frontend::OpConversionFailure& e) { exc(e.what()); } }); } void regclass_pyngraph_InitializationFailureFrontEnd(py::module m) { - static py::exception exc(std::move(m), "InitializationFailure"); + static py::exception exc(std::move(m), "InitializationFailure"); py::register_exception_translator([](std::exception_ptr p) { try { if (p) std::rethrow_exception(p); - } catch (const ngraph::frontend::InitializationFailure& e) { + } catch (const ov::frontend::InitializationFailure& e) { exc(e.what()); } }); } void regclass_pyngraph_NotImplementedFailureFrontEnd(py::module m) { - static py::exception exc(std::move(m), "NotImplementedFailure"); + static py::exception exc(std::move(m), "NotImplementedFailure"); py::register_exception_translator([](std::exception_ptr p) { try { if (p) std::rethrow_exception(p); - } catch (const ngraph::frontend::NotImplementedFailure& e) { + } catch (const ov::frontend::NotImplementedFailure& e) { exc(e.what()); } }); diff --git a/runtime/bindings/python/src/compatibility/pyngraph/frontend/inputmodel.cpp b/runtime/bindings/python/src/compatibility/pyngraph/frontend/inputmodel.cpp index 94e5628a917a32..6396c33bf194ae 100644 --- a/runtime/bindings/python/src/compatibility/pyngraph/frontend/inputmodel.cpp +++ b/runtime/bindings/python/src/compatibility/pyngraph/frontend/inputmodel.cpp @@ -12,14 +12,14 @@ namespace py = pybind11; void regclass_pyngraph_InputModel(py::module m) { - py::class_> im(m, - "InputModel", - py::dynamic_attr(), - py::module_local()); + py::class_> im(m, + "InputModel", + py::dynamic_attr(), + py::module_local()); im.doc() = "ngraph.impl.InputModel wraps ngraph::frontend::InputModel"; im.def("get_place_by_tensor_name", - &ngraph::frontend::InputModel::get_place_by_tensor_name, + &ov::frontend::InputModel::get_place_by_tensor_name, py::arg("tensorName"), R"( Returns a tensor place by a tensor name following framework conventions, or @@ -37,7 +37,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("get_place_by_operation_name", - &ngraph::frontend::InputModel::get_place_by_operation_name, + &ov::frontend::InputModel::get_place_by_operation_name, py::arg("operationName"), R"( Returns an operation place by an operation name following framework conventions, or @@ -55,7 +55,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("get_place_by_operation_name_and_input_port", - &ngraph::frontend::InputModel::get_place_by_operation_name_and_input_port, + &ov::frontend::InputModel::get_place_by_operation_name_and_input_port, py::arg("operationName"), py::arg("inputPortIndex"), R"( @@ -76,7 +76,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("get_place_by_operation_name_and_output_port", - &ngraph::frontend::InputModel::get_place_by_operation_name_and_output_port, + &ov::frontend::InputModel::get_place_by_operation_name_and_output_port, py::arg("operationName"), py::arg("outputPortIndex"), R"( @@ -97,7 +97,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("set_name_for_tensor", - &ngraph::frontend::InputModel::set_name_for_tensor, + &ov::frontend::InputModel::set_name_for_tensor, py::arg("tensor"), py::arg("newName"), R"( @@ -113,7 +113,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("add_name_for_tensor", - &ngraph::frontend::InputModel::add_name_for_tensor, + &ov::frontend::InputModel::add_name_for_tensor, py::arg("tensor"), py::arg("newName"), R"( @@ -129,7 +129,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("set_name_for_operation", - &ngraph::frontend::InputModel::set_name_for_operation, + &ov::frontend::InputModel::set_name_for_operation, py::arg("operation"), py::arg("newName"), R"( @@ -145,7 +145,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("free_name_for_tensor", - &ngraph::frontend::InputModel::free_name_for_tensor, + &ov::frontend::InputModel::free_name_for_tensor, py::arg("name"), R"( Unassign specified name from tensor place(s). @@ -157,7 +157,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("free_name_for_operation", - &ngraph::frontend::InputModel::free_name_for_operation, + &ov::frontend::InputModel::free_name_for_operation, py::arg("name"), R"( Unassign specified name from operation place(s). @@ -169,7 +169,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("set_name_for_dimension", - &ngraph::frontend::InputModel::set_name_for_dimension, + &ov::frontend::InputModel::set_name_for_dimension, py::arg("place"), py::arg("dimIndex"), py::arg("dimName"), @@ -189,7 +189,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("cut_and_add_new_input", - &ngraph::frontend::InputModel::cut_and_add_new_input, + &ov::frontend::InputModel::cut_and_add_new_input, py::arg("place"), py::arg("newName") = std::string(), R"( @@ -206,7 +206,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("cut_and_add_new_output", - &ngraph::frontend::InputModel::cut_and_add_new_output, + &ov::frontend::InputModel::cut_and_add_new_output, py::arg("place"), py::arg("newName") = std::string(), R"( @@ -223,7 +223,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("add_output", - &ngraph::frontend::InputModel::add_output, + &ov::frontend::InputModel::add_output, py::arg("place"), R"( Assign this place as new output or add necessary nodes to represent a new output. @@ -235,7 +235,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("remove_output", - &ngraph::frontend::InputModel::remove_output, + &ov::frontend::InputModel::remove_output, py::arg("place"), R"( Removes any sinks directly attached to this place with all inbound data flow @@ -248,7 +248,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("set_partial_shape", - &ngraph::frontend::InputModel::set_partial_shape, + &ov::frontend::InputModel::set_partial_shape, py::arg("place"), py::arg("shape"), R"( @@ -267,7 +267,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("get_partial_shape", - &ngraph::frontend::InputModel::get_partial_shape, + &ov::frontend::InputModel::get_partial_shape, py::arg("place"), R"( Returns current partial shape used for this place. @@ -284,7 +284,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("get_inputs", - &ngraph::frontend::InputModel::get_inputs, + &ov::frontend::InputModel::get_inputs, R"( Returns all inputs for a model. @@ -295,7 +295,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("get_outputs", - &ngraph::frontend::InputModel::get_outputs, + &ov::frontend::InputModel::get_outputs, R"( Returns all outputs for a model. An output is a terminal place in a graph where data escapes the flow. @@ -306,7 +306,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("extract_subgraph", - &ngraph::frontend::InputModel::extract_subgraph, + &ov::frontend::InputModel::extract_subgraph, py::arg("inputs"), py::arg("outputs"), R"( @@ -322,7 +322,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("override_all_inputs", - &ngraph::frontend::InputModel::override_all_inputs, + &ov::frontend::InputModel::override_all_inputs, py::arg("inputs"), R"( Modifies the graph to use new inputs instead of existing ones. New inputs @@ -335,7 +335,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("override_all_outputs", - &ngraph::frontend::InputModel::override_all_outputs, + &ov::frontend::InputModel::override_all_outputs, py::arg("outputs"), R"( Replaces all existing outputs with new ones removing all data flow that @@ -348,7 +348,7 @@ void regclass_pyngraph_InputModel(py::module m) { )"); im.def("set_element_type", - &ngraph::frontend::InputModel::set_element_type, + &ov::frontend::InputModel::set_element_type, py::arg("place"), py::arg("type"), R"( diff --git a/runtime/bindings/python/src/compatibility/pyngraph/frontend/place.cpp b/runtime/bindings/python/src/compatibility/pyngraph/frontend/place.cpp index 5414d74529f9b5..a35832a1fa77bf 100644 --- a/runtime/bindings/python/src/compatibility/pyngraph/frontend/place.cpp +++ b/runtime/bindings/python/src/compatibility/pyngraph/frontend/place.cpp @@ -14,14 +14,14 @@ namespace py = pybind11; void regclass_pyngraph_Place(py::module m) { - py::class_> place(m, - "Place", - py::dynamic_attr(), - py::module_local()); + py::class_> place(m, + "Place", + py::dynamic_attr(), + py::module_local()); place.doc() = "ngraph.impl.Place wraps ngraph::frontend::Place"; place.def("is_input", - &ngraph::frontend::Place::is_input, + &ov::frontend::Place::is_input, R"( Returns true if this place is input for a model. @@ -32,7 +32,7 @@ void regclass_pyngraph_Place(py::module m) { )"); place.def("is_output", - &ngraph::frontend::Place::is_output, + &ov::frontend::Place::is_output, R"( Returns true if this place is output for a model. @@ -43,7 +43,7 @@ void regclass_pyngraph_Place(py::module m) { )"); place.def("get_names", - &ngraph::frontend::Place::get_names, + &ov::frontend::Place::get_names, R"( All associated names (synonyms) that identify this place in the graph in a framework specific way. @@ -55,7 +55,7 @@ void regclass_pyngraph_Place(py::module m) { )"); place.def("is_equal", - &ngraph::frontend::Place::is_equal, + &ov::frontend::Place::is_equal, py::arg("other"), R"( Returns true if another place is the same as this place. @@ -72,7 +72,7 @@ void regclass_pyngraph_Place(py::module m) { )"); place.def("is_equal_data", - &ngraph::frontend::Place::is_equal_data, + &ov::frontend::Place::is_equal_data, py::arg("other"), R"( Returns true if another place points to the same data. @@ -92,7 +92,7 @@ void regclass_pyngraph_Place(py::module m) { place.def( "get_consuming_operations", - [](const ngraph::frontend::Place& self, py::object outputName, py::object outputPortIndex) { + [](const ov::frontend::Place& self, py::object outputName, py::object outputPortIndex) { if (outputName == py::none()) { if (outputPortIndex == py::none()) { return self.get_consuming_operations(); @@ -130,7 +130,7 @@ void regclass_pyngraph_Place(py::module m) { place.def( "get_target_tensor", - [](const ngraph::frontend::Place& self, py::object outputName, py::object outputPortIndex) { + [](const ov::frontend::Place& self, py::object outputName, py::object outputPortIndex) { if (outputName == py::none()) { if (outputPortIndex == py::none()) { return self.get_target_tensor(); @@ -167,7 +167,7 @@ void regclass_pyngraph_Place(py::module m) { place.def( "get_producing_operation", - [](const ngraph::frontend::Place& self, py::object inputName, py::object inputPortIndex) { + [](const ov::frontend::Place& self, py::object inputName, py::object inputPortIndex) { if (inputName == py::none()) { if (inputPortIndex == py::none()) { return self.get_producing_operation(); @@ -203,7 +203,7 @@ void regclass_pyngraph_Place(py::module m) { )"); place.def("get_producing_port", - &ngraph::frontend::Place::get_producing_port, + &ov::frontend::Place::get_producing_port, R"( Returns a port that produces data for this place. @@ -215,7 +215,7 @@ void regclass_pyngraph_Place(py::module m) { place.def( "get_input_port", - [](const ngraph::frontend::Place& self, py::object inputName, py::object inputPortIndex) { + [](const ov::frontend::Place& self, py::object inputName, py::object inputPortIndex) { if (inputName == py::none()) { if (inputPortIndex == py::none()) { return self.get_input_port(); @@ -251,7 +251,7 @@ void regclass_pyngraph_Place(py::module m) { place.def( "get_output_port", - [](const ngraph::frontend::Place& self, py::object outputName, py::object outputPortIndex) { + [](const ov::frontend::Place& self, py::object outputName, py::object outputPortIndex) { if (outputName == py::none()) { if (outputPortIndex == py::none()) { return self.get_output_port(); @@ -286,7 +286,7 @@ void regclass_pyngraph_Place(py::module m) { )"); place.def("get_consuming_ports", - &ngraph::frontend::Place::get_consuming_ports, + &ov::frontend::Place::get_consuming_ports, R"( Returns all input ports that consume data flows through this place. @@ -298,7 +298,7 @@ void regclass_pyngraph_Place(py::module m) { place.def( "get_source_tensor", - [](const ngraph::frontend::Place& self, py::object inputName, py::object inputPortIndex) { + [](const ov::frontend::Place& self, py::object inputName, py::object inputPortIndex) { if (inputName == py::none()) { if (inputPortIndex == py::none()) { return self.get_source_tensor(); diff --git a/runtime/bindings/python/src/compatibility/pyngraph/node_factory.cpp b/runtime/bindings/python/src/compatibility/pyngraph/node_factory.cpp index e93e3ce30bbac1..e7d7ee2aa563e3 100644 --- a/runtime/bindings/python/src/compatibility/pyngraph/node_factory.cpp +++ b/runtime/bindings/python/src/compatibility/pyngraph/node_factory.cpp @@ -82,7 +82,6 @@ class NodeFactory { {"opset5", OpsetFunction(ngraph::get_opset5)}, {"opset6", OpsetFunction(ngraph::get_opset6)}, {"opset7", OpsetFunction(ngraph::get_opset7)}, - {"opset8", OpsetFunction(ngraph::get_opset8)}, }; auto it = s_opsets.find(opset_ver); diff --git a/runtime/bindings/python/src/openvino/__init__.py b/runtime/bindings/python/src/openvino/__init__.py index a8ce307765f147..ca73e6b4d6add0 100644 --- a/runtime/bindings/python/src/openvino/__init__.py +++ b/runtime/bindings/python/src/openvino/__init__.py @@ -6,46 +6,32 @@ from pkg_resources import get_distribution, DistributionNotFound -__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore # mypy issue #1422 +__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore # mypy issue #1422 try: __version__ = get_distribution("openvino-core").version except DistributionNotFound: __version__ = "0.0.0.dev0" -from openvino.ie_api import BlobWrapper -from openvino.ie_api import infer -from openvino.ie_api import async_infer -from openvino.ie_api import get_result -from openvino.ie_api import blob_from_file +# Openvino pybind bindings and python extended classes from openvino.impl import Dimension from openvino.impl import Function from openvino.impl import Node from openvino.impl import PartialShape from openvino.impl import Layout -from openvino.pyopenvino import Core -from openvino.pyopenvino import IENetwork -from openvino.pyopenvino import ExecutableNetwork +from openvino.ie_api import Core +from openvino.ie_api import ExecutableNetwork +from openvino.ie_api import InferRequest +from openvino.ie_api import AsyncInferQueue from openvino.pyopenvino import Version from openvino.pyopenvino import Parameter -from openvino.pyopenvino import InputInfoPtr -from openvino.pyopenvino import InputInfoCPtr -from openvino.pyopenvino import DataPtr -from openvino.pyopenvino import TensorDesc -from openvino.pyopenvino import get_version -from openvino.pyopenvino import StatusCode -from openvino.pyopenvino import InferQueue -from openvino.pyopenvino import InferRequest # TODO: move to ie_api? -from openvino.pyopenvino import Blob -from openvino.pyopenvino import PreProcessInfo -from openvino.pyopenvino import MeanVariant -from openvino.pyopenvino import ResizeAlgorithm -from openvino.pyopenvino import ColorFormat -from openvino.pyopenvino import PreProcessChannel from openvino.pyopenvino import Tensor +from openvino.pyopenvino import ProfilingInfo +from openvino.pyopenvino import get_version +# Import opsets from openvino import opset1 from openvino import opset2 from openvino import opset3 @@ -55,6 +41,10 @@ from openvino import opset7 from openvino import opset8 +# Helper functions for openvino module +from openvino.ie_api import tensor_from_file +from openvino.ie_api import compile_model + # Extend Node class to support binary operators Node.__add__ = opset8.add Node.__sub__ = opset8.subtract @@ -72,16 +62,3 @@ Node.__le__ = opset8.less_equal Node.__gt__ = opset8.greater Node.__ge__ = opset8.greater_equal - -# Patching for Blob class -# flake8: noqa: F811 -# this class will be removed -Blob = BlobWrapper -# Patching ExecutableNetwork -ExecutableNetwork.infer = infer -# Patching InferRequest -InferRequest.infer = infer -InferRequest.async_infer = async_infer -InferRequest.get_result = get_result -# Patching InferQueue -InferQueue.async_infer = async_infer diff --git a/runtime/bindings/python/src/openvino/ie_api.py b/runtime/bindings/python/src/openvino/ie_api.py index 925bc2ad5bb545..6300f88ce7c67f 100644 --- a/runtime/bindings/python/src/openvino/ie_api.py +++ b/runtime/bindings/python/src/openvino/ie_api.py @@ -2,113 +2,110 @@ # SPDX-License-Identifier: Apache-2.0 import numpy as np +import copy +from typing import Any, List, Union -from openvino.pyopenvino import TBlobFloat32 -from openvino.pyopenvino import TBlobFloat64 -from openvino.pyopenvino import TBlobInt64 -from openvino.pyopenvino import TBlobUint64 -from openvino.pyopenvino import TBlobInt32 -from openvino.pyopenvino import TBlobUint32 -from openvino.pyopenvino import TBlobInt16 -from openvino.pyopenvino import TBlobUint16 -from openvino.pyopenvino import TBlobInt8 -from openvino.pyopenvino import TBlobUint8 -from openvino.pyopenvino import TensorDesc -from openvino.pyopenvino import InferRequest - - -precision_map = {"FP32": np.float32, - "FP64": np.float64, - "FP16": np.int16, - "BF16": np.int16, - "I16": np.int16, - "I8": np.int8, - "BIN": np.int8, - "I32": np.int32, - "I64": np.int64, - "U8": np.uint8, - "BOOL": np.uint8, - "U16": np.uint16, - "U32": np.uint32, - "U64": np.uint64} - - -def normalize_inputs(py_dict: dict) -> dict: - """Normalize a dictionary of inputs to contiguous numpy arrays.""" - return {k: (np.ascontiguousarray(v) if isinstance(v, np.ndarray) else v) - for k, v in py_dict.items()} - -# flake8: noqa: D102 -def infer(request: InferRequest, inputs: dict = None) -> dict: - results = request._infer(inputs=normalize_inputs(inputs if inputs is not None else {})) - return {name: (blob.buffer.copy()) for name, blob in results.items()} - -# flake8: noqa: D102 -def get_result(request: InferRequest, name: str) -> np.ndarray: - return request.get_blob(name).buffer.copy() - -# flake8: noqa: D102 -def async_infer(request: InferRequest, inputs: dict = None, userdata=None) -> None: # type: ignore - request._async_infer(inputs=normalize_inputs(inputs if inputs is not None else {}), - userdata=userdata) - -# flake8: noqa: C901 -# Dispatch Blob types on Python side. -class BlobWrapper: - def __new__(cls, tensor_desc: TensorDesc, arr: np.ndarray = None): # type: ignore - arr_size = 0 - precision = "" - if tensor_desc is not None: - tensor_desc_size = int(np.prod(tensor_desc.dims)) - precision = tensor_desc.precision - if arr is not None: - arr = np.array(arr) # Keeping array as numpy array - arr_size = int(np.prod(arr.shape)) - if np.isfortran(arr): - arr = arr.ravel(order="F") - else: - arr = arr.ravel(order="C") - if arr_size != tensor_desc_size: - raise AttributeError(f"Number of elements in provided numpy array " - f"{arr_size} and required by TensorDesc " - f"{tensor_desc_size} are not equal") - if arr.dtype != precision_map[precision]: - raise ValueError(f"Data type {arr.dtype} of provided numpy array " - f"doesn't match to TensorDesc precision {precision}") - if not arr.flags["C_CONTIGUOUS"]: - arr = np.ascontiguousarray(arr) - elif arr is None: - arr = np.empty(0, dtype=precision_map[precision]) - else: - raise AttributeError("TensorDesc can't be None") - - if precision in ["FP32"]: - return TBlobFloat32(tensor_desc, arr, arr_size) - elif precision in ["FP64"]: - return TBlobFloat64(tensor_desc, arr, arr_size) - elif precision in ["FP16", "BF16"]: - return TBlobInt16(tensor_desc, arr.view(dtype=np.int16), arr_size) - elif precision in ["I64"]: - return TBlobInt64(tensor_desc, arr, arr_size) - elif precision in ["U64"]: - return TBlobUint64(tensor_desc, arr, arr_size) - elif precision in ["I32"]: - return TBlobInt32(tensor_desc, arr, arr_size) - elif precision in ["U32"]: - return TBlobUint32(tensor_desc, arr, arr_size) - elif precision in ["I16"]: - return TBlobInt16(tensor_desc, arr, arr_size) - elif precision in ["U16"]: - return TBlobUint16(tensor_desc, arr, arr_size) - elif precision in ["I8", "BIN"]: - return TBlobInt8(tensor_desc, arr, arr_size) - elif precision in ["U8", "BOOL"]: - return TBlobUint8(tensor_desc, arr, arr_size) - else: - raise AttributeError(f"Unsupported precision {precision} for Blob") - -# flake8: noqa: D102 -def blob_from_file(path_to_bin_file: str) -> BlobWrapper: - array = np.fromfile(path_to_bin_file, dtype=np.uint8) - tensor_desc = TensorDesc("U8", array.shape, "C") - return BlobWrapper(tensor_desc, array) +from openvino.pyopenvino import Function +from openvino.pyopenvino import Core as CoreBase +from openvino.pyopenvino import ExecutableNetwork as ExecutableNetworkBase +from openvino.pyopenvino import InferRequest as InferRequestBase +from openvino.pyopenvino import AsyncInferQueue as AsyncInferQueueBase +from openvino.pyopenvino import Tensor + +from openvino.utils.types import get_dtype + + +def tensor_from_file(path: str) -> Tensor: + """Create Tensor from file. Data will be read with dtype of unit8.""" + return Tensor(np.fromfile(path, dtype=np.uint8)) + + +def normalize_inputs(py_dict: dict, py_types: dict) -> dict: + """Normalize a dictionary of inputs to Tensors.""" + for k, val in py_dict.items(): + try: + if isinstance(k, int): + ov_type = list(py_types.values())[k] + elif isinstance(k, str): + ov_type = py_types[k] + else: + raise TypeError("Incompatible key type for tensor named: {}".format(k)) + except KeyError: + raise KeyError("Port for tensor named {} was not found!".format(k)) + py_dict[k] = val if isinstance(val, Tensor) else Tensor(np.array(val, get_dtype(ov_type))) + return py_dict + + +def get_input_types(obj: Union[InferRequestBase, ExecutableNetworkBase]) -> dict: + """Get all precisions from object inputs.""" + return {i.get_node().get_friendly_name(): i.get_node().get_element_type() for i in obj.inputs} + + +class InferRequest(InferRequestBase): + """InferRequest wrapper.""" + + def infer(self, inputs: dict = {}) -> List[np.ndarray]: # noqa: B006 + """Infer wrapper for InferRequest.""" + res = super().infer(inputs=normalize_inputs(inputs, get_input_types(self))) + # Required to return list since np.ndarray forces all of tensors data to match in + # dimensions. This results in errors when running ops like variadic split. + return [copy.deepcopy(tensor.data) for tensor in res] + + def start_async(self, inputs: dict = {}, userdata: Any = None) -> None: # noqa: B006, type: ignore + """Asynchronous infer wrapper for InferRequest.""" + super().start_async(inputs=normalize_inputs(inputs, get_input_types(self)), userdata=userdata) + + +class ExecutableNetwork(ExecutableNetworkBase): + """ExecutableNetwork wrapper.""" + + def create_infer_request(self) -> InferRequest: + """Create new InferRequest object.""" + return InferRequest(super().create_infer_request()) + + def infer_new_request(self, inputs: dict = {}) -> List[np.ndarray]: # noqa: B006 + """Infer wrapper for ExecutableNetwork.""" + res = super().infer_new_request(inputs=normalize_inputs(inputs, get_input_types(self))) + # Required to return list since np.ndarray forces all of tensors data to match in + # dimensions. This results in errors when running ops like variadic split. + return [copy.deepcopy(tensor.data) for tensor in res] + + +class AsyncInferQueue(AsyncInferQueueBase): + """AsyncInferQueue wrapper.""" + + def __getitem__(self, i: int) -> InferRequest: + """Return i-th InferRequest from AsyncInferQueue.""" + return InferRequest(super().__getitem__(i)) + + def start_async( + self, inputs: dict = {}, userdata: Any = None # noqa: B006 + ) -> None: # type: ignore + """Asynchronous infer wrapper for AsyncInferQueue.""" + super().start_async( + inputs=normalize_inputs( + inputs, get_input_types(self[self.get_idle_request_id()]) + ), + userdata=userdata, + ) + + +class Core(CoreBase): + """Core wrapper.""" + + def compile_model( + self, model: Function, device_name: str, config: dict = {} # noqa: B006 + ) -> ExecutableNetwork: + """Compile a model from given Function.""" + return ExecutableNetwork(super().compile_model(model, device_name, config)) + + def import_model( + self, model_file: str, device_name: str, config: dict = {} # noqa: B006 + ) -> ExecutableNetwork: + """Compile a model from given model file path.""" + return ExecutableNetwork(super().import_model(model_file, device_name, config)) + + +def compile_model(model_path: str) -> ExecutableNetwork: + """Compact method to compile model with AUTO plugin.""" + return Core().compile_model(model_path, "AUTO") diff --git a/runtime/bindings/python/src/openvino/impl/__init__.py b/runtime/bindings/python/src/openvino/impl/__init__.py index 641764122dc5a9..8a4da6705b90b2 100644 --- a/runtime/bindings/python/src/openvino/impl/__init__.py +++ b/runtime/bindings/python/src/openvino/impl/__init__.py @@ -49,4 +49,6 @@ from openvino.pyopenvino import Coordinate from openvino.pyopenvino import Output from openvino.pyopenvino import Layout +from openvino.pyopenvino import ConstOutput from openvino.pyopenvino import util +from openvino.pyopenvino import layout_helpers diff --git a/runtime/bindings/python/src/openvino/offline_transformations_pybind/__init__.py b/runtime/bindings/python/src/openvino/offline_transformations_pybind/__init__.py new file mode 100644 index 00000000000000..567d667c0724b2 --- /dev/null +++ b/runtime/bindings/python/src/openvino/offline_transformations_pybind/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from openvino.pyopenvino.offline_transformations_pybind import apply_moc_transformations +from openvino.pyopenvino.offline_transformations_pybind import apply_pot_transformations +from openvino.pyopenvino.offline_transformations_pybind import apply_low_latency_transformation +from openvino.pyopenvino.offline_transformations_pybind import apply_pruning_transformation +from openvino.pyopenvino.offline_transformations_pybind import generate_mapping_file +from openvino.pyopenvino.offline_transformations_pybind import apply_make_stateful_transformation diff --git a/runtime/bindings/python/src/pyopenvino/CMakeLists.txt b/runtime/bindings/python/src/pyopenvino/CMakeLists.txt index 305a5687c0fee4..7b377180f9e4c1 100644 --- a/runtime/bindings/python/src/pyopenvino/CMakeLists.txt +++ b/runtime/bindings/python/src/pyopenvino/CMakeLists.txt @@ -4,7 +4,7 @@ project (pyopenvino) if(NOT DEFINED OpenVINO_SOURCE_DIR) - find_package(OpenVINO REQUIRED) + find_package(InferenceEngineDeveloperPackage REQUIRED) endif() # PYTHON_VERSION_MAJOR and PYTHON_VERSION_MINOR are defined inside pybind11 @@ -30,8 +30,14 @@ file(GLOB_RECURSE SOURCES *.cpp) pybind11_add_module(${PROJECT_NAME} MODULE ${SOURCES}) +if(TARGET offline_transformations) + set(OFFLINE_TRANSFORMATIONS_LIB offline_transformations) +else() + set(OFFLINE_TRANSFORMATIONS_LIB IE::offline_transformations) +endif() + target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..") -target_link_libraries(${PROJECT_NAME} PRIVATE openvino::runtime) +target_link_libraries(${PROJECT_NAME} PRIVATE openvino::runtime ${OFFLINE_TRANSFORMATIONS_LIB}) # perform copy if(OpenVINO_SOURCE_DIR) @@ -61,3 +67,7 @@ if(OpenVINO_SOURCE_DIR OR InferenceEngineDeveloperPackage_FOUND) ie_cpack(pyopenvino_${PYTHON_VERSION}) endif() + +if(TARGET ie_wheel) + add_dependencies(ie_wheel ${PROJECT_NAME}) +endif() diff --git a/runtime/bindings/python/src/pyopenvino/core/async_infer_queue.cpp b/runtime/bindings/python/src/pyopenvino/core/async_infer_queue.cpp new file mode 100644 index 00000000000000..160a3ef2307c2f --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/async_infer_queue.cpp @@ -0,0 +1,192 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "pyopenvino/core/async_infer_queue.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pyopenvino/core/common.hpp" +#include "pyopenvino/core/infer_request.hpp" + +namespace py = pybind11; + +class AsyncInferQueue { +public: + AsyncInferQueue(std::vector requests, + std::queue idle_handles, + std::vector user_ids) + : _requests(requests), + _idle_handles(idle_handles), + _user_ids(user_ids) { + this->set_default_callbacks(); + } + + ~AsyncInferQueue() { + _requests.clear(); + } + + bool _is_ready() { + py::gil_scoped_release release; + std::unique_lock lock(_mutex); + _cv.wait(lock, [this] { + return !(_idle_handles.empty()); + }); + + return !(_idle_handles.empty()); + } + + size_t get_idle_request_id() { + // Wait for any of _idle_handles + py::gil_scoped_release release; + std::unique_lock lock(_mutex); + _cv.wait(lock, [this] { + return !(_idle_handles.empty()); + }); + + return _idle_handles.front(); + } + + void wait_all() { + // Wait for all requests to return with callback thus updating + // _idle_handles so it matches the size of requests + py::gil_scoped_release release; + std::unique_lock lock(_mutex); + _cv.wait(lock, [this] { + return _idle_handles.size() == _requests.size(); + }); + } + + void set_default_callbacks() { + for (size_t handle = 0; handle < _requests.size(); handle++) { + _requests[handle]._request.set_callback([this, handle /* ... */](std::exception_ptr exception_ptr) { + _requests[handle]._end_time = Time::now(); + // Add idle handle to queue + _idle_handles.push(handle); + // Notify locks in getIdleRequestId() or waitAll() functions + _cv.notify_one(); + }); + } + } + + void set_custom_callbacks(py::function f_callback) { + for (size_t handle = 0; handle < _requests.size(); handle++) { + _requests[handle]._request.set_callback([this, f_callback, handle](std::exception_ptr exception_ptr) { + _requests[handle]._end_time = Time::now(); + try { + if (exception_ptr) { + std::rethrow_exception(exception_ptr); + } + } catch (const std::exception& e) { + throw ov::Exception(e.what()); + } + // Acquire GIL, execute Python function + py::gil_scoped_acquire acquire; + f_callback(_requests[handle], _user_ids[handle]); + // Add idle handle to queue + _idle_handles.push(handle); + // Notify locks in getIdleRequestId() or waitAll() functions + _cv.notify_one(); + }); + } + } + + std::vector _requests; + std::queue _idle_handles; + std::vector _user_ids; // user ID can be any Python object + std::mutex _mutex; + std::condition_variable _cv; +}; + +void regclass_AsyncInferQueue(py::module m) { + py::class_> cls(m, "AsyncInferQueue"); + + cls.def(py::init([](ov::runtime::ExecutableNetwork& net, size_t jobs) { + if (jobs == 0) { + jobs = (size_t)Common::get_optimal_number_of_requests(net); + } + + std::vector requests; + std::queue idle_handles; + std::vector user_ids(jobs); + + for (size_t handle = 0; handle < jobs; handle++) { + auto request = InferRequestWrapper(net.create_infer_request()); + // Get Inputs and Outputs info from executable network + request._inputs = net.inputs(); + request._outputs = net.outputs(); + + requests.push_back(request); + idle_handles.push(handle); + } + + return new AsyncInferQueue(requests, idle_handles, user_ids); + }), + py::arg("network"), + py::arg("jobs") = 0); + + cls.def( + "start_async", + [](AsyncInferQueue& self, const py::dict inputs, py::object userdata) { + // getIdleRequestId function has an intention to block InferQueue + // until there is at least one idle (free to use) InferRequest + auto handle = self.get_idle_request_id(); + self._idle_handles.pop(); + // Set new inputs label/id from user + self._user_ids[handle] = userdata; + // Update inputs if there are any + Common::set_request_tensors(self._requests[handle]._request, inputs); + // Now GIL can be released - we are NOT working with Python objects in this block + { + py::gil_scoped_release release; + self._requests[handle]._start_time = Time::now(); + // Start InferRequest in asynchronus mode + self._requests[handle]._request.start_async(); + } + }, + py::arg("inputs"), + py::arg("userdata")); + + cls.def("is_ready", [](AsyncInferQueue& self) { + return self._is_ready(); + }); + + cls.def("wait_all", [](AsyncInferQueue& self) { + return self.wait_all(); + }); + + cls.def("get_idle_request_id", [](AsyncInferQueue& self) { + return self.get_idle_request_id(); + }); + + cls.def("set_callback", [](AsyncInferQueue& self, py::function f_callback) { + self.set_custom_callbacks(f_callback); + }); + + cls.def("__len__", [](AsyncInferQueue& self) { + return self._requests.size(); + }); + + cls.def( + "__iter__", + [](AsyncInferQueue& self) { + return py::make_iterator(self._requests.begin(), self._requests.end()); + }, + py::keep_alive<0, 1>()); /* Keep set alive while iterator is used */ + + cls.def("__getitem__", [](AsyncInferQueue& self, size_t i) { + return self._requests[i]; + }); + + cls.def_property_readonly("userdata", [](AsyncInferQueue& self) { + return self._user_ids; + }); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_network.hpp b/runtime/bindings/python/src/pyopenvino/core/async_infer_queue.hpp similarity index 77% rename from runtime/bindings/python/src/pyopenvino/core/ie_network.hpp rename to runtime/bindings/python/src/pyopenvino/core/async_infer_queue.hpp index 9cbd5e43456ba9..3ed1122ba126d7 100644 --- a/runtime/bindings/python/src/pyopenvino/core/ie_network.hpp +++ b/runtime/bindings/python/src/pyopenvino/core/async_infer_queue.hpp @@ -1,6 +1,5 @@ // Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -// #pragma once @@ -8,4 +7,4 @@ namespace py = pybind11; -void regclass_IENetwork(py::module m); +void regclass_AsyncInferQueue(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/core/common.cpp b/runtime/bindings/python/src/pyopenvino/core/common.cpp index 098a85f2ffc95a..6ef5774163a20e 100644 --- a/runtime/bindings/python/src/pyopenvino/core/common.cpp +++ b/runtime/bindings/python/src/pyopenvino/core/common.cpp @@ -6,6 +6,8 @@ #include +#define C_CONTIGUOUS py::detail::npy_api::constants::NPY_ARRAY_C_CONTIGUOUS_ + namespace Common { const std::map& ov_type_to_dtype() { static const std::map ov_type_to_dtype_mapping = { @@ -45,42 +47,130 @@ const std::map& dtype_to_ov_type() { return dtype_to_ov_type_mapping; } -InferenceEngine::Layout get_layout_from_string(const std::string& layout) { - static const std::unordered_map layout_str_to_enum = { - {"ANY", InferenceEngine::Layout::ANY}, - {"NHWC", InferenceEngine::Layout::NHWC}, - {"NCHW", InferenceEngine::Layout::NCHW}, - {"NCDHW", InferenceEngine::Layout::NCDHW}, - {"NDHWC", InferenceEngine::Layout::NDHWC}, - {"OIHW", InferenceEngine::Layout::OIHW}, - {"GOIHW", InferenceEngine::Layout::GOIHW}, - {"OIDHW", InferenceEngine::Layout::OIDHW}, - {"GOIDHW", InferenceEngine::Layout::GOIDHW}, - {"SCALAR", InferenceEngine::Layout::SCALAR}, - {"C", InferenceEngine::Layout::C}, - {"CHW", InferenceEngine::Layout::CHW}, - {"HW", InferenceEngine::Layout::HW}, - {"NC", InferenceEngine::Layout::NC}, - {"CN", InferenceEngine::Layout::CN}, - {"BLOCKED", InferenceEngine::Layout::BLOCKED}}; - return layout_str_to_enum.at(layout); +ov::runtime::Tensor tensor_from_numpy(py::array& array, bool shared_memory) { + // Check if passed array has C-style contiguous memory layout. + bool is_contiguous = C_CONTIGUOUS == (array.flags() & C_CONTIGUOUS); + auto type = Common::dtype_to_ov_type().at(py::str(array.dtype())); + std::vector shape(array.shape(), array.shape() + array.ndim()); + + // If memory is going to be shared it needs to be contiguous before + // passing to the constructor. This case should be handled by advanced + // users on their side of the code. + if (shared_memory) { + if (is_contiguous) { + std::vector strides(array.strides(), array.strides() + array.ndim()); + return ov::runtime::Tensor(type, shape, const_cast(array.data(0)), strides); + } else { + throw ov::Exception("Tensor with shared memory must be C contiguous!"); + } + } + // Convert to contiguous array if not already C-style. + if (!is_contiguous) { + array = Common::as_contiguous(array, type); + } + // Create actual Tensor and copy data. + auto tensor = ov::runtime::Tensor(type, shape); + // If ndim of py::array is 0, array is a numpy scalar. That results in size to be equal to 0. + // To gain access to actual raw/low-level data, it is needed to use buffer protocol. + py::buffer_info buf = array.request(); + std::memcpy(tensor.data(), buf.ptr, buf.ndim == 0 ? buf.itemsize : buf.itemsize * buf.size); + return tensor; +} + +py::array as_contiguous(py::array& array, ov::element::Type type) { + switch (type) { + // floating + case ov::element::f64: + return array.cast>(); + case ov::element::f32: + return array.cast>(); + // signed + case ov::element::i64: + return array.cast>(); + case ov::element::i32: + return array.cast>(); + case ov::element::i16: + return array.cast>(); + case ov::element::i8: + return array.cast>(); + // unsigned + case ov::element::u64: + return array.cast>(); + case ov::element::u32: + return array.cast>(); + case ov::element::u16: + return array.cast>(); + case ov::element::u8: + return array.cast>(); + // other + case ov::element::boolean: + return array.cast>(); + case ov::element::u1: + return array.cast>(); + // need to create a view on array to cast it correctly + case ov::element::f16: + case ov::element::bf16: + return array.view("int16").cast>(); + default: + throw ov::Exception("Tensor cannot be created as contiguous!"); + break; + } +} + +const ov::runtime::Tensor& cast_to_tensor(const py::handle& tensor) { + return tensor.cast(); +} + +const Containers::TensorNameMap cast_to_tensor_name_map(const py::dict& inputs) { + Containers::TensorNameMap result_map; + for (auto&& input : inputs) { + std::string name; + if (py::isinstance(input.first)) { + name = input.first.cast(); + } else { + throw py::type_error("incompatible function arguments!"); + } + if (py::isinstance(input.second)) { + auto tensor = Common::cast_to_tensor(input.second); + result_map[name] = tensor; + } else { + throw ov::Exception("Unable to cast tensor " + name + "!"); + } + } + return result_map; +} + +const Containers::TensorIndexMap cast_to_tensor_index_map(const py::dict& inputs) { + Containers::TensorIndexMap result_map; + for (auto&& input : inputs) { + int idx; + if (py::isinstance(input.first)) { + idx = input.first.cast(); + } else { + throw py::type_error("incompatible function arguments!"); + } + if (py::isinstance(input.second)) { + auto tensor = Common::cast_to_tensor(input.second); + result_map[idx] = tensor; + } else { + throw ov::Exception("Unable to cast tensor " + std::to_string(idx) + "!"); + } + } + return result_map; } -const std::string& get_layout_from_enum(const InferenceEngine::Layout& layout) { - static const std::unordered_map layout_int_to_str_map = {{0, "ANY"}, - {1, "NCHW"}, - {2, "NHWC"}, - {3, "NCDHW"}, - {4, "NDHWC"}, - {64, "OIHW"}, - {95, "SCALAR"}, - {96, "C"}, - {128, "CHW"}, - {192, "HW"}, - {193, "NC"}, - {194, "CN"}, - {200, "BLOCKED"}}; - return layout_int_to_str_map.at(layout); +void set_request_tensors(ov::runtime::InferRequest& request, const py::dict& inputs) { + if (!inputs.empty()) { + for (auto&& input : inputs) { + if (py::isinstance(input.first)) { + request.set_tensor(input.first.cast(), Common::cast_to_tensor(input.second)); + } else if (py::isinstance(input.first)) { + request.set_input_tensor(input.first.cast(), Common::cast_to_tensor(input.second)); + } else { + throw py::type_error("Incompatible key type for tensor named: " + input.first.cast()); + } + } + } } PyObject* parse_parameter(const InferenceEngine::Parameter& param) { @@ -185,105 +275,13 @@ PyObject* parse_parameter(const InferenceEngine::Parameter& param) { } } -bool is_TBlob(const py::handle& blob) { - if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else if (py::isinstance>(blob)) { - return true; - } else { - return false; - } -} - -const std::shared_ptr cast_to_blob(const py::handle& blob) { - if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else if (py::isinstance>(blob)) { - return blob.cast>&>(); - } else { - IE_THROW() << "Unsupported data type for when casting to blob!"; - // return nullptr; - } -} - -void blob_from_numpy(const py::handle& arr, InferenceEngine::Blob::Ptr blob) { - if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else if (py::isinstance>(arr)) { - Common::fill_blob(arr, blob); - } else { - IE_THROW() << "Unsupported data type for when filling blob!"; - } -} - -void set_request_blobs(InferenceEngine::InferRequest& request, const py::dict& dictonary) { - for (auto&& pair : dictonary) { - const std::string& name = pair.first.cast(); - if (py::isinstance(pair.second)) { - Common::blob_from_numpy(pair.second, request.GetBlob(name)); - } else if (is_TBlob(pair.second)) { - request.SetBlob(name, Common::cast_to_blob(pair.second)); - } else { - IE_THROW() << "Unable to set blob " << name << "!"; - } - } -} - -uint32_t get_optimal_number_of_requests(const InferenceEngine::ExecutableNetwork& actual) { +uint32_t get_optimal_number_of_requests(const ov::runtime::ExecutableNetwork& actual) { try { - auto parameter_value = actual.GetMetric(METRIC_KEY(SUPPORTED_METRICS)); + auto parameter_value = actual.get_metric(METRIC_KEY(SUPPORTED_METRICS)); auto supported_metrics = parameter_value.as>(); const std::string key = METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS); if (std::find(supported_metrics.begin(), supported_metrics.end(), key) != supported_metrics.end()) { - parameter_value = actual.GetMetric(key); + parameter_value = actual.get_metric(key); if (parameter_value.is()) return parameter_value.as(); else diff --git a/runtime/bindings/python/src/pyopenvino/core/common.hpp b/runtime/bindings/python/src/pyopenvino/core/common.hpp index 314a8290244581..7e2e0f0dfc95af 100644 --- a/runtime/bindings/python/src/pyopenvino/core/common.hpp +++ b/runtime/bindings/python/src/pyopenvino/core/common.hpp @@ -4,53 +4,43 @@ #pragma once -#include -#include -#include -#include -#include +#include + +#include #include #include -#include + +#include +#include +#include #include "Python.h" #include "ie_common.h" +#include "openvino/runtime/tensor.hpp" +#include "openvino/runtime/executable_network.hpp" +#include "openvino/runtime/infer_request.hpp" +#include "pyopenvino/core/containers.hpp" namespace py = pybind11; namespace Common { - template - void fill_blob(const py::handle& py_array, InferenceEngine::Blob::Ptr blob) - { - py::array_t arr = py::cast(py_array); - if (arr.size() != 0) { - // blob->allocate(); - InferenceEngine::MemoryBlob::Ptr mem_blob = InferenceEngine::as(blob); - std::copy( - arr.data(0), arr.data(0) + arr.size(), mem_blob->rwmap().as()); - } else { - py::print("Empty array!"); - } - } - const std::map& ov_type_to_dtype(); + const std::map& dtype_to_ov_type(); - InferenceEngine::Layout get_layout_from_string(const std::string& layout); + ov::runtime::Tensor tensor_from_numpy(py::array& array, bool shared_memory); - const std::string& get_layout_from_enum(const InferenceEngine::Layout& layout); + py::array as_contiguous(py::array& array, ov::element::Type type); - PyObject* parse_parameter(const InferenceEngine::Parameter& param); + const ov::runtime::Tensor& cast_to_tensor(const py::handle& tensor); - PyObject* parse_parameter(const InferenceEngine::Parameter& param); - - bool is_TBlob(const py::handle& blob); + const Containers::TensorNameMap cast_to_tensor_name_map(const py::dict& inputs); - const std::shared_ptr cast_to_blob(const py::handle& blob); + const Containers::TensorIndexMap cast_to_tensor_index_map(const py::dict& inputs); - void blob_from_numpy(const py::handle& _arr, InferenceEngine::Blob::Ptr &blob); + void set_request_tensors(ov::runtime::InferRequest& request, const py::dict& inputs); - void set_request_blobs(InferenceEngine::InferRequest& request, const py::dict& dictonary); + PyObject* parse_parameter(const InferenceEngine::Parameter& param); - uint32_t get_optimal_number_of_requests(const InferenceEngine::ExecutableNetwork& actual); + uint32_t get_optimal_number_of_requests(const ov::runtime::ExecutableNetwork& actual); }; // namespace Common diff --git a/runtime/bindings/python/src/pyopenvino/core/containers.cpp b/runtime/bindings/python/src/pyopenvino/core/containers.cpp index 096b6074325815..12a50b1caf5331 100644 --- a/runtime/bindings/python/src/pyopenvino/core/containers.cpp +++ b/runtime/bindings/python/src/pyopenvino/core/containers.cpp @@ -1,51 +1,23 @@ - // Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // #include "pyopenvino/core/containers.hpp" -#include #include -PYBIND11_MAKE_OPAQUE(Containers::PyInputsDataMap); -PYBIND11_MAKE_OPAQUE(Containers::PyConstInputsDataMap); -PYBIND11_MAKE_OPAQUE(Containers::PyOutputsDataMap); -PYBIND11_MAKE_OPAQUE(Containers::PyResults); +PYBIND11_MAKE_OPAQUE(Containers::TensorIndexMap); +PYBIND11_MAKE_OPAQUE(Containers::TensorNameMap); namespace py = pybind11; namespace Containers { -void regclass_PyInputsDataMap(py::module m) { - auto py_inputs_data_map = py::bind_map(m, "PyInputsDataMap"); - - py_inputs_data_map.def("keys", [](PyInputsDataMap& self) { - return py::make_key_iterator(self.begin(), self.end()); - }); -} - -void regclass_PyConstInputsDataMap(py::module m) { - auto py_const_inputs_data_map = py::bind_map(m, "PyConstInputsDataMap"); - - py_const_inputs_data_map.def("keys", [](PyConstInputsDataMap& self) { - return py::make_key_iterator(self.begin(), self.end()); - }); +void regclass_TensorIndexMap(py::module m) { + py::bind_map(m, "TensorIndexMap"); } -void regclass_PyOutputsDataMap(py::module m) { - auto py_outputs_data_map = py::bind_map(m, "PyOutputsDataMap"); - - py_outputs_data_map.def("keys", [](PyOutputsDataMap& self) { - return py::make_key_iterator(self.begin(), self.end()); - }); -} - -void regclass_PyResults(py::module m) { - auto py_results = py::bind_map(m, "PyResults"); - - py_results.def("keys", [](PyResults& self) { - return py::make_key_iterator(self.begin(), self.end()); - }); +void regclass_TensorNameMap(py::module m) { + py::bind_map(m, "TensorNameMap"); } } // namespace Containers diff --git a/runtime/bindings/python/src/pyopenvino/core/containers.hpp b/runtime/bindings/python/src/pyopenvino/core/containers.hpp index 511d9053ea50fa..e24e7336236cac 100644 --- a/runtime/bindings/python/src/pyopenvino/core/containers.hpp +++ b/runtime/bindings/python/src/pyopenvino/core/containers.hpp @@ -4,28 +4,21 @@ #pragma once -#include #include -#include -#include "ie_data.h" -#include "ie_blob.h" - -namespace py = pybind11; +#include +#include -namespace Containers { - using PyInputsDataMap = std::map>; +#include - using PyConstInputsDataMap = - std::map>; +#include - using PyOutputsDataMap = - std::map>; +namespace py = pybind11; - using PyResults = - std::map>; +namespace Containers { + using TensorIndexMap = std::map; + using TensorNameMap = std::map; + using InferResults = std::vector; - void regclass_PyInputsDataMap(py::module m); - void regclass_PyConstInputsDataMap(py::module m); - void regclass_PyOutputsDataMap(py::module m); - void regclass_PyResults(py::module m); -} \ No newline at end of file + void regclass_TensorIndexMap(py::module m); + void regclass_TensorNameMap(py::module m); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/core.cpp b/runtime/bindings/python/src/pyopenvino/core/core.cpp new file mode 100644 index 00000000000000..46eed93d02b46f --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/core.cpp @@ -0,0 +1,121 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "pyopenvino/core/core.hpp" + +#include +#include + +#include +#include + +#include "common.hpp" + +namespace py = pybind11; + +using ConfigMap = std::map; + +std::string to_string(py::handle handle) { + auto encodedString = PyUnicode_AsUTF8String(handle.ptr()); + return PyBytes_AsString(encodedString); +} + +void regclass_Core(py::module m) { + py::class_> cls(m, "Core"); + + cls.def(py::init(), py::arg("xml_config_file") = ""); + + cls.def("set_config", + (void (ov::runtime::Core::*)(const ConfigMap&, const std::string&)) & ov::runtime::Core::set_config, + py::arg("config"), + py::arg("device_name") = ""); + + cls.def( + "compile_model", + (ov::runtime::ExecutableNetwork( + ov::runtime::Core::*)(const std::shared_ptr&, const std::string&, const ConfigMap&)) & + ov::runtime::Core::compile_model, + py::arg("model"), + py::arg("device_name"), + py::arg("config") = py::dict()); + + cls.def("compile_model", + (ov::runtime::ExecutableNetwork( + ov::runtime::Core::*)(const std::string&, const std::string&, const ConfigMap&)) & + ov::runtime::Core::compile_model, + py::arg("model_path"), + py::arg("device_name"), + py::arg("config") = py::dict()); + + cls.def("get_versions", &ov::runtime::Core::get_versions); + + cls.def("read_model", + (std::shared_ptr(ov::runtime::Core::*)(const std::string&, const std::string&) const) & + ov::runtime::Core::read_model, + py::arg("model"), + py::arg("weights") = ""); + + cls.def( + "read_model", + (std::shared_ptr(ov::runtime::Core::*)(const std::string&, const ov::runtime::Tensor&) const) & + ov::runtime::Core::read_model, + py::arg("model"), + py::arg("weights")); + + cls.def( + "read_model", + [](ov::runtime::Core& self, py::object model, py::object weights) { + return self.read_model(py::str(model), py::str(weights)); + }, + py::arg("model"), + py::arg("weights") = ""); + + cls.def( + "import_model", + (ov::runtime::ExecutableNetwork(ov::runtime::Core::*)(std::istream&, const std::string&, const ConfigMap&)) & + ov::runtime::Core::import_model, + py::arg("model_file"), + py::arg("device_name"), + py::arg("config") = py::none()); + + cls.def( + "get_config", + [](ov::runtime::Core& self, const std::string& device_name, const std::string& name) -> py::handle { + return Common::parse_parameter(self.get_config(device_name, name)); + }, + py::arg("device_name"), + py::arg("name")); + + cls.def( + "get_metric", + [](ov::runtime::Core& self, const std::string device_name, const std::string name) -> py::handle { + return Common::parse_parameter(self.get_metric(device_name, name)); + }, + py::arg("device_name"), + py::arg("name")); + + cls.def("register_plugin", &ov::runtime::Core::register_plugin, py::arg("plugin_name"), py::arg("device_name")); + + cls.def("register_plugins", &ov::runtime::Core::register_plugins, py::arg("xml_config_file")); + + cls.def("unload_plugin", &ov::runtime::Core::unload_plugin, py::arg("device_name")); + + cls.def( + "query_model", + (ov::runtime::SupportedOpsMap( + ov::runtime::Core::*)(const std::shared_ptr&, const std::string&, const ConfigMap&)) & + ov::runtime::Core::query_model, + py::arg("model"), + py::arg("device_name"), + py::arg("config") = py::dict()); + + cls.def( + "add_extension", + [](ov::runtime::Core& self, const std::string& library_path) { + return self.add_extension(library_path); + }, + py::arg("library_path")); + + cls.def_property_readonly("available_devices", &ov::runtime::Core::get_available_devices); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_core.hpp b/runtime/bindings/python/src/pyopenvino/core/core.hpp similarity index 100% rename from runtime/bindings/python/src/pyopenvino/core/ie_core.hpp rename to runtime/bindings/python/src/pyopenvino/core/core.hpp diff --git a/runtime/bindings/python/src/pyopenvino/core/executable_network.cpp b/runtime/bindings/python/src/pyopenvino/core/executable_network.cpp new file mode 100644 index 00000000000000..37d6811f38dbce --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/executable_network.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "openvino/runtime/executable_network.hpp" + +#include + +#include "common.hpp" +#include "pyopenvino/core/containers.hpp" +#include "pyopenvino/core/infer_request.hpp" + +PYBIND11_MAKE_OPAQUE(Containers::TensorIndexMap); +PYBIND11_MAKE_OPAQUE(Containers::TensorNameMap); + +namespace py = pybind11; + +void regclass_ExecutableNetwork(py::module m) { + py::class_> cls( + m, + "ExecutableNetwork"); + + cls.def(py::init([](ov::runtime::ExecutableNetwork& other) { + return other; + }), + py::arg("other")); + + cls.def("create_infer_request", [](ov::runtime::ExecutableNetwork& self) { + return InferRequestWrapper(self.create_infer_request(), self.inputs(), self.outputs()); + }); + + cls.def( + "infer_new_request", + [](ov::runtime::ExecutableNetwork& self, const py::dict& inputs) { + auto request = self.create_infer_request(); + // Update inputs if there are any + Common::set_request_tensors(request, inputs); + request.infer(); + + Containers::InferResults results; + for (const auto out : self.outputs()) { + results.push_back(request.get_tensor(out)); + } + return results; + }, + py::arg("inputs")); + + cls.def("export_model", &ov::runtime::ExecutableNetwork::export_model, py::arg("network_model")); + + cls.def( + "get_config", + [](ov::runtime::ExecutableNetwork& self, const std::string& name) -> py::handle { + return Common::parse_parameter(self.get_config(name)); + }, + py::arg("name")); + + cls.def( + "get_metric", + [](ov::runtime::ExecutableNetwork& self, const std::string& name) -> py::handle { + return Common::parse_parameter(self.get_metric(name)); + }, + py::arg("name")); + + cls.def("get_runtime_function", &ov::runtime::ExecutableNetwork::get_runtime_function); + + cls.def_property_readonly("inputs", &ov::runtime::ExecutableNetwork::inputs); + + cls.def("input", + (ov::Output(ov::runtime::ExecutableNetwork::*)() const) & + ov::runtime::ExecutableNetwork::input); + + cls.def("input", + (ov::Output(ov::runtime::ExecutableNetwork::*)(size_t) const) & + ov::runtime::ExecutableNetwork::input, + py::arg("i")); + + cls.def("input", + (ov::Output(ov::runtime::ExecutableNetwork::*)(const std::string&) const) & + ov::runtime::ExecutableNetwork::input, + py::arg("tensor_name")); + + cls.def_property_readonly("outputs", &ov::runtime::ExecutableNetwork::outputs); + + cls.def("output", + (ov::Output(ov::runtime::ExecutableNetwork::*)() const) & + ov::runtime::ExecutableNetwork::output); + + cls.def("output", + (ov::Output(ov::runtime::ExecutableNetwork::*)(size_t) const) & + ov::runtime::ExecutableNetwork::output, + py::arg("i")); + + cls.def("output", + (ov::Output(ov::runtime::ExecutableNetwork::*)(const std::string&) const) & + ov::runtime::ExecutableNetwork::output, + py::arg("tensor_name")); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_executable_network.hpp b/runtime/bindings/python/src/pyopenvino/core/executable_network.hpp similarity index 100% rename from runtime/bindings/python/src/pyopenvino/core/ie_executable_network.hpp rename to runtime/bindings/python/src/pyopenvino/core/executable_network.hpp diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_blob.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_blob.cpp deleted file mode 100644 index 11e6c7634a3f23..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_blob.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "ie_blob.h" - -#include -#include -#include - -#include - -#include "pyopenvino/core/ie_blob.hpp" -#include "pyopenvino/core/tensor_description.hpp" - -namespace py = pybind11; - -void regclass_Blob(py::module m) { - py::class_> cls(m, "Blob"); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_blob.hpp b/runtime/bindings/python/src/pyopenvino/core/ie_blob.hpp deleted file mode 100644 index b5efc4403869b2..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_blob.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include - -#include -#include -#include - -#include "ie_blob.h" -#include "ie_common.h" -#include "ie_layouts.h" -#include "ie_precision.hpp" - -#include "pyopenvino/core/tensor_description.hpp" - -namespace py = pybind11; - -void regclass_Blob(py::module m); - -template -void regclass_TBlob(py::module m, std::string typestring) -{ - auto pyclass_name = py::detail::c_str((std::string("TBlob") + typestring)); - - py::class_, std::shared_ptr>> cls( - m, pyclass_name); - - cls.def(py::init( - [](const InferenceEngine::TensorDesc& tensorDesc, py::array_t& arr, size_t size = 0) { - auto blob = InferenceEngine::make_shared_blob(tensorDesc); - blob->allocate(); - if (size != 0) { - std::copy(arr.data(0), arr.data(0) + size, blob->rwmap().template as()); - } - return blob; - })); - - cls.def_property_readonly("buffer", [](InferenceEngine::TBlob& self) { - auto blob_ptr = self.buffer().template as(); - auto shape = self.getTensorDesc().getDims(); - return py::array_t(shape, &blob_ptr[0], py::cast(self)); - }); - - cls.def_property_readonly("tensor_desc", - [](InferenceEngine::TBlob& self) { return self.getTensorDesc(); }); - - cls.def("__str__", [](InferenceEngine::TBlob& self) -> std::string { - std::stringstream ss; - auto blob_ptr = self.buffer().template as(); - auto shape = self.getTensorDesc().getDims(); - auto py_arr = py::array_t(shape, &blob_ptr[0], py::cast(self)); - ss << py_arr; - return ss.str(); - }); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_core.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_core.cpp deleted file mode 100644 index 9d37bfb00f7fe3..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_core.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/ie_core.hpp" - -#include - -#include - -#include "common.hpp" - -namespace py = pybind11; - -std::string to_string(py::handle handle) { - auto encodedString = PyUnicode_AsUTF8String(handle.ptr()); - return PyBytes_AsString(encodedString); -} - -void regclass_Core(py::module m) { - py::class_> cls(m, "Core"); - cls.def(py::init()); - cls.def(py::init()); - - cls.def( - "set_config", - [](InferenceEngine::Core& self, const py::dict& config, const std::string& device_name) { - std::map config_map; - for (auto item : config) { - config_map[to_string(item.first)] = to_string(item.second); - } - self.SetConfig(config_map, device_name); - }, - py::arg("config"), - py::arg("device_name")); - - cls.def( - "load_network", - [](InferenceEngine::Core& self, - const InferenceEngine::CNNNetwork& network, - const std::string& device_name, - const std::map& config) { - return self.LoadNetwork(network, device_name, config); - }, - py::arg("network"), - py::arg("device_name"), - py::arg("config") = py::dict()); - - cls.def( - "add_extension", - [](InferenceEngine::Core& self, const std::string& extension_path, const std::string& device_name) { - auto extension_ptr = InferenceEngine::make_so_pointer(extension_path); - auto extension = std::dynamic_pointer_cast(extension_ptr); - self.AddExtension(extension, device_name); - }, - py::arg("extension_path"), - py::arg("device_name")); - - cls.def( - "get_versions", - [](InferenceEngine::Core& self, const std::string& device_name) { - return self.GetVersions(device_name); - }, - py::arg("device_name")); - - cls.def( - "read_network", - [](InferenceEngine::Core& self, py::bytes model, py::bytes weights) { - InferenceEngine::MemoryBlob::Ptr weights_blob; - if (weights) { - std::string weights_bytes = weights; - uint8_t* bin = (uint8_t*)weights_bytes.c_str(); - size_t bin_size = weights_bytes.length(); - InferenceEngine::TensorDesc tensorDesc(InferenceEngine::Precision::U8, - {bin_size}, - InferenceEngine::Layout::C); - weights_blob = InferenceEngine::make_shared_blob(tensorDesc); - weights_blob->allocate(); - memcpy(weights_blob->rwmap().as(), bin, bin_size); - } - return self.ReadNetwork(model, weights_blob); - }, - py::arg("model"), - py::arg("weights")); - - cls.def( - "read_network", - [](InferenceEngine::Core& self, const std::string& model, const std::string& weights) { - return self.ReadNetwork(model, weights); - }, - py::arg("model"), - py::arg("weights") = ""); - - cls.def( - "read_network", - [](InferenceEngine::Core& self, const std::string& model, py::handle blob) { - return self.ReadNetwork(model, Common::cast_to_blob(blob)); - }, - py::arg("model"), - py::arg("blob")); - - cls.def( - "read_network", - [](InferenceEngine::Core& self, py::object model, py::object weights) { - return self.ReadNetwork(py::str(model), py::str(weights)); - }, - py::arg("model"), - py::arg("weights") = ""); - - cls.def( - "import_network", - [](InferenceEngine::Core& self, - const std::string& model_file, - const std::string& device_name, - const std::map& config) { - return self.ImportNetwork(model_file, device_name, config); - }, - py::arg("model_file"), - py::arg("device_name"), - py::arg("config") = py::none()); - - cls.def( - "get_config", - [](InferenceEngine::Core& self, const std::string& device_name, const std::string& config_name) -> py::handle { - return Common::parse_parameter(self.GetConfig(device_name, config_name)); - }, - py::arg("device_name"), - py::arg("config_name")); - - cls.def( - "get_metric", - [](InferenceEngine::Core& self, std::string device_name, std::string metric_name) -> py::handle { - return Common::parse_parameter(self.GetMetric(device_name, metric_name)); - }, - py::arg("device_name"), - py::arg("metric_name")); - - cls.def("register_plugin", - &InferenceEngine::Core::RegisterPlugin, - py::arg("plugin_name"), - py::arg("device_name") = py::str()); - - cls.def("register_plugins", &InferenceEngine::Core::RegisterPlugins); - - cls.def("unregister_plugin", &InferenceEngine::Core::UnregisterPlugin, py::arg("device_name")); - - cls.def( - "query_network", - [](InferenceEngine::Core& self, - const InferenceEngine::CNNNetwork& network, - const std::string& device_name, - const std::map& config) { - return self.QueryNetwork(network, device_name, config).supportedLayersMap; - }, - py::arg("network"), - py::arg("device_name"), - py::arg("config") = py::dict()); - - cls.def_property_readonly("available_devices", &InferenceEngine::Core::GetAvailableDevices); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_data.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_data.cpp deleted file mode 100644 index d1fd3bf760dda4..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_data.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/ie_data.hpp" - -#include -#include - -#include "common.hpp" - -namespace py = pybind11; - -void regclass_Data(py::module m) { - py::class_> cls(m, "DataPtr"); - - cls.def_property( - "layout", - [](InferenceEngine::Data& self) { - return Common::get_layout_from_enum(self.getLayout()); - }, - [](InferenceEngine::Data& self, const std::string& layout) { - self.setLayout(Common::get_layout_from_string(layout)); - }); - - cls.def_property( - "precision", - [](InferenceEngine::Data& self) { - return self.getPrecision().name(); - }, - [](InferenceEngine::Data& self, const std::string& precision) { - self.setPrecision(InferenceEngine::Precision::FromStr(precision)); - }); - - cls.def_property_readonly("shape", &InferenceEngine::Data::getDims); - - cls.def_property_readonly("name", &InferenceEngine::Data::getName); - // cls.def_property_readonly("initialized", ); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_executable_network.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_executable_network.cpp deleted file mode 100644 index 37199110f09e68..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_executable_network.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "pyopenvino/core/ie_executable_network.hpp" - -#include -#include - -#include "common.hpp" -#include "pyopenvino/core/containers.hpp" -#include "pyopenvino/core/ie_infer_request.hpp" -#include "pyopenvino/core/ie_input_info.hpp" - -namespace py = pybind11; - -void regclass_ExecutableNetwork(py::module m) { - py::class_> cls( - m, - "ExecutableNetwork"); - - cls.def("create_infer_request", [](InferenceEngine::ExecutableNetwork& self) { - auto request = InferRequestWrapper(self.CreateInferRequest()); - // Get Inputs and Outputs info from executable network - request._inputsInfo = self.GetInputsInfo(); - request._outputsInfo = self.GetOutputsInfo(); - // request.user_callback_defined = false; - return request; - }); - - cls.def( - "_infer", - [](InferenceEngine::ExecutableNetwork& self, const py::dict& inputs) { - // Create temporary InferRequest - auto request = self.CreateInferRequest(); - // Update inputs if there are any - if (!inputs.empty()) { - Common::set_request_blobs(request, inputs); //, self.GetInputsInfo()); - } - // Call Infer function - request.Infer(); - // Get output Blobs and return - Containers::PyResults results; - InferenceEngine::ConstOutputsDataMap outputsInfo = self.GetOutputsInfo(); - for (auto& out : outputsInfo) { - results[out.first] = request.GetBlob(out.first); - } - return results; - }, - py::arg("inputs")); - - cls.def("get_exec_graph_info", &InferenceEngine::ExecutableNetwork::GetExecGraphInfo); - - cls.def( - "export", - [](InferenceEngine::ExecutableNetwork& self, const std::string& modelFileName) { - self.Export(modelFileName); - }, - py::arg("model_file")); - - cls.def( - "get_config", - [](InferenceEngine::ExecutableNetwork& self, const std::string& config_name) -> py::handle { - return Common::parse_parameter(self.GetConfig(config_name)); - }, - py::arg("config_name")); - - cls.def( - "get_metric", - [](InferenceEngine::ExecutableNetwork& self, const std::string& metric_name) -> py::handle { - return Common::parse_parameter(self.GetMetric(metric_name)); - }, - py::arg("metric_name")); - - cls.def_property_readonly("input_info", [](InferenceEngine::ExecutableNetwork& self) { - Containers::PyConstInputsDataMap inputs; - const InferenceEngine::ConstInputsDataMap& inputsInfo = self.GetInputsInfo(); - for (const auto& in : inputsInfo) { - inputs[in.first] = in.second; - } - return inputs; - }); - - cls.def_property_readonly("output_info", [](InferenceEngine::ExecutableNetwork& self) { - Containers::PyOutputsDataMap outputs; - InferenceEngine::ConstOutputsDataMap outputsInfo = self.GetOutputsInfo(); - for (auto& out : outputsInfo) { - outputs[out.first] = out.second; - } - return outputs; - }); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_infer_queue.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_infer_queue.cpp deleted file mode 100644 index d54e7cce69c9ff..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_infer_queue.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "pyopenvino/core/ie_infer_queue.hpp" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pyopenvino/core/common.hpp" -#include "pyopenvino/core/ie_infer_request.hpp" - -#define INVALID_ID -1 - -namespace py = pybind11; - -class InferQueue { -public: - InferQueue(std::vector requests, - std::queue idle_handles, - std::vector user_ids) - : _requests(requests), - _idle_handles(idle_handles), - _user_ids(user_ids) { - this->setDefaultCallbacks(); - _last_id = -1; - } - - ~InferQueue() { - _requests.clear(); - } - - bool _is_ready() { - py::gil_scoped_release release; - std::unique_lock lock(_mutex); - _cv.wait(lock, [this] { - return !(_idle_handles.empty()); - }); - - return !(_idle_handles.empty()); - } - - py::dict _getIdleRequestInfo() { - py::gil_scoped_release release; - std::unique_lock lock(_mutex); - _cv.wait(lock, [this] { - return !(_idle_handles.empty()); - }); - - size_t request_id = _idle_handles.front(); - - InferenceEngine::StatusCode status = - _requests[request_id]._request.Wait(InferenceEngine::IInferRequest::WaitMode::STATUS_ONLY); - - if (status == InferenceEngine::StatusCode::RESULT_NOT_READY) { - status = _requests[request_id]._request.Wait(InferenceEngine::IInferRequest::WaitMode::RESULT_READY); - } - - py::dict request_info = py::dict(); - request_info["id"] = request_id; - request_info["status"] = status; - - return request_info; - } - - size_t getIdleRequestId() { - // Wait for any of _idle_handles - py::gil_scoped_release release; - std::unique_lock lock(_mutex); - _cv.wait(lock, [this] { - return !(_idle_handles.empty()); - }); - - size_t idle_request_id = _idle_handles.front(); - _idle_handles.pop(); - - return idle_request_id; - } - - std::vector waitAll() { - // Wait for all requests to return with callback thus updating - // _idle_handles so it matches the size of requests - py::gil_scoped_release release; - std::unique_lock lock(_mutex); - _cv.wait(lock, [this] { - return _idle_handles.size() == _requests.size(); - }); - - std::vector statuses; - - for (size_t handle = 0; handle < _requests.size(); handle++) { - statuses.push_back(_requests[handle]._request.Wait(InferenceEngine::IInferRequest::WaitMode::RESULT_READY)); - } - - return statuses; - } - - void setDefaultCallbacks() { - for (size_t handle = 0; handle < _requests.size(); handle++) { - _requests[handle]._request.SetCompletionCallback([this, handle /* ... */]() { - _requests[handle]._endTime = Time::now(); - // Add idle handle to queue - _idle_handles.push(handle); - // Notify locks in getIdleRequestId() or waitAll() functions - _cv.notify_one(); - }); - } - } - - void setCustomCallbacks(py::function f_callback) { - for (size_t handle = 0; handle < _requests.size(); handle++) { - _requests[handle]._request.SetCompletionCallback([this, f_callback, handle /* ... */]() { - _requests[handle]._endTime = Time::now(); - InferenceEngine::StatusCode statusCode = - _requests[handle]._request.Wait(InferenceEngine::IInferRequest::WaitMode::STATUS_ONLY); - if (statusCode == InferenceEngine::StatusCode::RESULT_NOT_READY) { - statusCode = InferenceEngine::StatusCode::OK; - } - // Acquire GIL, execute Python function - py::gil_scoped_acquire acquire; - f_callback(_requests[handle], statusCode, _user_ids[handle]); - // Add idle handle to queue - _idle_handles.push(handle); - // Notify locks in getIdleRequestId() or waitAll() functions - _cv.notify_one(); - }); - } - } - - std::vector _requests; - std::queue _idle_handles; - std::vector _user_ids; // user ID can be any Python object - size_t _last_id; - std::mutex _mutex; - std::condition_variable _cv; -}; - -void regclass_InferQueue(py::module m) { - py::class_> cls(m, "InferQueue"); - - cls.def(py::init([](InferenceEngine::ExecutableNetwork& net, size_t jobs) { - if (jobs == 0) { - const InferenceEngine::ExecutableNetwork& _net = net; - jobs = (size_t)Common::get_optimal_number_of_requests(_net); - } - - std::vector requests; - std::queue idle_handles; - std::vector user_ids(jobs); - - for (size_t handle = 0; handle < jobs; handle++) { - auto request = InferRequestWrapper(net.CreateInferRequest()); - // Get Inputs and Outputs info from executable network - request._inputsInfo = net.GetInputsInfo(); - request._outputsInfo = net.GetOutputsInfo(); - - requests.push_back(request); - idle_handles.push(handle); - } - - return new InferQueue(requests, idle_handles, user_ids); - }), - py::arg("network"), - py::arg("jobs") = 0); - - cls.def( - "_async_infer", - [](InferQueue& self, const py::dict inputs, py::object userdata) { - // getIdleRequestId function has an intention to block InferQueue - // until there is at least one idle (free to use) InferRequest - auto handle = self.getIdleRequestId(); - // Set new inputs label/id from user - self._user_ids[handle] = userdata; - // Update inputs of picked InferRequest - if (!inputs.empty()) { - Common::set_request_blobs(self._requests[handle]._request, inputs); - } - // Now GIL can be released - we are NOT working with Python objects in this block - { - py::gil_scoped_release release; - self._requests[handle]._startTime = Time::now(); - // Start InferRequest in asynchronus mode - self._requests[handle]._request.StartAsync(); - } - }, - py::arg("inputs"), - py::arg("userdata")); - - cls.def("is_ready", [](InferQueue& self) { - return self._is_ready(); - }); - - cls.def("wait_all", [](InferQueue& self) { - return self.waitAll(); - }); - - cls.def("get_idle_request_info", [](InferQueue& self) { - return self._getIdleRequestInfo(); - }); - - cls.def("set_infer_callback", [](InferQueue& self, py::function f_callback) { - self.setCustomCallbacks(f_callback); - }); - - cls.def("__len__", [](InferQueue& self) { - return self._requests.size(); - }); - - cls.def( - "__iter__", - [](InferQueue& self) { - return py::make_iterator(self._requests.begin(), self._requests.end()); - }, - py::keep_alive<0, 1>()); /* Keep set alive while iterator is used */ - - cls.def("__getitem__", [](InferQueue& self, size_t i) { - return self._requests[i]; - }); - - cls.def_property_readonly("userdata", [](InferQueue& self) { - return self._user_ids; - }); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_infer_queue.hpp b/runtime/bindings/python/src/pyopenvino/core/ie_infer_queue.hpp deleted file mode 100644 index 23aa72fd072496..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_infer_queue.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -namespace py = pybind11; - -void regclass_InferQueue(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_infer_request.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_infer_request.cpp deleted file mode 100644 index f45ddd6a5cd73d..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_infer_request.cpp +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "pyopenvino/core/ie_infer_request.hpp" - -#include -#include - -#include - -#include "pyopenvino/core/common.hpp" -#include "pyopenvino/core/containers.hpp" -#include "pyopenvino/core/ie_executable_network.hpp" -#include "pyopenvino/core/ie_preprocess_info.hpp" - -namespace py = pybind11; - -void regclass_InferRequest(py::module m) { - py::class_> cls(m, "InferRequest"); - - cls.def( - "set_batch", - [](InferRequestWrapper& self, const int size) { - self._request.SetBatch(size); - }, - py::arg("size")); - - cls.def( - "get_blob", - [](InferRequestWrapper& self, const std::string& name) { - return self._request.GetBlob(name); - }, - py::arg("name")); - - cls.def( - "set_blob", - [](InferRequestWrapper& self, const std::string& name, py::handle& blob) { - self._request.SetBlob(name, Common::cast_to_blob(blob)); - }, - py::arg("name"), - py::arg("blob")); - - cls.def( - "set_blob", - [](InferRequestWrapper& self, - const std::string& name, - py::handle& blob, - const InferenceEngine::PreProcessInfo& info) { - self._request.SetBlob(name, Common::cast_to_blob(blob)); - }, - py::arg("name"), - py::arg("blob"), - py::arg("info")); - - cls.def( - "set_input", - [](InferRequestWrapper& self, const py::dict& inputs) { - Common::set_request_blobs(self._request, inputs); - }, - py::arg("inputs")); - - cls.def( - "set_output", - [](InferRequestWrapper& self, const py::dict& results) { - Common::set_request_blobs(self._request, results); - }, - py::arg("results")); - - cls.def( - "_infer", - [](InferRequestWrapper& self, const py::dict& inputs) { - // Update inputs if there are any - if (!inputs.empty()) { - Common::set_request_blobs(self._request, inputs); - } - // Call Infer function - self._startTime = Time::now(); - self._request.Infer(); - self._endTime = Time::now(); - // Get output Blobs and return - Containers::PyResults results; - for (auto& out : self._outputsInfo) { - results[out.first] = self._request.GetBlob(out.first); - } - return results; - }, - py::arg("inputs")); - - cls.def( - "_async_infer", - [](InferRequestWrapper& self, const py::dict inputs, py::object userdata) { - py::gil_scoped_release release; - if (!inputs.empty()) { - Common::set_request_blobs(self._request, inputs); - } - // TODO: check for None so next async infer userdata can be updated - // if (!userdata.empty()) - // { - // if (user_callback_defined) - // { - // self._request.SetCompletionCallback([self, userdata]() { - // // py::gil_scoped_acquire acquire; - // auto statusCode = const_cast(self).Wait( - // InferenceEngine::IInferRequest::WaitMode::STATUS_ONLY); - // self._request.user_callback(self, statusCode, userdata); - // // py::gil_scoped_release release; - // }); - // } - // else - // { - // py::print("There is no callback function!"); - // } - // } - self._startTime = Time::now(); - self._request.StartAsync(); - }, - py::arg("inputs"), - py::arg("userdata")); - - cls.def("cancel", [](InferRequestWrapper& self) { - self._request.Cancel(); - }); - - cls.def( - "wait", - [](InferRequestWrapper& self, int64_t millis_timeout) { - py::gil_scoped_release release; - return self._request.Wait(millis_timeout); - }, - py::arg("millis_timeout") = InferenceEngine::IInferRequest::WaitMode::RESULT_READY); - - cls.def( - "set_completion_callback", - [](InferRequestWrapper& self, py::function f_callback, py::object userdata) { - self._request.SetCompletionCallback([&self, f_callback, userdata]() { - self._endTime = Time::now(); - InferenceEngine::StatusCode statusCode = - self._request.Wait(InferenceEngine::IInferRequest::WaitMode::STATUS_ONLY); - if (statusCode == InferenceEngine::StatusCode::RESULT_NOT_READY) { - statusCode = InferenceEngine::StatusCode::OK; - } - // Acquire GIL, execute Python function - py::gil_scoped_acquire acquire; - f_callback(self, statusCode, userdata); - }); - }, - py::arg("f_callback"), - py::arg("userdata")); - - cls.def("get_perf_counts", [](InferRequestWrapper& self) { - std::map perfMap; - perfMap = self._request.GetPerformanceCounts(); - py::dict perf_map; - - for (auto it : perfMap) { - py::dict profile_info; - switch (it.second.status) { - case InferenceEngine::InferenceEngineProfileInfo::EXECUTED: - profile_info["status"] = "EXECUTED"; - break; - case InferenceEngine::InferenceEngineProfileInfo::NOT_RUN: - profile_info["status"] = "NOT_RUN"; - break; - case InferenceEngine::InferenceEngineProfileInfo::OPTIMIZED_OUT: - profile_info["status"] = "OPTIMIZED_OUT"; - break; - default: - profile_info["status"] = "UNKNOWN"; - } - profile_info["exec_type"] = it.second.exec_type; - profile_info["layer_type"] = it.second.layer_type; - profile_info["cpu_time"] = it.second.cpu_uSec; - profile_info["real_time"] = it.second.realTime_uSec; - profile_info["execution_index"] = it.second.execution_index; - perf_map[it.first.c_str()] = profile_info; - } - return perf_map; - }); - - cls.def( - "preprocess_info", - [](InferRequestWrapper& self, const std::string& name) { - return self._request.GetPreProcess(name); - }, - py::arg("name")); - - // cls.def_property_readonly("preprocess_info", [](InferRequestWrapper& self) { - // - // }); - - cls.def_property_readonly("input_blobs", [](InferRequestWrapper& self) { - Containers::PyResults input_blobs; - for (auto& in : self._inputsInfo) { - input_blobs[in.first] = self._request.GetBlob(in.first); - } - return input_blobs; - }); - - cls.def_property_readonly("output_blobs", [](InferRequestWrapper& self) { - Containers::PyResults output_blobs; - for (auto& out : self._outputsInfo) { - output_blobs[out.first] = self._request.GetBlob(out.first); - } - return output_blobs; - }); - - cls.def_property_readonly("latency", [](InferRequestWrapper& self) { - return self.getLatency(); - }); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_infer_request.hpp b/runtime/bindings/python/src/pyopenvino/core/ie_infer_request.hpp deleted file mode 100644 index 13afbac440360d..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_infer_request.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include - -#include - -#include -#include -#include - -namespace py = pybind11; - -typedef std::chrono::high_resolution_clock Time; -typedef std::chrono::nanoseconds ns; - -class InferRequestWrapper { -public: - InferRequestWrapper(InferenceEngine::InferRequest request) - : _request(request) - { - } - // ~InferRequestWrapper() = default; - - // bool user_callback_defined; - // py::function user_callback; - - double getLatency() { - auto execTime = std::chrono::duration_cast(_endTime - _startTime); - return static_cast(execTime.count()) * 0.000001; - } - - InferenceEngine::InferRequest _request; - InferenceEngine::ConstInputsDataMap _inputsInfo; - InferenceEngine::ConstOutputsDataMap _outputsInfo; - Time::time_point _startTime; - Time::time_point _endTime; -}; - -void regclass_InferRequest(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_input_info.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_input_info.cpp deleted file mode 100644 index d47020b537a098..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_input_info.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/ie_input_info.hpp" - -#include - -#include - -#include "common.hpp" - -namespace py = pybind11; - -class ConstInputInfoWrapper { -public: - ConstInputInfoWrapper() = default; - ~ConstInputInfoWrapper() = default; - const InferenceEngine::InputInfo& cref() const { - return value; - } - -protected: - const InferenceEngine::InputInfo& ref() { - return this->value; - } - const InferenceEngine::InputInfo value = InferenceEngine::InputInfo(); -}; - -void regclass_InputInfo(py::module m) { - // Workaround for constant class - py::class_> cls_const(m, "InputInfoCPtr"); - - cls_const.def(py::init<>()); - - cls_const.def_property_readonly("input_data", [](const ConstInputInfoWrapper& self) { - return self.cref().getInputData(); - }); - cls_const.def_property_readonly("precision", [](const ConstInputInfoWrapper& self) { - return self.cref().getPrecision().name(); - }); - cls_const.def_property_readonly("tensor_desc", [](const ConstInputInfoWrapper& self) { - return self.cref().getTensorDesc(); - }); - cls_const.def_property_readonly("name", [](const ConstInputInfoWrapper& self) { - return self.cref().name(); - }); - // Mutable version - py::class_> cls(m, "InputInfoPtr"); - - cls.def(py::init<>()); - - cls.def_property("input_data", - &InferenceEngine::InputInfo::getInputData, - &InferenceEngine::InputInfo::setInputData); - cls.def_property( - "layout", - [](InferenceEngine::InputInfo& self) { - return Common::get_layout_from_enum(self.getLayout()); - }, - [](InferenceEngine::InputInfo& self, const std::string& layout) { - self.setLayout(Common::get_layout_from_string(layout)); - }); - cls.def_property( - "precision", - [](InferenceEngine::InputInfo& self) { - return self.getPrecision().name(); - }, - [](InferenceEngine::InputInfo& self, const std::string& precision) { - self.setPrecision(InferenceEngine::Precision::FromStr(precision)); - }); - cls.def_property_readonly("tensor_desc", &InferenceEngine::InputInfo::getTensorDesc); - cls.def_property_readonly("name", &InferenceEngine::InputInfo::name); - cls.def_property_readonly("preprocess_info", [](InferenceEngine::InputInfo& self) { - InferenceEngine::PreProcessInfo& preprocess = self.getPreProcess(); - return preprocess; - }); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_network.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_network.cpp deleted file mode 100644 index b57765f19cf55c..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_network.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/ie_network.hpp" - -#include -#include -#include - -#include - -#include "openvino/core/function.hpp" -#include "pyopenvino/core/containers.hpp" -#include "pyopenvino/core/ie_input_info.hpp" - -namespace py = pybind11; - -void regclass_IENetwork(py::module m) { - py::class_> cls(m, "IENetwork"); - cls.def(py::init()); - - cls.def(py::init([](std::shared_ptr& function) { - InferenceEngine::CNNNetwork cnnNetwork(function); - return std::make_shared(cnnNetwork); - })); - - cls.def("reshape", - [](InferenceEngine::CNNNetwork& self, const std::map>& input_shapes) { - self.reshape(input_shapes); - }); - - cls.def( - "add_outputs", - [](InferenceEngine::CNNNetwork& self, py::handle& outputs) { - int i = 0; - py::list _outputs; - if (!py::isinstance(outputs)) { - if (py::isinstance(outputs)) { - _outputs.append(outputs.cast()); - } else if (py::isinstance(outputs)) { - _outputs.append(outputs.cast()); - } - } else { - _outputs = outputs.cast(); - } - for (py::handle output : _outputs) { - if (py::isinstance(_outputs[i])) { - self.addOutput(output.cast(), 0); - } else if (py::isinstance(output)) { - py::tuple output_tuple = output.cast(); - self.addOutput(output_tuple[0].cast(), output_tuple[1].cast()); - } else { - IE_THROW() << "Incorrect type " << output.get_type() << "for layer to add at index " << i - << ". Expected string with layer name or tuple with two elements: layer name as " - "first element and port id as second"; - } - i++; - } - }, - py::arg("outputs")); - cls.def("add_output", &InferenceEngine::CNNNetwork::addOutput, py::arg("layer_name"), py::arg("output_index") = 0); - - cls.def( - "serialize", - [](InferenceEngine::CNNNetwork& self, const std::string& path_to_xml, const std::string& path_to_bin) { - self.serialize(path_to_xml, path_to_bin); - }, - py::arg("path_to_xml"), - py::arg("path_to_bin") = ""); - - cls.def("get_function", [](InferenceEngine::CNNNetwork& self) { - return self.getFunction(); - }); - - cls.def("get_ov_name_for_tensor", &InferenceEngine::CNNNetwork::getOVNameForTensor, py::arg("orig_name")); - - cls.def_property("batch_size", - &InferenceEngine::CNNNetwork::getBatchSize, - &InferenceEngine::CNNNetwork::setBatchSize); - - cls.def_property_readonly("input_info", [](InferenceEngine::CNNNetwork& self) { - Containers::PyInputsDataMap inputs; - const InferenceEngine::InputsDataMap& inputsInfo = self.getInputsInfo(); - for (auto& in : inputsInfo) { - inputs[in.first] = in.second; - } - return inputs; - }); - - cls.def_property_readonly("outputs", [](InferenceEngine::CNNNetwork& self) { - return self.getOutputsInfo(); - }); - - cls.def_property_readonly("name", &InferenceEngine::CNNNetwork::getName); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_preprocess_info.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_preprocess_info.cpp deleted file mode 100644 index 7accf2f2b66075..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_preprocess_info.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/ie_preprocess_info.hpp" - -#include -#include - -#include - -#include "pyopenvino/core/common.hpp" - -namespace py = pybind11; - -void regclass_PreProcessInfo(py::module m) { - py::class_>( - m, - "PreProcessChannel") - .def_readwrite("std_scale", &InferenceEngine::PreProcessChannel::stdScale) - .def_readwrite("mean_value", &InferenceEngine::PreProcessChannel::meanValue) - .def_readwrite("mean_data", &InferenceEngine::PreProcessChannel::meanData); - - py::class_ cls(m, "PreProcessInfo"); - - cls.def(py::init()); - cls.def("__getitem__", [](InferenceEngine::PreProcessInfo& self, size_t& index) { - return self[index]; - }); - cls.def("get_number_of_channels", &InferenceEngine::PreProcessInfo::getNumberOfChannels); - cls.def("init", &InferenceEngine::PreProcessInfo::init); - cls.def("set_mean_image", [](InferenceEngine::PreProcessInfo& self, py::handle meanImage) { - self.setMeanImage(Common::cast_to_blob(meanImage)); - }); - cls.def("set_mean_image_for_channel", - [](InferenceEngine::PreProcessInfo& self, py::handle meanImage, const size_t channel) { - self.setMeanImageForChannel(Common::cast_to_blob(meanImage), channel); - }); - cls.def_property("mean_variant", - &InferenceEngine::PreProcessInfo::getMeanVariant, - &InferenceEngine::PreProcessInfo::setVariant); - cls.def_property("resize_algorithm", - &InferenceEngine::PreProcessInfo::getResizeAlgorithm, - &InferenceEngine::PreProcessInfo::setResizeAlgorithm); - cls.def_property("color_format", - &InferenceEngine::PreProcessInfo::getColorFormat, - &InferenceEngine::PreProcessInfo::setColorFormat); - - py::enum_(m, "MeanVariant") - .value("MEAN_IMAGE", InferenceEngine::MeanVariant::MEAN_IMAGE) - .value("MEAN_VALUE", InferenceEngine::MeanVariant::MEAN_VALUE) - .value("NONE", InferenceEngine::MeanVariant::NONE) - .export_values(); - - py::enum_(m, "ResizeAlgorithm") - .value("NO_RESIZE", InferenceEngine::ResizeAlgorithm::NO_RESIZE) - .value("RESIZE_BILINEAR", InferenceEngine::ResizeAlgorithm::RESIZE_BILINEAR) - .value("RESIZE_AREA", InferenceEngine::ResizeAlgorithm::RESIZE_AREA) - .export_values(); - - py::enum_(m, "ColorFormat") - .value("RAW", InferenceEngine::ColorFormat::RAW) - .value("RGB", InferenceEngine::ColorFormat::RGB) - .value("BGR", InferenceEngine::ColorFormat::BGR) - .value("RGBX", InferenceEngine::ColorFormat::RGBX) - .value("BGRX", InferenceEngine::ColorFormat::BGRX) - .value("NV12", InferenceEngine::ColorFormat::NV12) - .value("I420", InferenceEngine::ColorFormat::I420) - .export_values(); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_version.cpp b/runtime/bindings/python/src/pyopenvino/core/ie_version.cpp deleted file mode 100644 index 158cda68ceaaef..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/ie_version.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/ie_version.hpp" - -#include - -namespace py = pybind11; - -void regclass_Version(py::module m) { - py::class_ cls(m, "Version"); - - cls.def_readonly("build_number", &InferenceEngine::Version::buildNumber); - cls.def_readonly("description", &InferenceEngine::Version::description); - cls.def_readwrite("api_version", &InferenceEngine::Version::apiVersion); - - cls.def_property_readonly("major", [](InferenceEngine::Version& self) { - return IE_VERSION_MAJOR; - }); - - cls.def_property_readonly("minor", [](InferenceEngine::Version& self) { - return IE_VERSION_MINOR; - }); -} \ No newline at end of file diff --git a/runtime/bindings/python/src/pyopenvino/core/infer_request.cpp b/runtime/bindings/python/src/pyopenvino/core/infer_request.cpp new file mode 100644 index 00000000000000..65ed43e8499097 --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/infer_request.cpp @@ -0,0 +1,270 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "pyopenvino/core/infer_request.hpp" + +#include +#include +#include +#include + +#include + +#include "pyopenvino/core/common.hpp" +#include "pyopenvino/core/containers.hpp" + +PYBIND11_MAKE_OPAQUE(Containers::TensorIndexMap); +PYBIND11_MAKE_OPAQUE(Containers::TensorNameMap); + +namespace py = pybind11; + +void regclass_InferRequest(py::module m) { + py::class_> cls(m, "InferRequest"); + + cls.def(py::init([](InferRequestWrapper& other) { + return other; + }), + py::arg("other")); + + cls.def( + "set_tensors", + [](InferRequestWrapper& self, const py::dict& inputs) { + auto tensor_map = Common::cast_to_tensor_name_map(inputs); + for (auto&& input : tensor_map) { + self._request.set_tensor(input.first, input.second); + } + }, + py::arg("inputs")); + + cls.def( + "set_output_tensors", + [](InferRequestWrapper& self, const py::dict& outputs) { + auto outputs_map = Common::cast_to_tensor_index_map(outputs); + for (auto&& output : outputs_map) { + self._request.set_output_tensor(output.first, output.second); + } + }, + py::arg("outputs")); + + cls.def( + "set_input_tensors", + [](InferRequestWrapper& self, const py::dict& inputs) { + auto inputs_map = Common::cast_to_tensor_index_map(inputs); + for (auto&& input : inputs_map) { + self._request.set_input_tensor(input.first, input.second); + } + }, + py::arg("inputs")); + + cls.def( + "infer", + [](InferRequestWrapper& self, const py::dict& inputs) { + // Update inputs if there are any + Common::set_request_tensors(self._request, inputs); + // Call Infer function + self._start_time = Time::now(); + self._request.infer(); + self._end_time = Time::now(); + Containers::InferResults results; + for (auto& out : self._outputs) { + results.push_back(self._request.get_tensor(out)); + } + return results; + }, + py::arg("inputs")); + + cls.def( + "start_async", + [](InferRequestWrapper& self, const py::dict& inputs, py::object& userdata) { + // Update inputs if there are any + Common::set_request_tensors(self._request, inputs); + if (!userdata.is(py::none())) { + if (self.user_callback_defined) { + self.userdata = userdata; + } else { + PyErr_WarnEx(PyExc_RuntimeWarning, "There is no callback function!", 1); + } + } + py::gil_scoped_release release; + self._start_time = Time::now(); + self._request.start_async(); + }, + py::arg("inputs"), + py::arg("userdata")); + + cls.def("cancel", [](InferRequestWrapper& self) { + self._request.cancel(); + }); + + cls.def("wait", [](InferRequestWrapper& self) { + py::gil_scoped_release release; + self._request.wait(); + }); + + cls.def( + "wait_for", + [](InferRequestWrapper& self, const int timeout) { + py::gil_scoped_release release; + return self._request.wait_for(std::chrono::milliseconds(timeout)); + }, + py::arg("timeout")); + + cls.def( + "set_callback", + [](InferRequestWrapper& self, py::function f_callback, py::object& userdata) { + self.userdata = userdata; + self.user_callback_defined = true; + self._request.set_callback([&self, f_callback](std::exception_ptr exception_ptr) { + self._end_time = Time::now(); + try { + if (exception_ptr) { + std::rethrow_exception(exception_ptr); + } + } catch (const std::exception& e) { + throw ov::Exception("Caught exception: " + std::string(e.what())); + } + // Acquire GIL, execute Python function + py::gil_scoped_acquire acquire; + f_callback(self.userdata); + }); + }, + py::arg("f_callback"), + py::arg("userdata")); + + cls.def( + "get_tensor", + [](InferRequestWrapper& self, const std::string& name) { + return self._request.get_tensor(name); + }, + py::arg("name")); + + cls.def( + "get_tensor", + [](InferRequestWrapper& self, const ov::Output& port) { + return self._request.get_tensor(port); + }, + py::arg("port")); + + cls.def( + "get_tensor", + [](InferRequestWrapper& self, const ov::Output& port) { + return self._request.get_tensor(port); + }, + py::arg("port")); + + cls.def( + "get_input_tensor", + [](InferRequestWrapper& self, size_t idx) { + return self._request.get_input_tensor(idx); + }, + py::arg("idx")); + + cls.def("get_input_tensor", [](InferRequestWrapper& self) { + return self._request.get_input_tensor(); + }); + + cls.def( + "get_output_tensor", + [](InferRequestWrapper& self, size_t idx) { + return self._request.get_output_tensor(idx); + }, + py::arg("idx")); + + cls.def("get_output_tensor", [](InferRequestWrapper& self) { + return self._request.get_output_tensor(); + }); + + cls.def( + "set_tensor", + [](InferRequestWrapper& self, const std::string& name, const ov::runtime::Tensor& tensor) { + self._request.set_tensor(name, tensor); + }, + py::arg("name"), + py::arg("tensor")); + + cls.def( + "set_tensor", + [](InferRequestWrapper& self, const ov::Output& port, const ov::runtime::Tensor& tensor) { + self._request.set_tensor(port, tensor); + }, + py::arg("port"), + py::arg("tensor")); + + cls.def( + "set_tensor", + [](InferRequestWrapper& self, const ov::Output& port, const ov::runtime::Tensor& tensor) { + self._request.set_tensor(port, tensor); + }, + py::arg("port"), + py::arg("tensor")); + + cls.def( + "set_input_tensor", + [](InferRequestWrapper& self, size_t idx, const ov::runtime::Tensor& tensor) { + self._request.set_input_tensor(idx, tensor); + }, + py::arg("idx"), + py::arg("tensor")); + + cls.def( + "set_input_tensor", + [](InferRequestWrapper& self, const ov::runtime::Tensor& tensor) { + self._request.set_input_tensor(tensor); + }, + py::arg("tensor")); + + cls.def( + "set_output_tensor", + [](InferRequestWrapper& self, size_t idx, const ov::runtime::Tensor& tensor) { + self._request.set_output_tensor(idx, tensor); + }, + py::arg("idx"), + py::arg("tensor")); + + cls.def( + "set_output_tensor", + [](InferRequestWrapper& self, const ov::runtime::Tensor& tensor) { + self._request.set_output_tensor(tensor); + }, + py::arg("tensor")); + + cls.def("get_profiling_info", [](InferRequestWrapper& self) { + return self._request.get_profiling_info(); + }); + + cls.def_property_readonly("userdata", [](InferRequestWrapper& self) { + return self.userdata; + }); + + cls.def_property_readonly("inputs", [](InferRequestWrapper& self) { + return self._inputs; + }); + + cls.def_property_readonly("outputs", [](InferRequestWrapper& self) { + return self._outputs; + }); + + cls.def_property_readonly("input_tensors", [](InferRequestWrapper& self) { + std::vector tensors; + for (auto&& node : self._inputs) { + tensors.push_back(self._request.get_tensor(node)); + } + return tensors; + }); + + cls.def_property_readonly("output_tensors", [](InferRequestWrapper& self) { + std::vector tensors; + for (auto&& node : self._outputs) { + tensors.push_back(self._request.get_tensor(node)); + } + return tensors; + }); + + cls.def_property_readonly("latency", [](InferRequestWrapper& self) { + return self.get_latency(); + }); + + cls.def_property_readonly("profiling_info", [](InferRequestWrapper& self) { + return self._request.get_profiling_info(); + }); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/infer_request.hpp b/runtime/bindings/python/src/pyopenvino/core/infer_request.hpp new file mode 100644 index 00000000000000..143df8f200cb73 --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/infer_request.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include + +#include + +#include + +namespace py = pybind11; + +typedef std::chrono::high_resolution_clock Time; +typedef std::chrono::nanoseconds ns; + +class InferRequestWrapper { +public: + InferRequestWrapper(ov::runtime::InferRequest request) + : _request(request) + { + // AsyncInferQueue uses this constructor - setting callback for computing a latency will be done there + } + + InferRequestWrapper(ov::runtime::InferRequest request, const std::vector>& inputs, const std::vector>& outputs) + : _request(request), _inputs(inputs), _outputs(outputs) + { + _request.set_callback([this](std::exception_ptr exception_ptr) { + _end_time = Time::now(); + }); + } + // ~InferRequestWrapper() = default; + + bool user_callback_defined = false; + py::object userdata; + + double get_latency() { + auto execTime = std::chrono::duration_cast(_end_time - _start_time); + return static_cast(execTime.count()) * 0.000001; + } + + ov::runtime::InferRequest _request; + std::vector> _inputs; + std::vector> _outputs; + + Time::time_point _start_time; + Time::time_point _end_time; +}; + +void regclass_InferRequest(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/core/offline_transformations.cpp b/runtime/bindings/python/src/pyopenvino/core/offline_transformations.cpp new file mode 100644 index 00000000000000..f58bcc6eedfcd6 --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/offline_transformations.cpp @@ -0,0 +1,84 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "pyopenvino/core/offline_transformations.hpp" + +#include + +#include +#include +#include +#include +#include + +#include "openvino/pass/low_latency.hpp" +#include "openvino/pass/manager.hpp" + +namespace py = pybind11; + +void regmodule_offline_transformations(py::module m) { + // TODO: change the submodule name according to the description in 69196 + py::module m_offline_transformations = + m.def_submodule("offline_transformations_pybind", "Offline transformations module"); + + m_offline_transformations.def( + "apply_moc_transformations", + [](std::shared_ptr function, bool cf) { + ov::pass::Manager manager; + manager.register_pass(cf); + manager.run_passes(function); + }, + py::arg("function"), + py::arg("cf")); + + m_offline_transformations.def( + "apply_pot_transformations", + [](std::shared_ptr function, std::string device) { + ov::pass::Manager manager; + manager.register_pass(std::move(device)); + manager.run_passes(function); + }, + py::arg("function"), + py::arg("device")); + + m_offline_transformations.def( + "apply_low_latency_transformation", + [](std::shared_ptr function, bool use_const_initializer = true) { + ov::pass::Manager manager; + manager.register_pass(use_const_initializer); + manager.run_passes(function); + }, + py::arg("function"), + py::arg("use_const_initializer") = true); + + m_offline_transformations.def( + "apply_pruning_transformation", + [](std::shared_ptr function) { + ov::pass::Manager manager; + manager.register_pass(); + manager.run_passes(function); + }, + py::arg("function")); + + m_offline_transformations.def( + "generate_mapping_file", + [](std::shared_ptr function, std::string path, bool extract_names) { + ov::pass::Manager manager; + manager.register_pass(path, extract_names); + manager.run_passes(function); + }, + py::arg("function"), + py::arg("path"), + py::arg("extract_names")); + + m_offline_transformations.def( + "apply_make_stateful_transformation", + [](std::shared_ptr function, const std::map& param_res_names) { + ngraph::pass::Manager manager; + manager.register_pass(param_res_names); + manager.run_passes(function); + }, + py::arg("function"), + py::arg("param_res_names")); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_input_info.hpp b/runtime/bindings/python/src/pyopenvino/core/offline_transformations.hpp similarity index 74% rename from runtime/bindings/python/src/pyopenvino/core/ie_input_info.hpp rename to runtime/bindings/python/src/pyopenvino/core/offline_transformations.hpp index 69d17221bc271d..50d4210218a749 100644 --- a/runtime/bindings/python/src/pyopenvino/core/ie_input_info.hpp +++ b/runtime/bindings/python/src/pyopenvino/core/offline_transformations.hpp @@ -8,4 +8,4 @@ namespace py = pybind11; -void regclass_InputInfo(py::module m); +void regmodule_offline_transformations(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/core/profiling_info.cpp b/runtime/bindings/python/src/pyopenvino/core/profiling_info.cpp new file mode 100644 index 00000000000000..9619e070386017 --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/profiling_info.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "pyopenvino/core/profiling_info.hpp" + +#include + +#include "openvino/runtime/profiling_info.hpp" + +namespace py = pybind11; + +void regclass_ProfilingInfo(py::module m) { + py::class_> cls(m, "ProfilingInfo"); + cls.def(py::init<>()) + .def_readwrite("status", &ov::runtime::ProfilingInfo::status) + .def_readwrite("real_time", &ov::runtime::ProfilingInfo::real_time) + .def_readwrite("cpu_time", &ov::runtime::ProfilingInfo::cpu_time) + .def_readwrite("node_name", &ov::runtime::ProfilingInfo::node_name) + .def_readwrite("exec_type", &ov::runtime::ProfilingInfo::exec_type) + .def_readwrite("node_type", &ov::runtime::ProfilingInfo::node_type); + + py::enum_(cls, "Status") + .value("NOT_RUN", ov::runtime::ProfilingInfo::Status::NOT_RUN) + .value("OPTIMIZED_OUT", ov::runtime::ProfilingInfo::Status::OPTIMIZED_OUT) + .value("EXECUTED", ov::runtime::ProfilingInfo::Status::EXECUTED) + .export_values(); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_data.hpp b/runtime/bindings/python/src/pyopenvino/core/profiling_info.hpp similarity index 78% rename from runtime/bindings/python/src/pyopenvino/core/ie_data.hpp rename to runtime/bindings/python/src/pyopenvino/core/profiling_info.hpp index 6b1459714ecb0d..023935f620e913 100644 --- a/runtime/bindings/python/src/pyopenvino/core/ie_data.hpp +++ b/runtime/bindings/python/src/pyopenvino/core/profiling_info.hpp @@ -8,4 +8,4 @@ namespace py = pybind11; -void regclass_Data(py::module m); +void regclass_ProfilingInfo(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/core/tensor.cpp b/runtime/bindings/python/src/pyopenvino/core/tensor.cpp index a0d6952f04e0bb..1f1146c045c624 100644 --- a/runtime/bindings/python/src/pyopenvino/core/tensor.cpp +++ b/runtime/bindings/python/src/pyopenvino/core/tensor.cpp @@ -10,28 +10,13 @@ #include "openvino/runtime/tensor.hpp" #include "pyopenvino/core/common.hpp" -#define C_CONTIGUOUS py::detail::npy_api::constants::NPY_ARRAY_C_CONTIGUOUS_ - namespace py = pybind11; void regclass_Tensor(py::module m) { py::class_> cls(m, "Tensor"); cls.def(py::init([](py::array& array, bool shared_memory) { - auto type = Common::dtype_to_ov_type().at(py::str(array.dtype())); - std::vector shape(array.shape(), array.shape() + array.ndim()); - if (shared_memory) { - if (C_CONTIGUOUS == (array.flags() & C_CONTIGUOUS)) { - std::vector strides(array.strides(), array.strides() + array.ndim()); - return ov::runtime::Tensor(type, shape, const_cast(array.data(0)), strides); - } else { - IE_THROW() << "Tensor with shared memory must be C contiguous!"; - } - } - array = py::module::import("numpy").attr("ascontiguousarray")(array).cast(); - auto tensor = ov::runtime::Tensor(type, shape); - std::memcpy(tensor.data(), array.data(0), array.nbytes()); - return tensor; + return Common::tensor_from_numpy(array, shared_memory); }), py::arg("array"), py::arg("shared_memory") = false); diff --git a/runtime/bindings/python/src/pyopenvino/core/tensor_description.cpp b/runtime/bindings/python/src/pyopenvino/core/tensor_description.cpp deleted file mode 100644 index b9382f34e5cb2e..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/tensor_description.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#include "pyopenvino/core/tensor_description.hpp" - -#include -#include -#include - -#include - -#include "common.hpp" - -namespace py = pybind11; -using namespace InferenceEngine; - -void regclass_TensorDecription(py::module m) { - py::class_> cls(m, "TensorDesc"); - cls.def(py::init()); - cls.def(py::init([](const std::string& precision, const SizeVector& dims, const std::string& layout) { - return TensorDesc(Precision::FromStr(precision), dims, Common::get_layout_from_string(layout)); - })); - - cls.def_property( - "layout", - [](TensorDesc& self) { - return Common::get_layout_from_enum(self.getLayout()); - }, - [](TensorDesc& self, const std::string& layout) { - self.setLayout(Common::get_layout_from_string(layout)); - }); - - cls.def_property( - "precision", - [](TensorDesc& self) { - return self.getPrecision().name(); - }, - [](TensorDesc& self, const std::string& precision) { - self.setPrecision(InferenceEngine::Precision::FromStr(precision)); - }); - - cls.def_property( - "dims", - [](TensorDesc& self) { - return self.getDims(); - }, - [](TensorDesc& self, const SizeVector& dims) { - self.setDims(dims); - }); - - cls.def( - "__eq__", - [](const TensorDesc& a, const TensorDesc b) { - return a == b; - }, - py::is_operator()); -} diff --git a/runtime/bindings/python/src/pyopenvino/core/tensor_description.hpp b/runtime/bindings/python/src/pyopenvino/core/tensor_description.hpp deleted file mode 100644 index 806c7b9d3b8792..00000000000000 --- a/runtime/bindings/python/src/pyopenvino/core/tensor_description.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (C) 2021 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 -// - -#pragma once - -#include - -namespace py = pybind11; - -void regclass_TensorDecription(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/core/version.cpp b/runtime/bindings/python/src/pyopenvino/core/version.cpp new file mode 100644 index 00000000000000..bed253697fda06 --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/core/version.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "openvino/core/version.hpp" + +#include + +namespace py = pybind11; + +void regclass_Version(py::module m) { + py::class_ cls(m, "Version"); + + cls.def_readonly("build_number", &ov::Version::buildNumber); + cls.def_readonly("description", &ov::Version::description); + + cls.def_property_readonly("major", [](ov::Version& self) { + return OPENVINO_VERSION_MAJOR; + }); + + cls.def_property_readonly("minor", [](ov::Version& self) { + return OPENVINO_VERSION_MINOR; + }); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_version.hpp b/runtime/bindings/python/src/pyopenvino/core/version.hpp similarity index 100% rename from runtime/bindings/python/src/pyopenvino/core/ie_version.hpp rename to runtime/bindings/python/src/pyopenvino/core/version.hpp diff --git a/runtime/bindings/python/src/pyopenvino/graph/function.cpp b/runtime/bindings/python/src/pyopenvino/graph/function.cpp index 3496e88d0149dd..27e3d18b0ec079 100644 --- a/runtime/bindings/python/src/pyopenvino/graph/function.cpp +++ b/runtime/bindings/python/src/pyopenvino/graph/function.cpp @@ -7,6 +7,7 @@ #include #include +#include "openvino/core/partial_shape.hpp" #include "openvino/op/parameter.hpp" // ov::op::v0::Parameter #include "openvino/op/sink.hpp" #include "pyopenvino/graph/function.hpp" @@ -15,6 +16,16 @@ namespace py = pybind11; static const char* CAPSULE_NAME = "ngraph_function"; +void set_tensor_names(const ov::ParameterVector& parameters) { + for (const auto& param : parameters) { + ov::Output p = param; + if (p.get_node()->output(0).get_names().empty()) { + std::unordered_set p_names({p.get_node()->get_friendly_name()}); + p.get_node()->output(0).set_names(p_names); + } + } +} + void regclass_graph_Function(py::module m) { py::class_> function(m, "Function", py::module_local()); function.doc() = "openvino.impl.Function wraps ov::Function"; @@ -53,12 +64,15 @@ void regclass_graph_Function(py::module m) { String to set as function's friendly name. )"); - function.def(py::init>&, - const std::vector>&, - const std::string&>(), + function.def(py::init([](const std::vector>& results, + const ov::ParameterVector& parameters, + const std::string& name) { + set_tensor_names(parameters); + return std::make_shared(results, parameters, name); + }), py::arg("results"), py::arg("parameters"), - py::arg("name"), + py::arg("name") = "", R"( Create user-defined Function which is a representation of a model. @@ -74,12 +88,15 @@ void regclass_graph_Function(py::module m) { String to set as function's friendly name. )"); - function.def(py::init&, - const std::vector>&, - const std::string&>(), + function.def(py::init([](const std::shared_ptr& results, + const ov::ParameterVector& parameters, + const std::string& name) { + set_tensor_names(parameters); + return std::make_shared(results, parameters, name); + }), py::arg("result"), py::arg("parameters"), - py::arg("name"), + py::arg("name") = "", R"( Create user-defined Function which is a representation of a model. @@ -94,6 +111,41 @@ void regclass_graph_Function(py::module m) { name : str String to set as function's friendly name. )"); + + function.def( + "reshape", + [](ov::Function& self, const std::map& partial_shapes) { + self.reshape(partial_shapes); + }, + py::arg("partial_shapes"), + R"( + Parameters + ---------- + partial_shapes : Dict[string, PartialShape] + Index of Output. + + Returns + ---------- + reshape : void + )"); + + function.def( + "reshape", + [](ov::Function& self, const std::map, ov::PartialShape>& partial_shapes) { + self.reshape(partial_shapes); + }, + py::arg("partial_shapes"), + R"( + Parameters + ---------- + partial_shapes : Dict[Output, PartialShape] + Index of Output. + + Returns + ---------- + reshape : void + )"); + function.def("get_output_size", &ov::Function::get_output_size, R"( @@ -264,6 +316,42 @@ void regclass_graph_Function(py::module m) { ---------- is_dynamic : bool )"); + function.def("input", (ov::Output(ov::Function::*)()) & ov::Function::input); + + function.def("input", (ov::Output(ov::Function::*)(size_t)) & ov::Function::input, py::arg("i")); + + function.def("input", + (ov::Output(ov::Function::*)(const std::string&)) & ov::Function::input, + py::arg("tensor_name")); + + function.def("input", (ov::Output(ov::Function::*)() const) & ov::Function::input); + + function.def("input", + (ov::Output(ov::Function::*)(size_t) const) & ov::Function::input, + py::arg("i")); + + function.def("input", + (ov::Output(ov::Function::*)(const std::string&) const) & ov::Function::input, + py::arg("tensor_name")); + + function.def("output", (ov::Output(ov::Function::*)()) & ov::Function::output); + + function.def("output", (ov::Output(ov::Function::*)(size_t)) & ov::Function::output, py::arg("i")); + + function.def("output", + (ov::Output(ov::Function::*)(const std::string&)) & ov::Function::output, + py::arg("tensor_name")); + + function.def("output", (ov::Output(ov::Function::*)() const) & ov::Function::output); + + function.def("output", + (ov::Output(ov::Function::*)(size_t) const) & ov::Function::output, + py::arg("i")); + + function.def("output", + (ov::Output(ov::Function::*)(const std::string&) const) & ov::Function::output, + py::arg("tensor_name")); + function.def("__repr__", [](const ov::Function& self) { std::string class_name = py::cast(self).get_type().attr("__name__").cast(); std::stringstream shapes_ss; @@ -309,6 +397,16 @@ void regclass_graph_Function(py::module m) { return pybind_capsule; }); + function.def_property_readonly("inputs", + (std::vector>(ov::Function::*)()) & ov::Function::inputs); + function.def_property_readonly( + "inputs", + (std::vector>(ov::Function::*)() const) & ov::Function::inputs); + function.def_property_readonly("outputs", + (std::vector>(ov::Function::*)()) & ov::Function::outputs); + function.def_property_readonly( + "outputs", + (std::vector>(ov::Function::*)() const) & ov::Function::outputs); function.def_property_readonly("name", &ov::Function::get_name); function.def_property("friendly_name", &ov::Function::get_friendly_name, &ov::Function::set_friendly_name); } diff --git a/runtime/bindings/python/src/pyopenvino/graph/layout_helpers.cpp b/runtime/bindings/python/src/pyopenvino/graph/layout_helpers.cpp new file mode 100644 index 00000000000000..ff7eedaa07c5d4 --- /dev/null +++ b/runtime/bindings/python/src/pyopenvino/graph/layout_helpers.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "pyopenvino/graph/layout_helpers.hpp" + +#include + +#include "openvino/core/layout.hpp" + +namespace py = pybind11; + +void regmodule_graph_layout_helpers(py::module m) { + py::module mod = m.def_submodule("layout_helpers", "openvino.impl.layout_helpers"); + + mod.def("has_batch", &ov::layout::has_batch, py::arg("layout")); + mod.def("batch_idx", &ov::layout::batch_idx, py::arg("layout")); + mod.def("has_channels", &ov::layout::has_channels, py::arg("layout")); + mod.def("channels_idx", &ov::layout::channels_idx, py::arg("layout")); + mod.def("has_depth", &ov::layout::has_depth, py::arg("layout")); + mod.def("depth_idx", &ov::layout::depth_idx, py::arg("layout")); + mod.def("has_height", &ov::layout::has_height, py::arg("layout")); + mod.def("height_idx", &ov::layout::height_idx, py::arg("layout")); + mod.def("has_width", &ov::layout::has_width, py::arg("layout")); + mod.def("width_idx", &ov::layout::width_idx, py::arg("layout")); +} diff --git a/runtime/bindings/python/src/pyopenvino/core/ie_preprocess_info.hpp b/runtime/bindings/python/src/pyopenvino/graph/layout_helpers.hpp similarity index 75% rename from runtime/bindings/python/src/pyopenvino/core/ie_preprocess_info.hpp rename to runtime/bindings/python/src/pyopenvino/graph/layout_helpers.hpp index cc762ada0cb623..573316b3af1189 100644 --- a/runtime/bindings/python/src/pyopenvino/core/ie_preprocess_info.hpp +++ b/runtime/bindings/python/src/pyopenvino/graph/layout_helpers.hpp @@ -8,4 +8,4 @@ namespace py = pybind11; -void regclass_PreProcessInfo(py::module m); \ No newline at end of file +void regmodule_graph_layout_helpers(py::module m); diff --git a/runtime/bindings/python/src/pyopenvino/graph/node_output.cpp b/runtime/bindings/python/src/pyopenvino/graph/node_output.cpp index 56ac60e3ba9f64..8d1cfcec5bb7d0 100644 --- a/runtime/bindings/python/src/pyopenvino/graph/node_output.cpp +++ b/runtime/bindings/python/src/pyopenvino/graph/node_output.cpp @@ -11,68 +11,5 @@ namespace py = pybind11; -void regclass_graph_Output(py::module m) { - py::class_, std::shared_ptr>> output(m, "Output", py::dynamic_attr()); - output.doc() = "openvino.impl.Output wraps ov::Output"; - - output.def("get_node", - &ov::Output::get_node, - R"( - Get node referenced by this output handle. - - Returns - ---------- - get_node : Node - Node object referenced by this output handle. - )"); - output.def("get_index", - &ov::Output::get_index, - R"( - The index of the output referred to by this output handle. - - Returns - ---------- - get_index : int - Index value as integer. - )"); - output.def("get_element_type", - &ov::Output::get_element_type, - R"( - The element type of the output referred to by this output handle. - - Returns - ---------- - get_element_type : Type - Type of the output. - )"); - output.def("get_shape", - &ov::Output::get_shape, - R"( - The shape of the output referred to by this output handle. - - Returns - ---------- - get_shape : Shape - Shape of the output. - )"); - output.def("get_partial_shape", - &ov::Output::get_partial_shape, - R"( - The partial shape of the output referred to by this output handle. - - Returns - ---------- - get_partial_shape : PartialShape - PartialShape of the output. - )"); - output.def("get_target_inputs", - &ov::Output::get_target_inputs, - R"( - A set containing handles for all inputs targeted by the output - referenced by this output handle. - Returns - ---------- - get_target_inputs : Set[Input] - Set of Inputs. - )"); -} +template void regclass_graph_Output(py::module m, std::string typestring); +template void regclass_graph_Output(py::module m, std::string typestring); diff --git a/runtime/bindings/python/src/pyopenvino/graph/node_output.hpp b/runtime/bindings/python/src/pyopenvino/graph/node_output.hpp index 9934c628b2e098..a88722ebc18448 100644 --- a/runtime/bindings/python/src/pyopenvino/graph/node_output.hpp +++ b/runtime/bindings/python/src/pyopenvino/graph/node_output.hpp @@ -5,7 +5,80 @@ #pragma once #include +#include + +#include "openvino/core/node_output.hpp" namespace py = pybind11; -void regclass_graph_Output(py::module m); +template +void regclass_graph_Output(py::module m, std::string typestring) +{ + auto pyclass_name = py::detail::c_str((typestring + std::string("Output"))); + auto docs = py::detail::c_str((std::string("openvino.impl.") + typestring + std::string("Output wraps ov::Output<") + typestring + std::string(" ov::Node >"))); + py::class_, std::shared_ptr>> output(m, + pyclass_name, + py::dynamic_attr()); + output.doc() = docs; + + output.def("get_node", + &ov::Output::get_node, + R"( + Get node referenced by this output handle. + + Returns + ---------- + get_node : Node or const Node + Node object referenced by this output handle. + )"); + output.def("get_index", + &ov::Output::get_index, + R"( + The index of the output referred to by this output handle. + + Returns + ---------- + get_index : int + Index value as integer. + )"); + output.def("get_element_type", + &ov::Output::get_element_type, + R"( + The element type of the output referred to by this output handle. + + Returns + ---------- + get_element_type : Type + Type of the output. + )"); + output.def("get_shape", + &ov::Output::get_shape, + R"( + The shape of the output referred to by this output handle. + + Returns + ---------- + get_shape : Shape + Shape of the output. + )"); + output.def("get_partial_shape", + &ov::Output::get_partial_shape, + R"( + The partial shape of the output referred to by this output handle. + + Returns + ---------- + get_partial_shape : PartialShape + PartialShape of the output. + )"); + output.def("get_target_inputs", + &ov::Output::get_target_inputs, + R"( + A set containing handles for all inputs targeted by the output + referenced by this output handle. + Returns + ---------- + get_target_inputs : Set[Input] + Set of Inputs. + )"); +} diff --git a/runtime/bindings/python/src/pyopenvino/pyopenvino.cpp b/runtime/bindings/python/src/pyopenvino/pyopenvino.cpp index 4cd1d4765aa28e..5422948aa160e6 100644 --- a/runtime/bindings/python/src/pyopenvino/pyopenvino.cpp +++ b/runtime/bindings/python/src/pyopenvino/pyopenvino.cpp @@ -1,11 +1,10 @@ // Copyright (C) 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#include #include -#include -#include +#include +#include #include #include "pyopenvino/graph/axis_set.hpp" @@ -20,22 +19,19 @@ #if defined(NGRAPH_ONNX_FRONTEND_ENABLE) # include "pyopenvino/graph/onnx_import/onnx_import.hpp" #endif +#include "pyopenvino/core/async_infer_queue.hpp" #include "pyopenvino/core/containers.hpp" -#include "pyopenvino/core/ie_blob.hpp" -#include "pyopenvino/core/ie_core.hpp" -#include "pyopenvino/core/ie_data.hpp" -#include "pyopenvino/core/ie_executable_network.hpp" -#include "pyopenvino/core/ie_infer_queue.hpp" -#include "pyopenvino/core/ie_infer_request.hpp" -#include "pyopenvino/core/ie_input_info.hpp" -#include "pyopenvino/core/ie_network.hpp" +#include "pyopenvino/core/core.hpp" +#include "pyopenvino/core/executable_network.hpp" #include "pyopenvino/core/ie_parameter.hpp" -#include "pyopenvino/core/ie_preprocess_info.hpp" -#include "pyopenvino/core/ie_version.hpp" +#include "pyopenvino/core/infer_request.hpp" +#include "pyopenvino/core/offline_transformations.hpp" +#include "pyopenvino/core/profiling_info.hpp" #include "pyopenvino/core/tensor.hpp" -#include "pyopenvino/core/tensor_description.hpp" +#include "pyopenvino/core/version.hpp" #include "pyopenvino/graph/dimension.hpp" #include "pyopenvino/graph/layout.hpp" +#include "pyopenvino/graph/layout_helpers.hpp" #include "pyopenvino/graph/ops/constant.hpp" #include "pyopenvino/graph/ops/parameter.hpp" #include "pyopenvino/graph/ops/result.hpp" @@ -52,9 +48,9 @@ namespace py = pybind11; std::string get_version() { - auto version = InferenceEngine::GetInferenceEngineVersion(); - std::string version_str = std::to_string(version->apiVersion.major) + "."; - version_str += std::to_string(version->apiVersion.minor) + "."; + auto version = ov::get_openvino_version(); + std::string version_str = std::to_string(OPENVINO_VERSION_MAJOR) + "."; + version_str += std::to_string(OPENVINO_VERSION_MINOR) + "."; version_str += version->buildNumber; return version_str; } @@ -62,26 +58,6 @@ std::string get_version() { PYBIND11_MODULE(pyopenvino, m) { m.doc() = "Package openvino.pyopenvino which wraps openvino C++ APIs"; m.def("get_version", &get_version); - py::enum_(m, "StatusCode") - .value("OK", InferenceEngine::StatusCode::OK) - .value("GENERAL_ERROR", InferenceEngine::StatusCode::GENERAL_ERROR) - .value("NOT_IMPLEMENTED", InferenceEngine::StatusCode::NOT_IMPLEMENTED) - .value("NETWORK_NOT_LOADED", InferenceEngine::StatusCode::NETWORK_NOT_LOADED) - .value("PARAMETER_MISMATCH", InferenceEngine::StatusCode::PARAMETER_MISMATCH) - .value("NOT_FOUND", InferenceEngine::StatusCode::NOT_FOUND) - .value("OUT_OF_BOUNDS", InferenceEngine::StatusCode::OUT_OF_BOUNDS) - .value("UNEXPECTED", InferenceEngine::StatusCode::UNEXPECTED) - .value("REQUEST_BUSY", InferenceEngine::StatusCode::REQUEST_BUSY) - .value("RESULT_NOT_READY", InferenceEngine::StatusCode::RESULT_NOT_READY) - .value("NOT_ALLOCATED", InferenceEngine::StatusCode::NOT_ALLOCATED) - .value("INFER_NOT_STARTED", InferenceEngine::StatusCode::INFER_NOT_STARTED) - .value("NETWORK_NOT_READ", InferenceEngine::StatusCode::NETWORK_NOT_READ) - .export_values(); - - py::enum_(m, "WaitMode") - .value("RESULT_READY", InferenceEngine::IInferRequest::WaitMode::RESULT_READY) - .value("STATUS_ONLY", InferenceEngine::IInferRequest::WaitMode::STATUS_ONLY) - .export_values(); regclass_graph_PyRTMap(m); regmodule_graph_types(m); @@ -91,7 +67,6 @@ PYBIND11_MODULE(pyopenvino, m) { regclass_graph_PartialShape(m); regclass_graph_Node(m); regclass_graph_Input(m); - regclass_graph_Output(m); regclass_graph_NodeFactory(m); regclass_graph_Strides(m); regclass_graph_CoordinateDiff(m); @@ -102,6 +77,7 @@ PYBIND11_MODULE(pyopenvino, m) { regclass_graph_op_Constant(m_op); regclass_graph_op_Parameter(m_op); regclass_graph_op_Result(m_op); + #if defined(NGRAPH_ONNX_FRONTEND_ENABLE) regmodule_graph_onnx_import(m); #endif @@ -109,44 +85,25 @@ PYBIND11_MODULE(pyopenvino, m) { regclass_graph_Function(m); regmodule_graph_passes(m); regmodule_graph_util(m); + regmodule_graph_layout_helpers(m); regclass_graph_Variant(m); regclass_graph_VariantWrapper(m, std::string("String")); regclass_graph_VariantWrapper(m, std::string("Int")); + regclass_graph_Output(m, std::string("")); + regclass_graph_Output(m, std::string("Const")); regclass_Core(m); - regclass_IENetwork(m); - - regclass_Data(m); - regclass_TensorDecription(m); - - // Blob will be removed - // Registering template of Blob - regclass_Blob(m); - // Registering specific types of Blobs - regclass_TBlob(m, "Float32"); - regclass_TBlob(m, "Float64"); - regclass_TBlob(m, "Int64"); - regclass_TBlob(m, "Uint64"); - regclass_TBlob(m, "Int32"); - regclass_TBlob(m, "Uint32"); - regclass_TBlob(m, "Int16"); - regclass_TBlob(m, "Uint16"); - regclass_TBlob(m, "Int8"); - regclass_TBlob(m, "Uint8"); - regclass_Tensor(m); - // Registering specific types of containers - Containers::regclass_PyInputsDataMap(m); - Containers::regclass_PyConstInputsDataMap(m); - Containers::regclass_PyOutputsDataMap(m); - Containers::regclass_PyResults(m); + Containers::regclass_TensorIndexMap(m); + Containers::regclass_TensorNameMap(m); regclass_ExecutableNetwork(m); regclass_InferRequest(m); regclass_Version(m); regclass_Parameter(m); - regclass_InputInfo(m); - regclass_InferQueue(m); - regclass_PreProcessInfo(m); + regclass_AsyncInferQueue(m); + regclass_ProfilingInfo(m); + + regmodule_offline_transformations(m); } diff --git a/runtime/bindings/python/tests/__init__.py b/runtime/bindings/python/tests/__init__.py index 274b91d09fec20..48c46843e7ed58 100644 --- a/runtime/bindings/python/tests/__init__.py +++ b/runtime/bindings/python/tests/__init__.py @@ -24,8 +24,9 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): skip_segfault = pytest.mark.skip(reason="Segmentation fault error") xfail_accuracy = xfail_test(reason="Accuracy") +xfail_issue_FLOAT_LIKE = xfail_test(reason="Use of bfloat16 or float16") xfail_issue_69444 = xfail_test(reason="failed with accuracy issue") -skip_issue_69443 = pytest.mark.skip(reason="Segmentation fault due to empty pads_begin, pads_end") +xfail_issue_69443 = xfail_test(reason="Error in ref. implementation due to the empty pads_begin, pads_end") skip_issue_67415 = pytest.mark.skip(reason="RuntimeError: Unsupported data type for when filling blob!") xfail_issue_67415 = xfail_test(reason="RuntimeError: Unsupported data type for when filling blob!") xfail_issue_33488 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " @@ -47,7 +48,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): "TfIdfVectorizer") xfail_issue_33581 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " "GatherElements") -xfail_issue_33633 = xfail_test(reason="MaxPool: dilations unsupported") xfail_issue_35923 = xfail_test(reason="RuntimeError: PReLU without weights is not supported") xfail_issue_35927 = xfail_test(reason="RuntimeError: B has zero dimension that is not allowable") xfail_issue_36486 = xfail_test(reason="RuntimeError: HardSigmoid operation should be converted " @@ -93,8 +93,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): xfail_issue_44968 = xfail_test(reason="Expected: Unsupported dynamic op: Squeeze") xfail_issue_47323 = xfail_test(reason="RuntimeError: The plugin does not support FP64") xfail_issue_47337 = xfail_test(reason="RuntimeError: Unsupported dynamic ops: v1::OneHot") -xfail_issue_33593 = xfail_test(reason="Current implementation of MaxPool doesn't support indices output") -xfail_issue_55760 = xfail_test(reason="RuntimeError: Reversed axis have axes above the source space shape") # Model MSFT issues: xfail_issue_37957 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " @@ -108,9 +106,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): "/openvino/ngraph/src/ngraph/op/util/elementwise_args.cpp:48:") xfail_issue_39658 = xfail_test(reason="RuntimeError: Tile operation has a form that is not supported." " z should be converted to TileIE operation.") -xfail_issue_39659 = xfail_test(reason="RuntimeError: Broadcast operation has a form that is not supported." - " y should be converted to Tile operation.") -xfail_issue_45344 = xfail_test(reason="Unsupported dynamic ops: v3::NonMaxSuppressionIE3") xfail_issue_39662 = xfail_test(reason="RuntimeError: 'ScatterElementsUpdate' layer with name 'y' have " "indices value that points to non-existing output tensor element") @@ -139,7 +134,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): xfail_issue_63039 = xfail_test(reason="Result mismatches with UINT8 operations") xfail_issue_63043 = xfail_test(reason="Recurrent node expects constants as W, R, B inputs.") xfail_issue_63044 = xfail_test(reason="ONNX opset 14 operation: Trilu") -xfail_issue_63045 = xfail_test(reason="Maxpool with strides, padding and dilations fail") skip_rng_tests = pytest.mark.skip(reason="Tests use random number generator with no seed.") xfail_issue_63136 = xfail_test(reason="Unsupported operation: CastLike") @@ -147,3 +141,4 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): xfail_issue_63138 = xfail_test(reason="Missing ONNX Shape-15 support") xfail_issue_63643 = xfail_test(reason="RuntimeError: Unsupported operation of type: Convolution name") xfail_issue_54663 = xfail_test(reason="Disabled until MaxPool-8 is supported on CPU") +xfail_issue_68212 = xfail_test(reason="Unsupported reading model with bytes streams") diff --git a/runtime/bindings/python/tests/conftest.py b/runtime/bindings/python/tests/conftest.py index 865ae43552e0ec..9efb9a9ecaab1e 100644 --- a/runtime/bindings/python/tests/conftest.py +++ b/runtime/bindings/python/tests/conftest.py @@ -3,6 +3,7 @@ import os import pytest +import numpy as np import tests @@ -15,6 +16,19 @@ def image_path(): return path_to_img +def read_image(): + import cv2 + n, c, h, w = (1, 3, 32, 32) + image = cv2.imread(image_path()) + if image is None: + raise FileNotFoundError("Input image not found") + + image = cv2.resize(image, (h, w)) / 255 + image = image.transpose((2, 0, 1)).astype(np.float32) + image = image.reshape((n, c, h, w)) + return image + + def model_path(is_myriad=False): path_to_repo = os.environ["MODELS_PATH"] if not is_myriad: @@ -78,6 +92,8 @@ def pytest_configure(config): config.addinivalue_line("markers", "skip_on_hetero: Skip test on HETERO") config.addinivalue_line("markers", "skip_on_template: Skip test on TEMPLATE") config.addinivalue_line("markers", "onnx_coverage: Collect ONNX operator coverage") + config.addinivalue_line("markers", "template_extension") + config.addinivalue_line("markers", "dynamic_library: Runs tests only in dynamic libraries case") def pytest_collection_modifyitems(config, items): diff --git a/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.cpp b/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.cpp index dd760e262462a9..580dd5d58daacc 100644 --- a/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.cpp +++ b/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.cpp @@ -8,7 +8,7 @@ #include "frontend_manager/frontend_manager_defs.hpp" using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov::frontend; extern "C" MOCK_API FrontEndVersion GetAPIVersion() { return OV_FRONTEND_API_VERSION; diff --git a/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.hpp b/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.hpp index fef78ede66732b..d7a02f48904204 100644 --- a/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.hpp +++ b/runtime/bindings/python/tests/mock/mock_py_ngraph_frontend/mock_py_frontend.hpp @@ -18,7 +18,7 @@ // OK to have 'using' in mock header using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov::frontend; //////////////////////////////// diff --git a/runtime/bindings/python/tests/mock/pyngraph_fe_mock_api/pyngraph_mock_frontend_api.cpp b/runtime/bindings/python/tests/mock/pyngraph_fe_mock_api/pyngraph_mock_frontend_api.cpp index 54e022b978fe63..b806d1fddc5720 100644 --- a/runtime/bindings/python/tests/mock/pyngraph_fe_mock_api/pyngraph_mock_frontend_api.cpp +++ b/runtime/bindings/python/tests/mock/pyngraph_fe_mock_api/pyngraph_mock_frontend_api.cpp @@ -9,7 +9,7 @@ namespace py = pybind11; using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov::frontend; static void register_mock_frontend_stat(py::module m) { m.def( diff --git a/runtime/bindings/python/tests/runtime.py b/runtime/bindings/python/tests/runtime.py index cc5c49620a6c5e..a1c0bae384b965 100644 --- a/runtime/bindings/python/tests/runtime.py +++ b/runtime/bindings/python/tests/runtime.py @@ -7,11 +7,11 @@ from typing import Dict, List, Union import numpy as np -from openvino import Core, IENetwork, Blob, DataPtr + +from openvino import Core from openvino.exceptions import UserInputError from openvino.impl import Function, Node, PartialShape, Type -from openvino.opset1.ops import result from openvino.utils.types import NumericData, get_shape, get_dtype import tests @@ -32,46 +32,6 @@ def get_runtime(): return runtime() -def _convert_inputs(cnn_network: IENetwork) -> None: - """WA converts unsupported input images formats.""" - precision_map = { - "FP64": "FP32", - "I64": "I32", - "U32": "I32", - } - - for cnn_input in cnn_network.input_info: - try: - _precision = precision_map[cnn_network.input_info[cnn_input].precision] - cnn_network.input_info[cnn_input].precision = _precision - except KeyError: - pass - - -def _convert_val(val): - """WA converts unsupported input values.""" - if type(val) is np.ndarray: - if val.dtype == np.float64: - return np.array(val, dtype=np.float32) - elif val.dtype == np.int64: - return np.array(val, dtype=np.int32) - return np.array(val) - - return np.array(val, dtype=np.float32) - - -def apply_ng_type(output: DataPtr, ng_type: Type): - ng_ie_supported_type_map = { - Type.boolean.get_type_name(): "BOOL", - Type.f32.get_type_name(): "FP32", - Type.i8.get_type_name(): "I8", - Type.i32.get_type_name(): "I32", - Type.u8.get_type_name(): "U8", - } - if ng_type.get_type_name() in ng_ie_supported_type_map: - output.precision = ng_ie_supported_type_map[ng_type.get_type_name()] - - class Runtime(object): """Represents an nGraph runtime environment.""" @@ -120,25 +80,6 @@ def __repr__(self) -> str: params_string = ", ".join([param.name for param in self.parameters]) return "".format(self.function.get_name(), params_string) - def _get_ie_output_blob_name(self, outputs: Dict, ng_result: result) -> str: - if len(self.results) == 1: - return next(iter(outputs.keys())) - else: - prev_layer = ng_result.input(0).get_source_output() - out_name = prev_layer.get_node().get_friendly_name() - if prev_layer.get_node().get_output_size() != 1: - out_name += "." + str(prev_layer.get_index()) - return out_name - - def _get_ie_output_blob_buffer(self, output_blobs: Dict[str, Blob], ng_result: result) -> np.ndarray: - out_name = self._get_ie_output_blob_name(output_blobs, ng_result) - out_blob = output_blobs[out_name] - - if out_blob.tensor_desc.layout == "SCALAR": - return out_blob.buffer.reshape(()) - else: - return out_blob.buffer - def convert_buffers(self, source_buffers, target_dtypes): converted_buffers = [] for i in range(len(source_buffers)): @@ -157,35 +98,24 @@ def __call__(self, *input_values: NumericData) -> List[NumericData]: raise UserInputError( "Expected %s params, received not enough %s values.", len(self.parameters), len(input_values) ) - # ignore not needed input values - input_values = input_values[:len(self.parameters)] - - input_values = [_convert_val(input_value) for input_value in input_values] - input_shapes = [get_shape(input_value) for input_value in input_values] param_names = [param.friendly_name for param in self.parameters] + input_shapes = [get_shape(input_value) for input_value in input_values] if self.network_cache.get(str(input_shapes)) is None: - cnn_network = IENetwork(self.function) + function = self.function if self.function.is_dynamic(): - cnn_network.reshape(dict(zip(param_names, input_shapes))) - # Convert unsupported inputs of the network - _convert_inputs(cnn_network) - self.network_cache[str(input_shapes)] = cnn_network + function.reshape(dict(zip(param_names, [PartialShape(i) for i in input_shapes]))) + self.network_cache[str(input_shapes)] = function else: - cnn_network = self.network_cache[str(input_shapes)] - - # set output blobs precission based on nG results - for ng_result in self.results: - ie_out_name = self._get_ie_output_blob_name(cnn_network.outputs, ng_result) - apply_ng_type(cnn_network.outputs[ie_out_name], ng_result.get_output_element_type(0)) + function = self.network_cache[str(input_shapes)] - executable_network = self.runtime.backend.load_network(cnn_network, self.runtime.backend_name) + executable_network = self.runtime.backend.compile_model(function, self.runtime.backend_name) for parameter, input in zip(self.parameters, input_values): parameter_shape = parameter.get_output_partial_shape(0) - input_shape = PartialShape(input.shape) - if len(input.shape) > 0 and not parameter_shape.compatible(input_shape): + input_shape = PartialShape([]) if isinstance(input, (int, float)) else PartialShape(input.shape) + if not parameter_shape.compatible(input_shape): raise UserInputError( "Provided tensor's shape: %s does not match the expected: %s.", input_shape, @@ -193,13 +123,16 @@ def __call__(self, *input_values: NumericData) -> List[NumericData]: ) request = executable_network.create_infer_request() - request.infer(dict(zip(param_names, input_values))) - - # Set order of output blobs compatible with nG Function - result_buffers = [self._get_ie_output_blob_buffer(request.output_blobs, result) - for result in self.results] - - # Since OV overwrite result data type we have to convert results to the original one. + result_buffers = request.infer(dict(zip(param_names, input_values))) + # # Note: other methods to get result_buffers from request + # # First call infer with no return value: + # request.infer(dict(zip(param_names, input_values))) + # # Now use any of following options: + # result_buffers = [request.get_tensor(n).data for n in request.outputs] + # result_buffers = [request.get_output_tensor(i).data for i in range(len(request.outputs))] + # result_buffers = [t.data for t in request.output_tensors] + + # # Since OV overwrite result data type we have to convert results to the original one. original_dtypes = [get_dtype(result.get_output_element_type(0)) for result in self.results] converted_buffers = self.convert_buffers(result_buffers, original_dtypes) return converted_buffers diff --git a/runtime/bindings/python/tests/test_inference_engine/helpers.py b/runtime/bindings/python/tests/test_inference_engine/helpers.py deleted file mode 100644 index db48c1e9298da7..00000000000000 --- a/runtime/bindings/python/tests/test_inference_engine/helpers.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np -import cv2 -import os - - -def image_path(): - path_to_repo = os.environ["DATA_PATH"] - path_to_img = os.path.join(path_to_repo, "validation_set", "224x224", "dog.bmp") - return path_to_img - - -def model_path(is_myriad=False): - path_to_repo = os.environ["MODELS_PATH"] - if not is_myriad: - test_xml = os.path.join(path_to_repo, "models", "test_model", "test_model_fp32.xml") - test_bin = os.path.join(path_to_repo, "models", "test_model", "test_model_fp32.bin") - else: - test_xml = os.path.join(path_to_repo, "models", "test_model", "test_model_fp16.xml") - test_bin = os.path.join(path_to_repo, "models", "test_model", "test_model_fp16.bin") - return (test_xml, test_bin) - - -def read_image(): - n, c, h, w = (1, 3, 32, 32) - image = cv2.imread(image_path()) - if image is None: - raise FileNotFoundError("Input image not found") - - image = cv2.resize(image, (h, w)) / 255 - image = image.transpose((2, 0, 1)).astype(np.float32) - image = image.reshape((n, c, h, w)) - return image diff --git a/runtime/bindings/python/tests/test_inference_engine/test_core.py b/runtime/bindings/python/tests/test_inference_engine/test_core.py index 59ed993278c8aa..400a03b7f5abbf 100644 --- a/runtime/bindings/python/tests/test_inference_engine/test_core.py +++ b/runtime/bindings/python/tests/test_inference_engine/test_core.py @@ -8,160 +8,131 @@ from pathlib import Path import openvino.opset8 as ov -from openvino import Core, IENetwork, ExecutableNetwork, blob_from_file -from openvino.impl import Function, Shape, Type -from openvino.impl.op import Parameter -from openvino import TensorDesc, Blob +from openvino import Function, Core, ExecutableNetwork, Tensor, tensor_from_file, compile_model + +from ..conftest import model_path, model_onnx_path, plugins_path, read_image -from ..conftest import model_path, model_onnx_path, plugins_path test_net_xml, test_net_bin = model_path() test_net_onnx = model_onnx_path() plugins_xml, plugins_win_xml, plugins_osx_xml = plugins_path() -def test_blobs(): - input_shape = [1, 3, 4, 4] - input_data_float32 = (np.random.rand(*input_shape) - 0.5).astype(np.float32) - - td = TensorDesc("FP32", input_shape, "NCHW") - - input_blob_float32 = Blob(td, input_data_float32) - - assert np.all(np.equal(input_blob_float32.buffer, input_data_float32)) +def test_compact_api_xml(): + img = read_image() - input_data_int16 = (np.random.rand(*input_shape) + 0.5).astype(np.int16) + model = compile_model(test_net_xml) + assert(isinstance(model, ExecutableNetwork)) + results = model.infer_new_request({"data": img}) + assert np.argmax(results) == 2 - td = TensorDesc("I16", input_shape, "NCHW") - input_blob_i16 = Blob(td, input_data_int16) +def test_compact_api_onnx(): + img = read_image() - assert np.all(np.equal(input_blob_i16.buffer, input_data_int16)) + model = compile_model(test_net_onnx) + assert(isinstance(model, ExecutableNetwork)) + results = model.infer_new_request({"data": img}) + assert np.argmax(results) == 2 -@pytest.mark.skip(reason="Fix") -def test_ie_core_class(): +def test_core_class(): input_shape = [1, 3, 4, 4] param = ov.parameter(input_shape, np.float32, name="parameter") relu = ov.relu(param, name="relu") func = Function([relu], [param], "test") func.get_ordered_ops()[2].friendly_name = "friendly" - cnn_network = IENetwork(func) + core = Core() + model = core.compile_model(func, "CPU", {}) - ie_core = Core() - ie_core.set_config({}, device_name="CPU") - executable_network = ie_core.load_network(cnn_network, "CPU", {}) - - td = TensorDesc("FP32", input_shape, "NCHW") - - # from IPython import embed; embed() - - request = executable_network.create_infer_request() - input_data = np.random.rand(*input_shape) - 0.5 + request = model.create_infer_request() + input_data = np.random.rand(*input_shape).astype(np.float32) - 0.5 expected_output = np.maximum(0.0, input_data) - input_blob = Blob(td, input_data) - - request.set_input({"parameter": input_blob}) - request.infer() - - result = request.get_blob("relu").buffer + input_tensor = Tensor(input_data) + results = request.infer({"parameter": input_tensor}) - assert np.allclose(result, expected_output) + assert np.allclose(results, expected_output) -def test_load_network(device): +def test_compile_model(device): ie = Core() - net = ie.read_network(model=test_net_xml, weights=test_net_bin) - exec_net = ie.load_network(net, device) + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = ie.compile_model(func, device) assert isinstance(exec_net, ExecutableNetwork) -def test_read_network(): - ie_core = Core() - net = ie_core.read_network(model=test_net_xml, weights=test_net_bin) - assert isinstance(net, IENetwork) +def test_read_model_from_ir(): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + assert isinstance(func, Function) - net = ie_core.read_network(model=test_net_xml) - assert isinstance(net, IENetwork) + func = core.read_model(model=test_net_xml) + assert isinstance(func, Function) -def test_read_network_from_blob(): - ie_core = Core() +def test_read_model_from_tensor(): + core = Core() model = open(test_net_xml).read() - blob = blob_from_file(test_net_bin) - net = ie_core.read_network(model=model, blob=blob) - assert isinstance(net, IENetwork) + tensor = tensor_from_file(test_net_bin) + func = core.read_model(model=model, weights=tensor) + assert isinstance(func, Function) -def test_read_network_from_blob_valid(): - ie_core = Core() - model = open(test_net_xml).read() - blob = blob_from_file(test_net_bin) - net = ie_core.read_network(model=model, blob=blob) - ref_net = ie_core.read_network(model=test_net_xml, weights=test_net_bin) - assert net.name == ref_net.name - assert net.batch_size == ref_net.batch_size - ii_net = net.input_info - ii_net2 = ref_net.input_info - o_net = net.outputs - o_net2 = ref_net.outputs - assert ii_net.keys() == ii_net2.keys() - assert o_net.keys() == o_net2.keys() +def test_read_model_as_path(): + core = Core() + func = core.read_model(model=Path(test_net_xml), weights=Path(test_net_bin)) + assert isinstance(func, Function) + func = core.read_model(model=test_net_xml, weights=Path(test_net_bin)) + assert isinstance(func, Function) -def test_read_network_as_path(): - ie_core = Core() - net = ie_core.read_network(model=Path(test_net_xml), weights=Path(test_net_bin)) - assert isinstance(net, IENetwork) + func = core.read_model(model=Path(test_net_xml)) + assert isinstance(func, Function) - net = ie_core.read_network(model=test_net_xml, weights=Path(test_net_bin)) - assert isinstance(net, IENetwork) - net = ie_core.read_network(model=Path(test_net_xml)) - assert isinstance(net, IENetwork) +def test_read_model_from_onnx(): + core = Core() + func = core.read_model(model=test_net_onnx) + assert isinstance(func, Function) -def test_read_network_from_onnx(): - ie_core = Core() - net = ie_core.read_network(model=test_net_onnx) - assert isinstance(net, IENetwork) +def test_read_model_from_onnx_as_path(): + core = Core() + func = core.read_model(model=Path(test_net_onnx)) + assert isinstance(func, Function) -def test_read_network_from_onnx_as_path(): - ie_core = Core() - net = ie_core.read_network(model=Path(test_net_onnx)) - assert isinstance(net, IENetwork) - - -def test_read_net_from_buffer(): - ie_core = Core() - with open(test_net_bin, "rb") as f: - bin = f.read() - with open(model_path()[0], "rb") as f: - xml = f.read() - net = ie_core.read_network(model=xml, weights=bin) - assert isinstance(net, IENetwork) +# @pytest.mark.xfail("68212") +# def test_read_net_from_buffer(): +# core = Core() +# with open(test_net_bin, "rb") as f: +# bin = f.read() +# with open(model_path()[0], "rb") as f: +# xml = f.read() +# func = core.read_model(model=xml, weights=bin) +# assert isinstance(func, IENetwork) +@pytest.mark.xfail("68212") def test_net_from_buffer_valid(): - ie_core = Core() + core = Core() with open(test_net_bin, "rb") as f: bin = f.read() with open(model_path()[0], "rb") as f: xml = f.read() - net = ie_core.read_network(model=xml, weights=bin) - ref_net = ie_core.read_network(model=test_net_xml, weights=test_net_bin) - assert net.name == ref_net.name - assert net.batch_size == ref_net.batch_size - ii_net = net.input_info - ii_net2 = ref_net.input_info - o_net = net.outputs - o_net2 = ref_net.outputs - assert ii_net.keys() == ii_net2.keys() - assert o_net.keys() == o_net2.keys() + func = core.read_model(model=xml, weights=bin) + ref_func = core.read_model(model=test_net_xml, weights=test_net_bin) + assert func.name == func.name + assert func.batch_size == ref_func.batch_size + ii_func = func.input_info + ii_func2 = ref_func.input_info + o_func = func.outputs + o_func2 = ref_func.outputs + assert ii_func.keys() == ii_func2.keys() + assert o_func.keys() == o_func2.keys() def test_get_version(device): @@ -230,28 +201,29 @@ def test_get_metric_str(): f"metric must be string but {type(param)} is returned" -def test_query_network(device): +def test_query_model(device): ie = Core() - net = ie.read_network(model=test_net_xml, weights=test_net_bin) - query_res = ie.query_network(network=net, device_name=device) - func_net = net.get_function() - ops_net = func_net.get_ordered_ops() - ops_net_names = [op.friendly_name for op in ops_net] - assert [key for key in query_res.keys() if key not in ops_net_names] == [], \ - "Not all network layers present in query_network results" + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + query_res = ie.query_model(model=func, device_name=device) + ops_func = func.get_ordered_ops() + ops_func_names = [op.friendly_name for op in ops_func] + assert [key for key in query_res.keys() if key not in ops_func_names] == [], \ + "Not all network layers present in query_model results" assert next(iter(set(query_res.values()))) == device, "Wrong device for some layers" +@pytest.mark.dynamic_library @pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device independent test") def test_register_plugin(): ie = Core() ie.register_plugin("MKLDNNPlugin", "BLA") - net = ie.read_network(model=test_net_xml, weights=test_net_bin) - exec_net = ie.load_network(net, "BLA") + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = ie.compile_model(func, "BLA") assert isinstance(exec_net, ExecutableNetwork), \ "Cannot load the network to the registered plugin with name 'BLA'" +@pytest.mark.dynamic_library @pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device independent test") def test_register_plugins(): ie = Core() @@ -262,21 +234,92 @@ def test_register_plugins(): elif platform == "win32": ie.register_plugins(plugins_win_xml) - net = ie.read_network(model=test_net_xml, weights=test_net_bin) - exec_net = ie.load_network(net, "CUSTOM") + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = ie.compile_model(func, "CUSTOM") assert isinstance(exec_net, ExecutableNetwork), "Cannot load the network to " \ "the registered plugin with name 'CUSTOM' " \ - "registred in the XML file" + "registered in the XML file" -def test_create_IENetwork_from_nGraph(): - element_type = Type.f32 - param = Parameter(element_type, Shape([1, 3, 22, 22])) - relu = ov.relu(param) - func = Function([relu], [param], "test") - cnnNetwork = IENetwork(func) - assert cnnNetwork is not None - func2 = cnnNetwork.get_function() - assert func2 is not None - assert len(func2.get_ops()) == 3 +@pytest.mark.skip(reason="Need to figure out if it's expected behaviour (fails with C++ API as well") +def test_unregister_plugin(device): + ie = Core() + ie.unload_plugin(device) + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + with pytest.raises(RuntimeError) as e: + ie.load_network(func, device) + assert f"Device with '{device}' name is not registered in the InferenceEngine" in str(e.value) + + +@pytest.mark.xfail("68212") +@pytest.mark.template_extension +def test_add_extension(device): + model = bytes(b""" + + + + + + 2 + 2 + 2 + 1 + + + + + + + + 2 + 2 + 2 + 1 + + + + + 2 + 2 + 2 + 1 + + + + + + + 2 + 2 + 2 + 1 + + + + + + + + +""") + + core = Core() + if platform == "win32": + core.add_extension(extension_path="template_extension.dll") + else: + core.add_extension(extension_path="libtemplate_extension.so") + func = core.read_model(model=model, init_from_buffer=True) + assert isinstance(func, Function) + + # input_blob = next(iter(network.input_info)) + # n, c, h, w = network.input_info[input_blob].input_data.shape + + # input_values = np.ndarray(buffer=np.array([1, 2, 3, 4, 5, 6, 7, 8]), shape = (n, c, h, w), dtype=int) + # expected = np.ndarray(buffer=np.array([12, 13, 14, 15, 16, 17, 18, 19]), + # shape = (n, c, h, w), dtype=int) + # + # exec_network = core.compile_model(func, device) + # computed = exec_network.infer_new_request(inputs={input_blob : input_values}) + # output_blob = next(iter(network.outputs)) + # assert np.allclose(expected, computed[output_blob], atol=1e-2, rtol=1e-2) diff --git a/runtime/bindings/python/tests/test_inference_engine/test_executable_network.py b/runtime/bindings/python/tests/test_inference_engine/test_executable_network.py new file mode 100644 index 00000000000000..76d6775fcb45fe --- /dev/null +++ b/runtime/bindings/python/tests/test_inference_engine/test_executable_network.py @@ -0,0 +1,282 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import os +import pytest +import numpy as np + +from ..conftest import model_path, read_image +from openvino.impl import Function, ConstOutput, Shape + +from openvino import Core, Tensor + +is_myriad = os.environ.get("TEST_DEVICE") == "MYRIAD" +test_net_xml, test_net_bin = model_path(is_myriad) + + +def test_get_metric(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + network_name = exec_net.get_metric("NETWORK_NAME") + assert network_name == "test_model" + + +@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device dependent test") +def test_get_config(device): + core = Core() + if core.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to CPU dependent test") + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + config = exec_net.get_config("PERF_COUNT") + assert config == "NO" + + +def test_get_runtime_function(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + runtime_func = exec_net.get_runtime_function() + assert isinstance(runtime_func, Function) + + +@pytest.mark.skip(reason="After infer will be implemented") +def test_export_import(): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, "CPU") + exported_net_file = "exported_model.bin" + exec_net.export_model(network_model=exported_net_file) + assert os.path.exists(exported_net_file) + exec_net = core.import_network(exported_net_file, "CPU") + os.remove(exported_net_file) + img = read_image() + res = exec_net.infer({"data": img}) + assert np.argmax(res["fc_out"][0]) == 3 + del exec_net + del core + + +def test_get_input_i(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + input = exec_net.input(0) + input_node = input.get_node() + name = input_node.friendly_name + assert isinstance(input, ConstOutput) + assert name == "data" + + +def test_get_input_tensor_name(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + input = exec_net.input("data") + input_node = input.get_node() + name = input_node.friendly_name + assert isinstance(input, ConstOutput) + assert name == "data" + + +def test_get_input(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + input = exec_net.input() + input_node = input.get_node() + name = input_node.friendly_name + assert isinstance(input, ConstOutput) + assert name == "data" + + +def test_get_output_i(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + output = exec_net.output(0) + assert isinstance(output, ConstOutput) + + +def test_get_output(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + output = exec_net.output() + assert isinstance(output, ConstOutput) + + +def test_input_set_friendly_name(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + input = exec_net.input("data") + input_node = input.get_node() + input_node.set_friendly_name("input_1") + name = input_node.friendly_name + assert isinstance(input, ConstOutput) + assert name == "input_1" + + +def test_output_set_friendly_name(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + output = exec_net.output(0) + output_node = output.get_node() + output_node.set_friendly_name("output_1") + name = output_node.friendly_name + assert isinstance(output, ConstOutput) + assert name == "output_1" + + +def test_outputs(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + outputs = exec_net.outputs + assert isinstance(outputs, list) + assert len(outputs) == 1 + + +def test_outputs_items(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + outputs = exec_net.outputs + assert isinstance(outputs[0], ConstOutput) + + +def test_output_type(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + output = exec_net.output(0) + output_type = output.get_element_type().get_type_name() + assert output_type == "f32" + + +def test_output_shape(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + output = exec_net.output(0) + expected_shape = Shape([1, 10]) + assert str(output.get_shape()) == str(expected_shape) + + +def test_input_get_index(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + input = exec_net.input(0) + expected_idx = 0 + assert input.get_index() == expected_idx + + +def test_inputs(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + inputs = exec_net.inputs + assert isinstance(inputs, list) + assert len(inputs) == 1 + + +def test_inputs_items(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + inputs = exec_net.inputs + assert isinstance(inputs[0], ConstOutput) + + +def test_inputs_get_friendly_name(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + inputs = exec_net.inputs + input_0 = inputs[0] + node = input_0.get_node() + name = node.friendly_name + assert name == "data" + + +def test_inputs_set_friendly_name(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + inputs = exec_net.inputs + input_0 = inputs[0] + node = input_0.get_node() + node.set_friendly_name("input_0") + name = node.friendly_name + assert name == "input_0" + + +def test_inputs_docs(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + inputs = exec_net.inputs + input_0 = inputs[0] + expected_string = "openvino.impl.ConstOutput wraps ov::Output" + assert input_0.__doc__ == expected_string + + +def test_infer_new_request_numpy(device): + ie = Core() + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + img = read_image() + exec_net = ie.compile_model(func, device) + res = exec_net.infer_new_request({"data": img}) + assert np.argmax(res) == 2 + + +def test_infer_new_request_tensor_numpy_copy(device): + ie = Core() + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + img = read_image() + tensor = Tensor(img) + exec_net = ie.compile_model(func, device) + res_tensor = exec_net.infer_new_request({"data": tensor}) + res_img = exec_net.infer_new_request({"data": tensor}) + assert np.argmax(res_tensor) == 2 + assert np.argmax(res_tensor) == np.argmax(res_img) + + +def test_infer_tensor_numpy_shared_memory(device): + ie = Core() + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + img = read_image() + img = np.ascontiguousarray(img) + tensor = Tensor(img, shared_memory=True) + exec_net = ie.compile_model(func, device) + res_tensor = exec_net.infer_new_request({"data": tensor}) + res_img = exec_net.infer_new_request({"data": tensor}) + assert np.argmax(res_tensor) == 2 + assert np.argmax(res_tensor) == np.argmax(res_img) + + +def test_infer_new_request_wrong_port_name(device): + ie = Core() + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + img = read_image() + tensor = Tensor(img) + exec_net = ie.compile_model(func, device) + with pytest.raises(KeyError) as e: + exec_net.infer_new_request({"_data_": tensor}) + assert "Port for tensor named _data_ was not found!" in str(e.value) + + +def test_infer_tensor_wrong_input_data(device): + ie = Core() + func = ie.read_model(model=test_net_xml, weights=test_net_bin) + img = read_image() + img = np.ascontiguousarray(img) + tensor = Tensor(img, shared_memory=True) + exec_net = ie.compile_model(func, device) + with pytest.raises(TypeError) as e: + exec_net.infer_new_request({0.: tensor}) + assert "Incompatible key type for tensor named: 0." in str(e.value) diff --git a/runtime/bindings/python/tests/test_inference_engine/test_infer_request.py b/runtime/bindings/python/tests/test_inference_engine/test_infer_request.py index 518a11cb37dead..cf9a17f459fc5d 100644 --- a/runtime/bindings/python/tests/test_inference_engine/test_infer_request.py +++ b/runtime/bindings/python/tests/test_inference_engine/test_infer_request.py @@ -4,138 +4,197 @@ import numpy as np import os import pytest +import datetime +import time -from tests.test_inference_engine.helpers import model_path, read_image -from openvino import Core, Blob, TensorDesc, StatusCode - +from ..conftest import model_path, read_image +from openvino import Core, AsyncInferQueue, Tensor, ProfilingInfo is_myriad = os.environ.get("TEST_DEVICE") == "MYRIAD" test_net_xml, test_net_bin = model_path(is_myriad) -def test_get_perf_counts(device): - ie_core = Core() - net = ie_core.read_network(test_net_xml, test_net_bin) - ie_core.set_config({"PERF_COUNT": "YES"}, device) - exec_net = ie_core.load_network(net, device) +def test_get_profiling_info(device): + core = Core() + func = core.read_model(test_net_xml, test_net_bin) + core.set_config({"PERF_COUNT": "YES"}, device) + exec_net = core.compile_model(func, device) img = read_image() request = exec_net.create_infer_request() - td = TensorDesc("FP32", [1, 3, 32, 32], "NCHW") - input_blob = Blob(td, img) - request.set_input({"data": input_blob}) - request.infer() - pc = request.get_perf_counts() - assert pc["29"]["status"] == "EXECUTED" - assert pc["29"]["layer_type"] == "FullyConnected" - del exec_net - del ie_core - del net - - -@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", - reason=f"Can't run test on device {os.environ.get('TEST_DEVICE', 'CPU')}, " - "Dynamic batch fully supported only on CPU") -@pytest.mark.skip(reason="Fix") -def test_set_batch_size(device): - ie_core = Core() - ie_core.set_config({"DYN_BATCH_ENABLED": "YES"}, device) - net = ie_core.read_network(test_net_xml, test_net_bin) - net.batch_size = 10 - data = np.ones(shape=net.input_info["data"].input_data.shape) - exec_net = ie_core.load_network(net, device) - data[0] = read_image()[0] - request = exec_net.create_infer_request() - request.set_batch(1) - td = TensorDesc("FP32", [1, 3, 32, 32], "NCHW") - input_blob = Blob(td, data) - request.set_input({"data": input_blob}) - request.infer() - assert np.allclose(int(round(request.output_blobs["fc_out"].buffer[0][2])), 1), \ - "Incorrect data for 1st batch" - del exec_net - del ie_core - del net - - -@pytest.mark.skip(reason="Fix") -def test_set_zero_batch_size(device): - ie_core = Core() - net = ie_core.read_network(test_net_xml, test_net_bin) - exec_net = ie_core.load_network(net, device) - request = exec_net.create_infer_request() - with pytest.raises(ValueError) as e: - request.set_batch(0) - assert "Batch size should be positive integer number but 0 specified" in str(e.value) - del exec_net - del ie_core - del net - - -@pytest.mark.skip(reason="Fix") -def test_set_negative_batch_size(device): - ie_core = Core() - net = ie_core.read_network(test_net_xml, test_net_bin) - exec_net = ie_core.load_network(net, device) - request = exec_net.create_infer_request() - with pytest.raises(ValueError) as e: - request.set_batch(-1) - assert "Batch size should be positive integer number but -1 specified" in str(e.value) - del exec_net - del ie_core - del net + request.infer({0: img}) + assert request.latency > 0 + prof_info = request.get_profiling_info() + soft_max_node = next(node for node in prof_info if node.node_name == "fc_out") + assert soft_max_node.node_type == "Softmax" + assert soft_max_node.status == ProfilingInfo.Status.OPTIMIZED_OUT + assert isinstance(soft_max_node.real_time, datetime.timedelta) + assert isinstance(soft_max_node.cpu_time, datetime.timedelta) + assert isinstance(soft_max_node.exec_type, str) + + +def test_tensor_setter(device): + core = Core() + func = core.read_model(test_net_xml, test_net_bin) + exec_net_1 = core.compile_model(model=func, device_name=device) + exec_net_2 = core.compile_model(model=func, device_name=device) + img = read_image() + tensor = Tensor(img) -def test_blob_setter(device): - ie_core = Core() - net = ie_core.read_network(test_net_xml, test_net_bin) - exec_net_1 = ie_core.load_network(network=net, device_name=device) + request1 = exec_net_1.create_infer_request() + request1.set_tensor("data", tensor) + t1 = request1.get_tensor("data") - net.input_info["data"].layout = "NHWC" - exec_net_2 = ie_core.load_network(network=net, device_name=device) + assert np.allclose(tensor.data, t1.data, atol=1e-2, rtol=1e-2) - img = read_image() + res = request1.infer({0: tensor}) + res_1 = np.sort(res[0]) + t2 = request1.get_tensor("fc_out") + assert np.allclose(t2.data, res[0].data, atol=1e-2, rtol=1e-2) - request1 = exec_net_1.create_infer_request() - tensor_desc = TensorDesc("FP32", [1, 3, img.shape[2], img.shape[3]], "NCHW") - img_blob1 = Blob(tensor_desc, img) - request1.set_input({"data": img_blob1}) - request1.infer() - res_1 = np.sort(request1.get_blob("fc_out").buffer) - - img = np.transpose(img, axes=(0, 2, 3, 1)).astype(np.float32) - tensor_desc = TensorDesc("FP32", [1, 3, 32, 32], "NHWC") - img_blob = Blob(tensor_desc, img) request = exec_net_2.create_infer_request() - request.set_blob("data", img_blob) - request.infer() - res_2 = np.sort(request.get_blob("fc_out").buffer) + res = request.infer({"data": tensor}) + res_2 = np.sort(request.get_tensor("fc_out").data) assert np.allclose(res_1, res_2, atol=1e-2, rtol=1e-2) + request.set_tensor("data", tensor) + t3 = request.get_tensor("data") + assert np.allclose(t3.data, t1.data, atol=1e-2, rtol=1e-2) + + +def test_set_tensors(device): + core = Core() + func = core.read_model(test_net_xml, test_net_bin) + exec_net = core.compile_model(func, device) + + data1 = read_image() + tensor1 = Tensor(data1) + data2 = np.ones(shape=(1, 10), dtype=np.float32) + tensor2 = Tensor(data2) + data3 = np.ones(shape=(1, 3, 32, 32), dtype=np.float32) + tensor3 = Tensor(data3) + data4 = np.zeros(shape=(1, 10), dtype=np.float32) + tensor4 = Tensor(data4) + + request = exec_net.create_infer_request() + request.set_tensors({"data": tensor1, "fc_out": tensor2}) + t1 = request.get_tensor("data") + t2 = request.get_tensor("fc_out") + assert np.allclose(tensor1.data, t1.data, atol=1e-2, rtol=1e-2) + assert np.allclose(tensor2.data, t2.data, atol=1e-2, rtol=1e-2) + + request.set_output_tensors({0: tensor2}) + output_node = exec_net.outputs[0] + t3 = request.get_tensor(output_node) + assert np.allclose(tensor2.data, t3.data, atol=1e-2, rtol=1e-2) + + request.set_input_tensors({0: tensor1}) + output_node = exec_net.inputs[0] + t4 = request.get_tensor(output_node) + assert np.allclose(tensor1.data, t4.data, atol=1e-2, rtol=1e-2) + + output_node = exec_net.inputs[0] + request.set_tensor(output_node, tensor3) + t5 = request.get_tensor(output_node) + assert np.allclose(tensor3.data, t5.data, atol=1e-2, rtol=1e-2) + + request.set_input_tensor(tensor3) + t6 = request.get_tensor(request.inputs[0]) + assert np.allclose(tensor3.data, t6.data, atol=1e-2, rtol=1e-2) + + request.set_input_tensor(0, tensor1) + t7 = request.get_tensor(request.inputs[0]) + assert np.allclose(tensor1.data, t7.data, atol=1e-2, rtol=1e-2) + + request.set_output_tensor(tensor2) + t8 = request.get_tensor(request.outputs[0]) + assert np.allclose(tensor2.data, t8.data, atol=1e-2, rtol=1e-2) + + request.set_output_tensor(0, tensor4) + t9 = request.get_tensor(request.outputs[0]) + assert np.allclose(tensor4.data, t9.data, atol=1e-2, rtol=1e-2) + def test_cancel(device): - ie_core = Core() - net = ie_core.read_network(test_net_xml, test_net_bin) - exec_net = ie_core.load_network(net, device) + core = Core() + func = core.read_model(test_net_xml, test_net_bin) + exec_net = core.compile_model(func, device) img = read_image() - td = TensorDesc("FP32", [1, 3, 32, 32], "NCHW") - input_blob = Blob(td, img) request = exec_net.create_infer_request() - def callback(req, code, array): - array.append(42) - - data = [] - request.set_completion_callback(callback, data) - request.set_input({"data": input_blob}) - request.async_infer() + request.start_async({0: img}) request.cancel() with pytest.raises(RuntimeError) as e: request.wait() assert "[ INFER_CANCELLED ]" in str(e.value) - # check if callback has executed - assert data == [42] - request.async_infer() - status = request.wait() - assert status == StatusCode.OK - assert data == [42, 42] + request.start_async({"data": img}) + request.cancel() + with pytest.raises(RuntimeError) as e: + request.wait_for(1) + assert "[ INFER_CANCELLED ]" in str(e.value) + + +def test_start_async(device): + core = Core() + func = core.read_model(test_net_xml, test_net_bin) + exec_net = core.compile_model(func, device) + img = read_image() + jobs = 3 + requests = [] + for _ in range(jobs): + requests.append(exec_net.create_infer_request()) + + def callback(callbacks_info): + time.sleep(0.01) + callbacks_info["finished"] += 1 + + callbacks_info = {} + callbacks_info["finished"] = 0 + for request in requests: + request.set_callback(callback, callbacks_info) + request.start_async({0: img}) + for request in requests: + request.wait() + assert request.latency > 0 + assert callbacks_info["finished"] == jobs + + +def test_infer_mixed_keys(device): + core = Core() + func = core.read_model(test_net_xml, test_net_bin) + core.set_config({"PERF_COUNT": "YES"}, device) + model = core.compile_model(func, device) + + img = read_image() + tensor = Tensor(img) + + data2 = np.ones(shape=img.shape, dtype=np.float32) + tensor2 = Tensor(data2) + + request = model.create_infer_request() + res = request.infer({0: tensor2, "data": tensor}) + assert np.argmax(res) == 2 + + +def test_infer_queue(device): + jobs = 8 + num_request = 4 + core = Core() + func = core.read_model(test_net_xml, test_net_bin) + exec_net = core.compile_model(func, device) + infer_queue = AsyncInferQueue(exec_net, num_request) + jobs_done = [{"finished": False, "latency": 0} for _ in range(jobs)] + + def callback(request, job_id): + jobs_done[job_id]["finished"] = True + jobs_done[job_id]["latency"] = request.latency + + img = read_image() + infer_queue.set_callback(callback) + assert infer_queue.is_ready + for i in range(jobs): + infer_queue.start_async({"data": img}, i) + infer_queue.wait_all() + assert all(job["finished"] for job in jobs_done) + assert all(job["latency"] > 0 for job in jobs_done) diff --git a/runtime/bindings/python/tests/test_inference_engine/test_output_const_node.py b/runtime/bindings/python/tests/test_inference_engine/test_output_const_node.py new file mode 100644 index 00000000000000..d7d1a2eea68a36 --- /dev/null +++ b/runtime/bindings/python/tests/test_inference_engine/test_output_const_node.py @@ -0,0 +1,83 @@ +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import os + +from ..conftest import model_path +from openvino.impl import ConstOutput, Shape, PartialShape, Type + +from openvino import Core + +is_myriad = os.environ.get("TEST_DEVICE") == "MYRIAD" +test_net_xml, test_net_bin = model_path(is_myriad) + + +def model_path(is_myriad=False): + path_to_repo = os.environ["MODELS_PATH"] + if not is_myriad: + test_xml = os.path.join(path_to_repo, "models", "test_model", "test_model_fp32.xml") + test_bin = os.path.join(path_to_repo, "models", "test_model", "test_model_fp32.bin") + else: + test_xml = os.path.join(path_to_repo, "models", "test_model", "test_model_fp16.xml") + test_bin = os.path.join(path_to_repo, "models", "test_model", "test_model_fp16.bin") + return (test_xml, test_bin) + + +def test_const_output_type(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + node = exec_net.input(0) + assert isinstance(node, ConstOutput) + + +def test_const_output_docs(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + node = exec_net.input(0) + exptected_string = "openvino.impl.ConstOutput wraps ov::Output" + assert node.__doc__ == exptected_string + + +def test_const_output_get_index(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + node = exec_net.input("data") + assert node.get_index() == 0 + + +def test_const_output_get_element_type(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + node = exec_net.input("data") + assert node.get_element_type() == Type.f32 + + +def test_const_output_get_shape(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + node = exec_net.input("data") + expected_shape = Shape([1, 3, 32, 32]) + assert str(node.get_shape()) == str(expected_shape) + + +def test_const_output_get_partial_shape(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + node = exec_net.input("data") + expected_partial_shape = PartialShape([1, 3, 32, 32]) + assert node.get_partial_shape() == expected_partial_shape + + +def test_const_output_get_target_inputs(device): + core = Core() + func = core.read_model(model=test_net_xml, weights=test_net_bin) + exec_net = core.compile_model(func, device) + outputs = exec_net.outputs + for node in outputs: + assert isinstance(node.get_target_inputs(), set) diff --git a/runtime/bindings/python/tests/test_inference_engine/test_tensor.py b/runtime/bindings/python/tests/test_inference_engine/test_tensor.py index d840bfa71f4a34..607364d9bc6ae6 100644 --- a/runtime/bindings/python/tests/test_inference_engine/test_tensor.py +++ b/runtime/bindings/python/tests/test_inference_engine/test_tensor.py @@ -4,7 +4,7 @@ import numpy as np import pytest -from tests.test_inference_engine.helpers import read_image +from ..conftest import read_image from openvino import Tensor import openvino as ov diff --git a/runtime/bindings/python/tests/test_ngraph/test_basic.py b/runtime/bindings/python/tests/test_ngraph/test_basic.py index 02fb9f4ca3acdb..011abee486eb95 100644 --- a/runtime/bindings/python/tests/test_ngraph/test_basic.py +++ b/runtime/bindings/python/tests/test_ngraph/test_basic.py @@ -12,13 +12,11 @@ from openvino.pyopenvino import VariantInt, VariantString from openvino.exceptions import UserInputError -from openvino.impl import Function, PartialShape, Shape, Type +from openvino.impl import Function, PartialShape, Shape, Type, layout_helpers from openvino.impl.op import Parameter from tests.runtime import get_runtime from tests.test_ngraph.util import run_op_node -from tests import skip_issue_67415 - def test_ngraph_function_api(): shape = [2, 2] @@ -35,6 +33,12 @@ def test_ngraph_function_api(): assert op_types == ["Parameter", "Parameter", "Parameter", "Add", "Multiply", "Result"] assert len(function.get_ops()) == 6 assert function.get_output_size() == 1 + assert ["A", "B", "C"] == [input.get_node().friendly_name for input in function.inputs] + assert ["Result"] == [output.get_node().get_type_name() for output in function.outputs] + assert function.input(0).get_node().friendly_name == "A" + assert function.output(0).get_node().get_type_name() == "Result" + assert function.input(tensor_name="A").get_node().friendly_name == "A" + assert function.output().get_node().get_type_name() == "Result" assert function.get_output_op(0).get_type_name() == "Result" assert function.get_output_element_type(0) == parameter_a.get_element_type() assert list(function.get_output_shape(0)) == [2, 2] @@ -48,7 +52,7 @@ def test_ngraph_function_api(): "dtype", [ np.float32, - pytest.param(np.float64, marks=skip_issue_67415), + np.float64, np.int8, np.int16, np.int32, @@ -173,7 +177,7 @@ def test_convert_to_float(destination_type, rand_range, in_dtype, expected_type) ) def test_convert_to_int(destination_type, expected_type): np.random.seed(133391) - input_data = (np.ceil(-8 + np.random.rand(2, 3, 4) * 16)).astype(np.float32) + input_data = (np.ceil(-8 + np.random.rand(2, 3, 4) * 16)).astype(expected_type) expected = np.array(input_data, dtype=expected_type) result = run_op_node([input_data], ops.convert, destination_type) assert np.allclose(result, expected) @@ -195,7 +199,7 @@ def test_convert_to_int(destination_type, expected_type): ) def test_convert_to_uint(destination_type, expected_type): np.random.seed(133391) - input_data = np.ceil(np.random.rand(2, 3, 4) * 16).astype(np.float32) + input_data = np.ceil(np.random.rand(2, 3, 4) * 16).astype(expected_type) expected = np.array(input_data, dtype=expected_type) result = run_op_node([input_data], ops.convert, destination_type) assert np.allclose(result, expected) @@ -534,3 +538,56 @@ def test_layout(): layout = ov.Layout("N...C") assert layout == "N...C" assert layout != "NC?" + + +def test_layout_helpers(): + layout = ov.Layout("NCHWD") + assert(layout_helpers.has_batch(layout)) + assert(layout_helpers.has_channels(layout)) + assert(layout_helpers.has_depth(layout)) + assert(layout_helpers.has_height(layout)) + assert(layout_helpers.has_width(layout)) + + assert layout_helpers.batch_idx(layout) == 0 + assert layout_helpers.channels_idx(layout) == 1 + assert layout_helpers.height_idx(layout) == 2 + assert layout_helpers.width_idx(layout) == 3 + assert layout_helpers.depth_idx(layout) == 4 + + layout = ov.Layout("N...C") + assert(layout_helpers.has_batch(layout)) + assert(layout_helpers.has_channels(layout)) + assert not(layout_helpers.has_depth(layout)) + assert not(layout_helpers.has_height(layout)) + assert not (layout_helpers.has_width(layout)) + + assert layout_helpers.batch_idx(layout) == 0 + assert layout_helpers.channels_idx(layout) == -1 + + with pytest.raises(RuntimeError): + layout_helpers.height_idx(layout) + + with pytest.raises(RuntimeError): + layout_helpers.width_idx(layout) + + with pytest.raises(RuntimeError): + layout_helpers.depth_idx(layout) + + layout = ov.Layout("NC?") + assert(layout_helpers.has_batch(layout)) + assert(layout_helpers.has_channels(layout)) + assert not(layout_helpers.has_depth(layout)) + assert not(layout_helpers.has_height(layout)) + assert not (layout_helpers.has_width(layout)) + + assert layout_helpers.batch_idx(layout) == 0 + assert layout_helpers.channels_idx(layout) == 1 + + with pytest.raises(RuntimeError): + layout_helpers.height_idx(layout) + + with pytest.raises(RuntimeError): + layout_helpers.width_idx(layout) + + with pytest.raises(RuntimeError): + layout_helpers.depth_idx(layout) diff --git a/runtime/bindings/python/tests/test_ngraph/test_data_movement.py b/runtime/bindings/python/tests/test_ngraph/test_data_movement.py index 0baac90c011e0a..624427210a888b 100644 --- a/runtime/bindings/python/tests/test_ngraph/test_data_movement.py +++ b/runtime/bindings/python/tests/test_ngraph/test_data_movement.py @@ -8,8 +8,6 @@ from tests.runtime import get_runtime from tests.test_ngraph.util import run_op_node -from tests import xfail_issue_67415 - def test_reverse_sequence(): input_data = np.array( @@ -180,7 +178,6 @@ def test_pad_constant(): assert np.allclose(result, expected) -@xfail_issue_67415 def test_select(): cond = np.array([[False, False], [True, False], [True, True]]) then_node = np.array([[-1, 0], [1, 2], [3, 4]], dtype=np.int32) diff --git a/runtime/bindings/python/tests/test_ngraph/test_ops.py b/runtime/bindings/python/tests/test_ngraph/test_ops.py index 4e4ce9005cfce3..4719466c451380 100644 --- a/runtime/bindings/python/tests/test_ngraph/test_ops.py +++ b/runtime/bindings/python/tests/test_ngraph/test_ops.py @@ -10,7 +10,6 @@ from openvino.impl.op import Constant, Parameter from tests.runtime import get_runtime -from tests import xfail_issue_67415 from tests import xfail_issue_54663 @@ -523,7 +522,6 @@ def test_axisset(): assert set(tuple_axisset) == set(set_axisset) -@xfail_issue_67415 def test_select(): element_type = Type.f32 A = Parameter(Type.boolean, Shape([1, 2])) diff --git a/runtime/bindings/python/tests/test_ngraph/test_ops_binary.py b/runtime/bindings/python/tests/test_ngraph/test_ops_binary.py index 7a910eae3c5b58..8e965c9e3f01c3 100644 --- a/runtime/bindings/python/tests/test_ngraph/test_ops_binary.py +++ b/runtime/bindings/python/tests/test_ngraph/test_ops_binary.py @@ -10,8 +10,6 @@ from tests.runtime import get_runtime from tests.test_ngraph.util import run_op_node -from tests import xfail_issue_67415 - @pytest.mark.parametrize( "ng_api_helper,numpy_function", @@ -84,7 +82,6 @@ def test_binary_op_with_scalar(ng_api_helper, numpy_function): assert np.allclose(result, expected) -@xfail_issue_67415 @pytest.mark.parametrize( "ng_api_helper,numpy_function", [(ov.logical_and, np.logical_and), (ov.logical_or, np.logical_or), (ov.logical_xor, np.logical_xor)], @@ -107,7 +104,6 @@ def test_binary_logical_op(ng_api_helper, numpy_function): assert np.allclose(result, expected) -@xfail_issue_67415 @pytest.mark.parametrize( "ng_api_helper,numpy_function", [(ov.logical_and, np.logical_and), (ov.logical_or, np.logical_or), (ov.logical_xor, np.logical_xor)], diff --git a/runtime/bindings/python/tests/test_ngraph/test_ops_unary.py b/runtime/bindings/python/tests/test_ngraph/test_ops_unary.py index e304914180210a..7ce4f98e94535a 100644 --- a/runtime/bindings/python/tests/test_ngraph/test_ops_unary.py +++ b/runtime/bindings/python/tests/test_ngraph/test_ops_unary.py @@ -9,8 +9,6 @@ from tests.runtime import get_runtime from tests.test_ngraph.util import run_op_node -from tests import xfail_issue_67415 - @pytest.mark.parametrize( "ng_api_fn, numpy_fn, range_start, range_end", @@ -79,7 +77,6 @@ def test_unary_op_scalar(ng_api_fn, numpy_fn, input_data): assert np.allclose(result, expected) -@xfail_issue_67415 @pytest.mark.parametrize( "input_data", [(np.array([True, False, True, False])), (np.array([True])), (np.array([False]))] ) diff --git a/runtime/bindings/python/tests/test_ngraph/test_reduction.py b/runtime/bindings/python/tests/test_ngraph/test_reduction.py index 12334fbe82fa89..8ac606eaa855ec 100644 --- a/runtime/bindings/python/tests/test_ngraph/test_reduction.py +++ b/runtime/bindings/python/tests/test_ngraph/test_reduction.py @@ -10,8 +10,6 @@ from tests.runtime import get_runtime from tests.test_ngraph.util import run_op_node -from tests import xfail_issue_67415 - @pytest.mark.parametrize( "ng_api_helper, numpy_function, reduction_axes", @@ -40,7 +38,6 @@ def test_reduction_ops(ng_api_helper, numpy_function, reduction_axes): assert np.allclose(result, expected) -@xfail_issue_67415 @pytest.mark.parametrize( "ng_api_helper, numpy_function, reduction_axes", [ diff --git a/runtime/bindings/python/tests/test_ngraph/test_sequence_processing.py b/runtime/bindings/python/tests/test_ngraph/test_sequence_processing.py index ebef086f174954..c394225230e8bd 100644 --- a/runtime/bindings/python/tests/test_ngraph/test_sequence_processing.py +++ b/runtime/bindings/python/tests/test_ngraph/test_sequence_processing.py @@ -6,8 +6,7 @@ import openvino.opset8 as ov from tests.runtime import get_runtime from tests.test_ngraph.util import run_op_node -from tests import (xfail_issue_47337, - xfail_accuracy) +from tests import (xfail_issue_47337) def test_onehot(): @@ -35,7 +34,6 @@ def test_one_hot(): assert np.allclose(result, excepted) -@xfail_accuracy def test_range(): start = 5 stop = 35 diff --git a/runtime/bindings/python/tests/test_onnx/test_backend.py b/runtime/bindings/python/tests/test_onnx/test_backend.py index 63b7e527eb3753..2af5e0f9b4399f 100644 --- a/runtime/bindings/python/tests/test_onnx/test_backend.py +++ b/runtime/bindings/python/tests/test_onnx/test_backend.py @@ -6,17 +6,15 @@ import onnx.backend.test from tests import ( BACKEND_NAME, + xfail_issue_FLOAT_LIKE, skip_rng_tests, - xfail_issue_67415, xfail_issue_33488, xfail_issue_33538, xfail_issue_33581, xfail_issue_33589, - xfail_issue_33593, xfail_issue_33595, xfail_issue_33596, xfail_issue_33606, - xfail_issue_33633, xfail_issue_33651, xfail_issue_38091, xfail_issue_38699, @@ -29,7 +27,6 @@ xfail_issue_38734, xfail_issue_38735, xfail_issue_39658, - xfail_issue_39659, xfail_issue_39662, xfail_issue_44854, xfail_issue_44858, @@ -37,25 +34,22 @@ xfail_issue_44965, xfail_issue_44968, xfail_issue_45180, - xfail_issue_45344, xfail_issue_47323, xfail_issue_47337, xfail_issue_48052, xfail_issue_49207, xfail_issue_49750, xfail_issue_52463, - xfail_issue_55760, xfail_issue_58033, xfail_issue_63033, xfail_issue_63036, xfail_issue_63039, xfail_issue_63043, xfail_issue_63044, - xfail_issue_63045, xfail_issue_63136, xfail_issue_63137, xfail_issue_63138, - skip_issue_69443, + xfail_issue_69443, xfail_issue_69444, ) from tests.test_onnx.utils.onnx_backend import OpenVinoTestBackend @@ -108,49 +102,18 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None tests_expected_to_fail = [ ( - xfail_issue_67415, - "OnnxBackendNodeModelTest.test_and2d_cpu", - "OnnxBackendNodeModelTest.test_and3d_cpu", - "OnnxBackendNodeModelTest.test_and4d_cpu", - "OnnxBackendNodeModelTest.test_and_bcast3v1d_cpu", - "OnnxBackendNodeModelTest.test_and_bcast3v2d_cpu", - "OnnxBackendNodeModelTest.test_and_bcast4v2d_cpu", - "OnnxBackendNodeModelTest.test_and_bcast4v3d_cpu", - "OnnxBackendNodeModelTest.test_and_bcast4v4d_cpu", + xfail_issue_FLOAT_LIKE, + "OnnxBackendNodeModelTest.test_cast_BFLOAT16_to_FLOAT_cpu", "OnnxBackendNodeModelTest.test_cast_FLOAT16_to_DOUBLE_cpu", "OnnxBackendNodeModelTest.test_cast_FLOAT16_to_FLOAT_cpu", + "OnnxBackendNodeModelTest.test_cast_FLOAT_to_BFLOAT16_cpu", + "OnnxBackendNodeModelTest.test_castlike_BFLOAT16_to_FLOAT_expanded_cpu", "OnnxBackendNodeModelTest.test_castlike_FLOAT16_to_DOUBLE_expanded_cpu", "OnnxBackendNodeModelTest.test_castlike_FLOAT16_to_FLOAT_expanded_cpu", - "OnnxBackendNodeModelTest.test_if_cpu", + "OnnxBackendNodeModelTest.test_castlike_FLOAT_to_BFLOAT16_expanded_cpu", "OnnxBackendNodeModelTest.test_max_float16_cpu", "OnnxBackendNodeModelTest.test_min_float16_cpu", "OnnxBackendNodeModelTest.test_mod_mixed_sign_float16_cpu", - "OnnxBackendNodeModelTest.test_not_2d_cpu", - "OnnxBackendNodeModelTest.test_not_3d_cpu", - "OnnxBackendNodeModelTest.test_not_4d_cpu", - "OnnxBackendNodeModelTest.test_or2d_cpu", - "OnnxBackendNodeModelTest.test_or3d_cpu", - "OnnxBackendNodeModelTest.test_or4d_cpu", - "OnnxBackendNodeModelTest.test_or_bcast3v1d_cpu", - "OnnxBackendNodeModelTest.test_or_bcast3v2d_cpu", - "OnnxBackendNodeModelTest.test_or_bcast4v2d_cpu", - "OnnxBackendNodeModelTest.test_or_bcast4v3d_cpu", - "OnnxBackendNodeModelTest.test_or_bcast4v4d_cpu", - "OnnxBackendNodeModelTest.test_where_example_cpu", - "OnnxBackendNodeModelTest.test_where_long_example_cpu", - "OnnxBackendNodeModelTest.test_xor2d_cpu", - "OnnxBackendNodeModelTest.test_xor3d_cpu", - "OnnxBackendNodeModelTest.test_xor4d_cpu", - "OnnxBackendNodeModelTest.test_xor_bcast3v1d_cpu", - "OnnxBackendNodeModelTest.test_xor_bcast3v2d_cpu", - "OnnxBackendNodeModelTest.test_xor_bcast4v2d_cpu", - "OnnxBackendNodeModelTest.test_xor_bcast4v3d_cpu", - "OnnxBackendNodeModelTest.test_xor_bcast4v4d_cpu", - "OnnxBackendNodeModelTest.test_compress_0_cpu", - "OnnxBackendNodeModelTest.test_compress_1_cpu", - "OnnxBackendNodeModelTest.test_compress_default_axis_cpu", - "OnnxBackendNodeModelTest.test_compress_negative_axis_cpu", - "OnnxBackendNodeModelTest.test_nonzero_example_cpu", ), ( xfail_issue_49207, @@ -165,7 +128,7 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_lstm_with_peepholes_cpu", ), ( - skip_issue_69443, + xfail_issue_69443, "OnnxBackendNodeModelTest.test_constant_pad_cpu", "OnnxBackendNodeModelTest.test_edge_pad_cpu", "OnnxBackendNodeModelTest.test_reflect_pad_cpu", @@ -175,36 +138,11 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_tile_cpu", "OnnxBackendNodeModelTest.test_tile_precomputed_cpu", ), - ( - xfail_issue_39659, - "OnnxBackendNodeModelTest.test_constantofshape_int_shape_zero_cpu", - ), - ( - xfail_issue_45344, - "OnnxBackendNodeModelTest.test_nonmaxsuppression_center_point_box_format_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_flipped_coordinates_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_identical_boxes_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_limit_output_size_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_single_box_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_and_scores_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_batches_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu", - ), ( xfail_issue_39662, - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu", "OnnxBackendNodeModelTest.test_scatter_elements_with_negative_indices_cpu", "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu", ), - (xfail_issue_33633, "OnnxBackendNodeModelTest.test_maxpool_2d_dilations_cpu"), - ( - xfail_issue_55760, - "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_example_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_example_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_random_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_random_select_last_index_cpu", - ), ( xfail_issue_38091, "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu", @@ -299,15 +237,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_align_corners_cpu", "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_A_n0p5_exclude_outside_cpu", "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_A_n0p5_exclude_outside_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_floor_align_corners_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_ceil_half_pixel_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_linear_pytorch_half_pixel_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn_cpu", ), ( xfail_issue_33581, @@ -401,11 +330,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_squeeze_cpu", "OnnxBackendNodeModelTest.test_squeeze_negative_axes_cpu", ), - ( - xfail_issue_33593, - "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_strides_cpu", - "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_pads_cpu", - ), (xfail_issue_58033, "OnnxBackendNodeModelTest.test_einsum_batch_diagonal_cpu"), ( xfail_issue_63033, @@ -450,11 +374,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_triu_square_neg_cpu", "OnnxBackendNodeModelTest.test_triu_zero_cpu", ), - ( - xfail_issue_63045, - "OnnxBackendPyTorchConvertedModelTest.test_MaxPool1d_stride_padding_dilation_cpu", - "OnnxBackendPyTorchConvertedModelTest.test_MaxPool2d_stride_padding_dilation_cpu", - ), ( skip_rng_tests, "OnnxBackendNodeModelTest.test_bernoulli_cpu", diff --git a/runtime/bindings/python/tests/test_onnx/test_onnx_external_data.py b/runtime/bindings/python/tests/test_onnx/test_onnx_external_data.py index cbeb316c79ad6c..8fd4fb89ca582d 100644 --- a/runtime/bindings/python/tests/test_onnx/test_onnx_external_data.py +++ b/runtime/bindings/python/tests/test_onnx/test_onnx_external_data.py @@ -12,9 +12,7 @@ def test_import_onnx_with_external_data(): model_path = os.path.join(os.path.dirname(__file__), "models/external_data.onnx") ie = Core() - network = ie.read_network(model=model_path) - - ng_function = network.get_function() + func = ie.read_model(model=model_path) dtype = np.float32 value_a = np.array([1.0, 3.0, 5.0], dtype=dtype) @@ -22,6 +20,6 @@ def test_import_onnx_with_external_data(): # third input [5.0, 1.0, 3.0] read from external file runtime = get_runtime() - computation = runtime.computation(ng_function) + computation = runtime.computation(func) result = computation(value_a, value_b) assert np.allclose(result, np.array([3.0, 3.0, 3.0], dtype=dtype)) diff --git a/runtime/bindings/python/tests/test_onnx/test_onnx_import.py b/runtime/bindings/python/tests/test_onnx/test_onnx_import.py index 2886ff592f3ef3..7f5387d20284f9 100644 --- a/runtime/bindings/python/tests/test_onnx/test_onnx_import.py +++ b/runtime/bindings/python/tests/test_onnx/test_onnx_import.py @@ -15,9 +15,7 @@ def test_import_onnx_function(): model_path = os.path.join(os.path.dirname(__file__), "models/add_abc.onnx") ie = Core() - network = ie.read_network(model=model_path) - - ng_function = network.get_function() + func = ie.read_model(model=model_path) dtype = np.float32 value_a = np.array([1.0], dtype=dtype) @@ -25,7 +23,7 @@ def test_import_onnx_function(): value_c = np.array([3.0], dtype=dtype) runtime = get_runtime() - computation = runtime.computation(ng_function) + computation = runtime.computation(func) result = computation(value_a, value_b, value_c) assert np.allclose(result, np.array([6], dtype=dtype)) @@ -49,5 +47,19 @@ def test_simple_graph(): runtime = get_runtime() computation = runtime.computation(ng_model_function) - assert np.array_equal(computation(1, 2, 3)[0], np.array([6.0], dtype=np.float32)) - assert np.array_equal(computation(4, 5, 6)[0], np.array([15.0], dtype=np.float32)) + assert np.array_equal( + computation( + np.array([1], dtype=np.float32), + np.array([2], dtype=np.float32), + np.array([3], dtype=np.float32), + )[0], + np.array([6.0], dtype=np.float32), + ) + assert np.array_equal( + computation( + np.array([4], dtype=np.float32), + np.array([5], dtype=np.float32), + np.array([6], dtype=np.float32), + )[0], + np.array([15.0], dtype=np.float32), + ) diff --git a/runtime/bindings/python/tests/test_onnx/test_ops_convpool.py b/runtime/bindings/python/tests/test_onnx/test_ops_convpool.py index 6637a06463b19c..6d431fea9e235d 100644 --- a/runtime/bindings/python/tests/test_onnx/test_ops_convpool.py +++ b/runtime/bindings/python/tests/test_onnx/test_ops_convpool.py @@ -369,7 +369,7 @@ def test_pool_max(ndarray_1x1x4x4): x = ndarray_1x1x4x4 y = np.array([[16, 18], [24, 26]], dtype=np.float32).reshape([1, 1, 2, 2]) - ng_results = run_node(node, [x]) + ng_results = run_node(node, [x], opset_version=7) assert np.array_equal(ng_results, [y]) diff --git a/runtime/bindings/python/tests/test_onnx/test_ops_logical.py b/runtime/bindings/python/tests/test_onnx/test_ops_logical.py index aabd4304277bf7..150d50673586ef 100644 --- a/runtime/bindings/python/tests/test_onnx/test_ops_logical.py +++ b/runtime/bindings/python/tests/test_onnx/test_ops_logical.py @@ -7,15 +7,13 @@ from tests.test_onnx.utils import run_node -from tests import xfail_issue_67415 - @pytest.mark.parametrize( "onnx_op, numpy_func, data_type", [ - pytest.param("And", np.logical_and, np.bool, marks=xfail_issue_67415), - pytest.param("Or", np.logical_or, np.bool, marks=xfail_issue_67415), - pytest.param("Xor", np.logical_xor, np.bool, marks=xfail_issue_67415), + pytest.param("And", np.logical_and, np.bool), + pytest.param("Or", np.logical_or, np.bool), + pytest.param("Xor", np.logical_xor, np.bool), pytest.param("Equal", np.equal, np.int32), pytest.param("Greater", np.greater, np.int32), pytest.param("Less", np.less, np.int32), @@ -37,7 +35,6 @@ def test_logical(onnx_op, numpy_func, data_type): assert np.array_equal(ng_results, [expected_output]) -@xfail_issue_67415 def test_logical_not(): input_data = np.array([[False, True, True], [False, True, False], [False, False, True]]) expected_output = np.logical_not(input_data) diff --git a/runtime/bindings/python/tests/test_onnx/test_ops_random.py b/runtime/bindings/python/tests/test_onnx/test_ops_random.py new file mode 100644 index 00000000000000..11388971e8759d --- /dev/null +++ b/runtime/bindings/python/tests/test_onnx/test_ops_random.py @@ -0,0 +1,53 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import numpy as np +import onnx +import onnx.mapping + +from tests.test_onnx.utils import run_node + + +def test_random_uniform(): + low = 90.0 + high = 100.0 + + node = onnx.helper.make_node( + "RandomUniform", + inputs=[], + outputs=["y"], + high=high, + low=low, + seed=10.0, + shape=(30, 30), + ) + + result = run_node(node, [])[0] + + assert result.shape == (30, 30) + assert len(np.unique(result)) == 900 + assert np.max(result) < high + assert np.min(result) > low + assert np.isclose(np.mean(result), np.mean(np.array([low, high])), rtol=0.001) + + +def test_random_normal(): + mean = 100.0 + scale = 10.0 + + node = onnx.helper.make_node( + "RandomNormal", + inputs=[], + outputs=["y"], + mean=mean, + scale=scale, + seed=10.0, + shape=(30, 30), + ) + + result = run_node(node, [])[0] + + assert result.shape == (30, 30) + assert len(np.unique(result)) == 900 + assert np.allclose(np.mean(result), mean, rtol=0.05) + assert np.allclose(np.std(result), scale, rtol=0.05) diff --git a/runtime/bindings/python/tests/test_onnx/test_ops_unary.py b/runtime/bindings/python/tests/test_onnx/test_ops_unary.py index 041466663d23a5..201458c629a60b 100644 --- a/runtime/bindings/python/tests/test_onnx/test_ops_unary.py +++ b/runtime/bindings/python/tests/test_onnx/test_ops_unary.py @@ -11,8 +11,6 @@ from tests.runtime import get_runtime from tests.test_onnx.utils import get_node_model, import_onnx_model, run_model, run_node -from tests import skip_issue_67415 - @pytest.mark.parametrize( "input_data", @@ -333,7 +331,6 @@ def test_cast_to_bool(val_type, input_data): assert np.allclose(result, expected) -@skip_issue_67415 @pytest.mark.parametrize( "val_type, range_start, range_end, in_dtype", [ @@ -359,7 +356,7 @@ def test_cast_to_float(val_type, range_start, range_end, in_dtype): ) def test_cast_to_int(val_type): np.random.seed(133391) - input_data = np.ceil(-8 + np.random.rand(2, 3, 4) * 16) + input_data = np.ceil(-8 + np.random.rand(2, 3, 4) * 16).astype(val_type) expected = np.array(input_data, dtype=val_type) model = get_node_model("Cast", input_data, opset=6, to=onnx.mapping.NP_TYPE_TO_TENSOR_TYPE[val_type]) @@ -372,7 +369,7 @@ def test_cast_to_int(val_type): ) def test_cast_to_uint(val_type): np.random.seed(133391) - input_data = np.ceil(np.random.rand(2, 3, 4) * 16) + input_data = np.ceil(np.random.rand(2, 3, 4) * 16).astype(val_type) expected = np.array(input_data, dtype=val_type) model = get_node_model("Cast", input_data, opset=6, to=onnx.mapping.NP_TYPE_TO_TENSOR_TYPE[val_type]) diff --git a/runtime/bindings/python/tests/test_onnx/test_zoo_models.py b/runtime/bindings/python/tests/test_onnx/test_zoo_models.py index 2042d7a0f6d303..ee16fa4724a5b0 100644 --- a/runtime/bindings/python/tests/test_onnx/test_zoo_models.py +++ b/runtime/bindings/python/tests/test_onnx/test_zoo_models.py @@ -77,6 +77,7 @@ def tinyyolov3_post_processing(outputs : Sequence[Any]) -> Sequence[Any]: "resnet34-v2-7": {"atol": 0.001, "rtol": 0.001}, "vgg16-7": {"atol": 0.001, "rtol": 0.001}, "vgg19-bn-7": {"atol": 0.001, "rtol": 0.001}, + "vgg19-7": {"atol": 0.001, "rtol": 0.001}, "tinyyolov2-7": {"atol": 0.001, "rtol": 0.001}, "tinyyolov2-8": {"atol": 0.001, "rtol": 0.001}, "candy-8": {"atol": 0.001, "rtol": 0.001}, @@ -115,6 +116,12 @@ def tinyyolov3_post_processing(outputs : Sequence[Any]) -> Sequence[Any]: "test_retinanet_resnet101": {"atol": 1.3e-06}, } +def tolerance_map_key_in_model_path(path): + for key in tolerance_map: + if key in path: + return key + return None + zoo_models = [] # rglob doesn't work for symlinks, so models have to be physically somwhere inside "MODELS_ROOT_DIR" for path in Path(MODELS_ROOT_DIR).rglob("*.onnx"): @@ -127,6 +134,12 @@ def tinyyolov3_post_processing(outputs : Sequence[Any]) -> Sequence[Any]: # updated model looks now: # {"model_name": path, "model_file": file, "dir": mdir, "atol": ..., "rtol": ...} model.update(tolerance_map[basedir]) + else: + # some models have the same stem, have to check if any of the keys from tolerance_map + # is found in the full model path + model_key = tolerance_map_key_in_model_path(str(path)) + if model_key is not None: + model.update(tolerance_map[model_key]) if basedir in post_processing: model.update(post_processing[basedir]) zoo_models.append(model) diff --git a/runtime/bindings/python/tests/test_onnx/utils/onnx_helpers.py b/runtime/bindings/python/tests/test_onnx/utils/onnx_helpers.py index 53c5487d31476f..570c82619eda03 100644 --- a/runtime/bindings/python/tests/test_onnx/utils/onnx_helpers.py +++ b/runtime/bindings/python/tests/test_onnx/utils/onnx_helpers.py @@ -5,7 +5,7 @@ import onnx from onnx.mapping import NP_TYPE_TO_TENSOR_TYPE -from openvino import Core, Blob, TensorDesc +from openvino import Core, Tensor from openvino.impl import Function @@ -21,9 +21,7 @@ def np_dtype_to_tensor_type(data_type: np.dtype) -> int: def import_onnx_model(model: onnx.ModelProto) -> Function: onnx.checker.check_model(model) model_byte_string = model.SerializeToString() - ie = Core() - ie_network = ie.read_network(bytes(model_byte_string), Blob(TensorDesc("U8", [], "C"))) + func = ie.read_model(bytes(model_byte_string), Tensor(type=np.uint8, shape=[])) - ng_function = ie_network.get_function() - return ng_function + return func diff --git a/runtime/bindings/python/tests/test_transformations/test_offline_api.py b/runtime/bindings/python/tests/test_transformations/test_offline_api.py new file mode 100644 index 00000000000000..72b72c811ec159 --- /dev/null +++ b/runtime/bindings/python/tests/test_transformations/test_offline_api.py @@ -0,0 +1,62 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +# TODO: change the module name according to the description in 69196 +from openvino.offline_transformations_pybind import apply_moc_transformations, apply_pot_transformations, \ + apply_low_latency_transformation, apply_pruning_transformation, apply_make_stateful_transformation + +from openvino import Function, PartialShape +import openvino as ov + + +def get_test_function(): + param = ov.opset8.parameter(PartialShape([1, 3, 22, 22]), name="parameter") + relu = ov.opset8.relu(param) + res = ov.opset8.result(relu, name="result") + return Function([res], [param], "test") + + +def test_moc_transformations(): + function = get_test_function() + + apply_moc_transformations(function, False) + + assert function is not None + assert len(function.get_ops()) == 3 + + +def test_pot_transformations(): + function = get_test_function() + + apply_pot_transformations(function, "GNA") + + assert function is not None + assert len(function.get_ops()) == 3 + + +def test_low_latency_transformation(): + function = get_test_function() + + apply_low_latency_transformation(function, True) + + assert function is not None + assert len(function.get_ops()) == 3 + + +def test_pruning_transformation(): + function = get_test_function() + + apply_pruning_transformation(function) + + assert function is not None + assert len(function.get_ops()) == 3 + + +def test_make_stateful_transformations(): + function = get_test_function() + + apply_make_stateful_transformation(function, {"parameter": "result"}) + + assert function is not None + assert len(function.get_parameters()) == 0 + assert len(function.get_results()) == 0 diff --git a/runtime/bindings/python/tests_compatibility/__init__.py b/runtime/bindings/python/tests_compatibility/__init__.py index b0348b293e8079..714761dc1f62b2 100644 --- a/runtime/bindings/python/tests_compatibility/__init__.py +++ b/runtime/bindings/python/tests_compatibility/__init__.py @@ -25,7 +25,7 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): skip_segfault = pytest.mark.skip(reason="Segmentation fault error") xfail_accuracy = xfail_test(reason="Accuracy") xfail_issue_69444 = xfail_test(reason="failed with accuracy issue") -skip_issue_69443 = pytest.mark.skip(reason="Segmentation fault due to empty pads_begin, pads_end") +xfail_issue_69443 = xfail_test(reason="Segmentation fault due to empty pads_begin, pads_end") xfail_issue_67415 = xfail_test(reason="RuntimeError: Unsupported data type for when filling blob!") xfail_issue_33488 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " "MaxUnpool") @@ -46,7 +46,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): "TfIdfVectorizer") xfail_issue_33581 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " "GatherElements") -xfail_issue_33633 = xfail_test(reason="MaxPool: dilations unsupported") xfail_issue_35923 = xfail_test(reason="RuntimeError: PReLU without weights is not supported") xfail_issue_35927 = xfail_test(reason="RuntimeError: B has zero dimension that is not allowable") xfail_issue_36486 = xfail_test(reason="RuntimeError: HardSigmoid operation should be converted " @@ -99,8 +98,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): xfail_issue_44968 = xfail_test(reason="Expected: Unsupported dynamic op: Squeeze") xfail_issue_47323 = xfail_test(reason="RuntimeError: The plugin does not support FP64") xfail_issue_47337 = xfail_test(reason="RuntimeError: Unsupported dynamic ops: v1::OneHot") -xfail_issue_33593 = xfail_test(reason="Current implementation of MaxPool doesn't support indices output") -xfail_issue_55760 = xfail_test(reason="RuntimeError: Reversed axis have axes above the source space shape") # Model MSFT issues: xfail_issue_37957 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations: " @@ -114,9 +111,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): "/openvino/ngraph/src/ngraph/op/util/elementwise_args.cpp:48:") xfail_issue_39658 = xfail_test(reason="RuntimeError: Tile operation has a form that is not supported." " z should be converted to TileIE operation.") -xfail_issue_39659 = xfail_test(reason="RuntimeError: Broadcast operation has a form that is not supported." - " y should be converted to Tile operation.") -xfail_issue_45344 = xfail_test(reason="Unsupported dynamic ops: v3::NonMaxSuppressionIE3") xfail_issue_39662 = xfail_test(reason="RuntimeError: 'ScatterElementsUpdate' layer with name 'y' have " "indices value that points to non-existing output tensor element") @@ -145,7 +139,6 @@ def xfail_test(reason="Mark the test as expected to fail", strict=True): xfail_issue_63039 = xfail_test(reason="Result mismatches with UINT8 operations") xfail_issue_63043 = xfail_test(reason="Recurrent node expects constants as W, R, B inputs.") xfail_issue_63044 = xfail_test(reason="ONNX opset 14 operation: Trilu") -xfail_issue_63045 = xfail_test(reason="Maxpool with strides, padding and dilations fail") skip_rng_tests = pytest.mark.skip(reason="Tests use random number generator with no seed.") xfail_issue_63136 = xfail_test(reason="Unsupported operation: CastLike") diff --git a/runtime/bindings/python/tests_compatibility/test_ngraph/test_adaptive_pool.py b/runtime/bindings/python/tests_compatibility/test_ngraph/test_adaptive_pool.py deleted file mode 100644 index ba7fe7b28f3508..00000000000000 --- a/runtime/bindings/python/tests_compatibility/test_ngraph/test_adaptive_pool.py +++ /dev/null @@ -1,63 +0,0 @@ -import ngraph as ng -import numpy as np -from tests_compatibility.runtime import get_runtime - - -def test_adaptive_avg_pool(): - runtime = get_runtime() - input = np.reshape([0.0, 4, 1, 3, -2, -5, -2, - -2, 1, -3, 1, -3, -4, 0, - -2, 1, -1, -2, 3, -1, -3, - - -1, -2, 3, 4, -3, -4, 1, - 2, 0, -4, -5, -2, -2, -3, - 2, 3, 1, -5, 2, -4, -2], (2, 3, 7)) - input_tensor = ng.constant(input) - output_shape = ng.constant(np.array([3], dtype=np.int32)) - - adaptive_pool_node = ng.adaptive_avg_pool(input_tensor, output_shape) - computation = runtime.computation(adaptive_pool_node) - adaptive_pool_results = computation() - expected_results = np.reshape([1.66666663, 0.66666669, -3., - -1.33333337, -1.66666663, -2.33333325, - -0.66666669, 0., -0.33333334, - - 0., 1.33333337, -2., - -0.66666669, -3.66666675, -2.33333325, - 2., -0.66666669, -1.33333337], (2, 3, 3)) - - assert np.allclose(adaptive_pool_results, expected_results) - - -def test_adaptive_max_pool(): - runtime = get_runtime() - input = np.reshape([0, 4, 1, 3, -2, -5, -2, - -2, 1, -3, 1, -3, -4, 0, - -2, 1, -1, -2, 3, -1, -3, - - -1, -2, 3, 4, -3, -4, 1, - 2, 0, -4, -5, -2, -2, -3, - 2, 3, 1, -5, 2, -4, -2], (2, 3, 7)) - input_tensor = ng.constant(input) - output_shape = ng.constant(np.array([3], dtype=np.int32)) - - adaptive_pool_node = ng.adaptive_max_pool(input_tensor, output_shape) - computation = runtime.computation(adaptive_pool_node) - adaptive_pool_results = computation() - expected_results = np.reshape([4, 3, -2, - 1, 1, 0, - 1, 3, 3, - - 3, 4, 1, - 2, -2, -2, - 3, 2, 2], (2, 3, 3)) - - expected_indices = np.reshape([1, 3, 4, - 1, 3, 6, - 1, 4, 4, - - 2, 3, 6, - 0, 4, 4, - 1, 4, 4], (2, 3, 3)) - - assert np.allclose(adaptive_pool_results, [expected_results, expected_indices]) diff --git a/runtime/bindings/python/tests_compatibility/test_ngraph/test_create_op.py b/runtime/bindings/python/tests_compatibility/test_ngraph/test_create_op.py index 673d7a2ebf10b4..d8cc5d8a19e11c 100644 --- a/runtime/bindings/python/tests_compatibility/test_ngraph/test_create_op.py +++ b/runtime/bindings/python/tests_compatibility/test_ngraph/test_create_op.py @@ -3,7 +3,7 @@ import numpy as np import pytest -from _pyngraph import PartialShape, Dimension +from _pyngraph import PartialShape import ngraph as ng import ngraph.opset1 as ng_opset1 @@ -23,33 +23,6 @@ ] -@pytest.mark.parametrize("dtype", [np.float32, np.float64]) -def test_adaptive_avg_pool(dtype): - data = ng.parameter([2, 24, 34, 62], name="input", dtype=dtype) - output_shape = ng.constant(np.array([16, 16], dtype=np.int32)) - - node = ng.adaptive_avg_pool(data, output_shape) - - assert node.get_type_name() == "AdaptiveAvgPool" - assert node.get_output_size() == 1 - assert list(node.get_output_shape(0)) == [2, 24, 16, 16] - - -@pytest.mark.parametrize("dtype", [np.float32, np.float64]) -@pytest.mark.parametrize("ind_type", ["i32", "i64"]) -def test_adaptive_max_pool(dtype, ind_type): - data = ng.parameter([2, 24, 34, 62], name="input", dtype=dtype) - output_shape = ng.constant(np.array([16, 16], dtype=np.int32)) - - node = ng.adaptive_max_pool(data, output_shape, ind_type) - - assert node.get_type_name() == "AdaptiveMaxPool" - assert node.get_output_size() == 2 - assert list(node.get_output_shape(0)) == [2, 24, 16, 16] - assert list(node.get_output_shape(1)) == [2, 24, 16, 16] - assert node.get_output_element_type(1) == Type.i32 if ind_type == "i32" else Type.i64 - - @pytest.mark.parametrize("dtype", [np.float32, np.float64]) def test_binary_convolution(dtype): strides = np.array([1, 1]) @@ -67,7 +40,14 @@ def test_binary_convolution(dtype): parameter_input1 = ng.parameter(input1_shape, name="Input1", dtype=dtype) node = ng.binary_convolution( - parameter_input0, parameter_input1, strides, pads_begin, pads_end, dilations, mode, pad_value, + parameter_input0, + parameter_input1, + strides, + pads_begin, + pads_end, + dilations, + mode, + pad_value, ) assert node.get_type_name() == "BinaryConvolution" @@ -91,26 +71,30 @@ def test_ctc_greedy_decoder(dtype): assert list(node.get_output_shape(0)) == expected_shape -@pytest.mark.parametrize("fp_dtype, int_dtype, int_ci, int_sl, merge_repeated, blank_index", - [ - (np.float32, np.int32, "i32", "i32", True, True), - (np.float32, np.int32, "i64", "i32", True, True), - (np.float32, np.int32, "i32", "i64", True, True), - (np.float32, np.int32, "i64", "i64", True, True), - (np.float64, np.int64, "i32", "i32", False, True), - (np.float64, np.int64, "i64", "i32", False, True), - (np.float64, np.int64, "i32", "i64", False, True), - (np.float64, np.int64, "i64", "i64", False, True), - (np.float32, np.int32, "i32", "i32", True, False), - (np.float32, np.int32, "i64", "i32", True, False), - (np.float32, np.int32, "i32", "i64", True, False), - (np.float32, np.int32, "i64", "i64", True, False), - (np.float64, np.int64, "i32", "i32", False, False), - (np.float64, np.int64, "i64", "i32", False, False), - (np.float64, np.int64, "i32", "i64", False, False), - (np.float64, np.int64, "i64", "i64", False, False) - ],) -def test_ctc_greedy_decoder_seq_len(fp_dtype, int_dtype, int_ci, int_sl, merge_repeated, blank_index): +@pytest.mark.parametrize( + "fp_dtype, int_dtype, int_ci, int_sl, merge_repeated, blank_index", + [ + (np.float32, np.int32, "i32", "i32", True, True), + (np.float32, np.int32, "i64", "i32", True, True), + (np.float32, np.int32, "i32", "i64", True, True), + (np.float32, np.int32, "i64", "i64", True, True), + (np.float64, np.int64, "i32", "i32", False, True), + (np.float64, np.int64, "i64", "i32", False, True), + (np.float64, np.int64, "i32", "i64", False, True), + (np.float64, np.int64, "i64", "i64", False, True), + (np.float32, np.int32, "i32", "i32", True, False), + (np.float32, np.int32, "i64", "i32", True, False), + (np.float32, np.int32, "i32", "i64", True, False), + (np.float32, np.int32, "i64", "i64", True, False), + (np.float64, np.int64, "i32", "i32", False, False), + (np.float64, np.int64, "i64", "i32", False, False), + (np.float64, np.int64, "i32", "i64", False, False), + (np.float64, np.int64, "i64", "i64", False, False), + ], +) +def test_ctc_greedy_decoder_seq_len( + fp_dtype, int_dtype, int_ci, int_sl, merge_repeated, blank_index +): input0_shape = [8, 20, 128] input1_shape = [8] input2_shape = [1] @@ -123,7 +107,12 @@ def test_ctc_greedy_decoder_seq_len(fp_dtype, int_dtype, int_ci, int_sl, merge_r parameter_input2 = ng.parameter(input2_shape, name="Input2", dtype=int_dtype) node = ng.ctc_greedy_decoder_seq_len( - parameter_input0, parameter_input1, parameter_input2, merge_repeated, int_ci, int_sl + parameter_input0, + parameter_input1, + parameter_input2, + merge_repeated, + int_ci, + int_sl, ) assert node.get_type_name() == "CTCGreedyDecoderSeqLen" @@ -148,7 +137,13 @@ def test_deformable_convolution_opset1(dtype): parameter_input2 = ng.parameter(input2_shape, name="Input2", dtype=dtype) node = ng_opset1.deformable_convolution( - parameter_input0, parameter_input1, parameter_input2, strides, pads_begin, pads_end, dilations, + parameter_input0, + parameter_input1, + parameter_input2, + strides, + pads_begin, + pads_end, + dilations, ) assert node.get_type_name() == "DeformableConvolution" @@ -173,35 +168,13 @@ def test_deformable_convolution(dtype): parameter_input2 = ng.parameter(input2_shape, name="Input2", dtype=dtype) node = ng.deformable_convolution( - parameter_input0, parameter_input1, parameter_input2, strides, pads_begin, pads_end, dilations, - ) - - assert node.get_type_name() == "DeformableConvolution" - assert node.get_output_size() == 1 - assert list(node.get_output_shape(0)) == expected_shape - - -@pytest.mark.parametrize("dtype", np_types) -def test_deformable_convolution_mask(dtype): - strides = np.array([1, 1]) - pads_begin = np.array([0, 0]) - pads_end = np.array([0, 0]) - dilations = np.array([1, 1]) - - input0_shape = [1, 1, 9, 9] - input1_shape = [1, 18, 7, 7] - input2_shape = [1, 1, 3, 3] - input3_shape = [1, 9, 7, 7] - expected_shape = [1, 1, 7, 7] - - parameter_input0 = ng.parameter(input0_shape, name="Input0", dtype=dtype) - parameter_input1 = ng.parameter(input1_shape, name="Input1", dtype=dtype) - parameter_input2 = ng.parameter(input2_shape, name="Input2", dtype=dtype) - parameter_input3 = ng.parameter(input3_shape, name="Input3", dtype=dtype) - - node = ng.deformable_convolution( - parameter_input0, parameter_input1, parameter_input2, strides, - pads_begin, pads_end, dilations, parameter_input3 + parameter_input0, + parameter_input1, + parameter_input2, + strides, + pads_begin, + pads_end, + dilations, ) assert node.get_type_name() == "DeformableConvolution" @@ -277,7 +250,9 @@ def test_gather_tree(dtype): parameter_input2 = ng.parameter(input2_shape, name="Input2", dtype=dtype) parameter_input3 = ng.parameter(input3_shape, name="Input3", dtype=dtype) - node = ng.gather_tree(parameter_input0, parameter_input1, parameter_input2, parameter_input3) + node = ng.gather_tree( + parameter_input0, parameter_input1, parameter_input2, parameter_input3 + ) assert node.get_type_name() == "GatherTree" assert node.get_output_size() == 1 @@ -307,7 +282,13 @@ def test_lstm_cell_operator(dtype): expected_shape = [1, 128] node_default = ng.lstm_cell( - parameter_X, parameter_H_t, parameter_C_t, parameter_W, parameter_R, parameter_B, hidden_size, + parameter_X, + parameter_H_t, + parameter_C_t, + parameter_W, + parameter_R, + parameter_B, + hidden_size, ) assert node_default.get_type_name() == "LSTMCell" @@ -363,7 +344,13 @@ def test_lstm_cell_operator_opset1(dtype): expected_shape = [1, 128] node_default = ng_opset1.lstm_cell( - parameter_X, parameter_H_t, parameter_C_t, parameter_W, parameter_R, parameter_B, hidden_size, + parameter_X, + parameter_H_t, + parameter_C_t, + parameter_W, + parameter_R, + parameter_B, + hidden_size, ) assert node_default.get_type_name() == "LSTMCell" @@ -612,7 +599,9 @@ def test_gru_cell_operator(): expected_shape = [1, 128] - node_default = ng.gru_cell(parameter_X, parameter_H_t, parameter_W, parameter_R, parameter_B, hidden_size) + node_default = ng.gru_cell( + parameter_X, parameter_H_t, parameter_W, parameter_R, parameter_B, hidden_size + ) assert node_default.get_type_name() == "GRUCell" assert node_default.get_output_size() == 1 @@ -820,8 +809,10 @@ def test_loop(): ti_inputs = [iter_cnt, data, initial_cma, one] body_const_condition = ng.constant(True, dtype=np.bool) - graph_body = GraphBody([body_timestep, body_data_in, body_prev_cma, body_const_one], - [curr_cma, cma_hist, body_const_condition]) + graph_body = GraphBody( + [body_timestep, body_data_in, body_prev_cma, body_const_one], + [curr_cma, cma_hist, body_const_condition], + ) ti_slice_input_desc = [ # timestep # input_idx, body_param_idx, start, stride, part_size, end, axis @@ -926,7 +917,9 @@ def test_region_yolo(): end_axis = 3 do_softmax = False - node = ng.region_yolo(data, num_coords, num_classes, num_regions, do_softmax, mask, axis, end_axis) + node = ng.region_yolo( + data, num_coords, num_classes, num_regions, do_softmax, mask, axis, end_axis + ) assert node.get_type_name() == "RegionYolo" assert node.get_output_size() == 1 @@ -996,7 +989,9 @@ def test_embedding_segments_sum_with_some_opt_inputs(): def test_embedding_bag_packed_sum(): emb_table = ng.parameter([5, 2], name="emb_table", dtype=np.float32) indices = ng.parameter([3, 3], name="indices", dtype=np.int64) - per_sample_weights = ng.parameter([3, 3], name="per_sample_weights", dtype=np.float32) + per_sample_weights = ng.parameter( + [3, 3], name="per_sample_weights", dtype=np.float32 + ) # only 1 out of 3 optional inputs node = ng.embedding_bag_packed_sum(emb_table, indices, per_sample_weights) @@ -1048,7 +1043,7 @@ def test_prior_box(int_dtype, fp_dtype): "offset": fp_dtype(0), "min_size": np.array([2, 3], dtype=fp_dtype), "aspect_ratio": np.array([1.5, 2.0, 2.5], dtype=fp_dtype), - "scale_all_sizes": False + "scale_all_sizes": False, } layer_shape = ng.constant(np.array([32, 32], dtype=int_dtype), int_dtype) @@ -1120,7 +1115,9 @@ def test_detection_output(int_dtype, fp_dtype): aux_class_preds = ng.parameter([4, 4], fp_dtype, "aux_class_preds") aux_box_preds = ng.parameter([4, 8], fp_dtype, "aux_box_preds") - node = ng.detection_output(box_logits, class_preds, proposals, attributes, aux_class_preds, aux_box_preds) + node = ng.detection_output( + box_logits, class_preds, proposals, attributes, aux_class_preds, aux_box_preds + ) assert node.get_type_name() == "DetectionOutput" assert node.get_output_size() == 1 @@ -1158,7 +1155,10 @@ def test_proposal(int_dtype, fp_dtype): assert node.get_type_name() == "Proposal" assert node.get_output_size() == 2 - assert list(node.get_output_shape(0)) == [batch_size * attributes["post_nms_topn"], 5] + assert list(node.get_output_shape(0)) == [ + batch_size * attributes["post_nms_topn"], + 5, + ] def test_tensor_iterator(): @@ -1193,7 +1193,10 @@ def test_tensor_iterator(): iter_cnt = ng.range(zero, np.int32(16), np.int32(1)) ti_inputs = [iter_cnt, data, initial_cma, one] - graph_body = GraphBody([body_timestep, body_data_in, body_prev_cma, body_const_one], [curr_cma, cma_hist]) + graph_body = GraphBody( + [body_timestep, body_data_in, body_prev_cma, body_const_one], + [curr_cma, cma_hist], + ) ti_slice_input_desc = [ # timestep # input_idx, body_param_idx, start, stride, part_size, end, axis @@ -1551,7 +1554,7 @@ def test_gru_sequence_operator_bidirectional(dtype): activation_alpha, activation_beta, clip, - linear_before_reset + linear_before_reset, ) assert node_param.get_type_name() == "GRUSequence" @@ -1617,7 +1620,7 @@ def test_gru_sequence_operator_reverse(dtype): activation_alpha, activation_beta, clip, - linear_before_reset + linear_before_reset, ) assert node_param.get_type_name() == "GRUSequence" @@ -1683,7 +1686,7 @@ def test_gru_sequence_operator_forward(dtype): activation_alpha, activation_beta, clip, - linear_before_reset + linear_before_reset, ) assert node.get_type_name() == "GRUSequence" @@ -1873,53 +1876,3 @@ def test_rnn_sequence_operator_forward(dtype): assert node.get_type_name() == "RNNSequence" assert node.get_output_size() == 2 - - -def test_multiclass_nms(): - boxes_data = np.array([0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, - 0.0, -0.1, 1.0, 0.9, 0.0, 10.0, 1.0, 11.0, - 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0], dtype="float32") - boxes_data = boxes_data.reshape([1, 6, 4]) - box = ng.constant(boxes_data, dtype=np.float) - scores_data = np.array([0.9, 0.75, 0.6, 0.95, 0.5, 0.3, - 0.95, 0.75, 0.6, 0.80, 0.5, 0.3], dtype="float32") - scores_data = scores_data.reshape([1, 2, 6]) - score = ng.constant(scores_data, dtype=np.float) - - nms_node = ng.multiclass_nms(box, score, output_type="i32", nms_top_k=3, - iou_threshold=0.5, score_threshold=0.0, sort_result_type="classid", - nms_eta=1.0) - - assert nms_node.get_type_name() == "MulticlassNms" - assert nms_node.get_output_size() == 3 - assert nms_node.outputs()[0].get_partial_shape() == PartialShape([Dimension(0, 6), Dimension(6)]) - assert nms_node.outputs()[1].get_partial_shape() == PartialShape([Dimension(0, 6), Dimension(1)]) - assert list(nms_node.outputs()[2].get_shape()) == [1, ] - assert nms_node.get_output_element_type(0) == Type.f32 - assert nms_node.get_output_element_type(1) == Type.i32 - assert nms_node.get_output_element_type(2) == Type.i32 - - -def test_matrix_nms(): - boxes_data = np.array([0.0, 0.0, 1.0, 1.0, 0.0, 0.1, 1.0, 1.1, - 0.0, -0.1, 1.0, 0.9, 0.0, 10.0, 1.0, 11.0, - 0.0, 10.1, 1.0, 11.1, 0.0, 100.0, 1.0, 101.0], dtype="float32") - boxes_data = boxes_data.reshape([1, 6, 4]) - box = ng.constant(boxes_data, dtype=np.float) - scores_data = np.array([0.9, 0.75, 0.6, 0.95, 0.5, 0.3, - 0.95, 0.75, 0.6, 0.80, 0.5, 0.3], dtype="float32") - scores_data = scores_data.reshape([1, 2, 6]) - score = ng.constant(scores_data, dtype=np.float) - - nms_node = ng.matrix_nms(box, score, output_type="i32", nms_top_k=3, - score_threshold=0.0, sort_result_type="score", background_class=0, - decay_function="linear", gaussian_sigma=2.0, post_threshold=0.0) - - assert nms_node.get_type_name() == "MatrixNms" - assert nms_node.get_output_size() == 3 - assert nms_node.outputs()[0].get_partial_shape() == PartialShape([Dimension(0, 6), Dimension(6)]) - assert nms_node.outputs()[1].get_partial_shape() == PartialShape([Dimension(0, 6), Dimension(1)]) - assert list(nms_node.outputs()[2].get_shape()) == [1, ] - assert nms_node.get_output_element_type(0) == Type.f32 - assert nms_node.get_output_element_type(1) == Type.i32 - assert nms_node.get_output_element_type(2) == Type.i32 diff --git a/runtime/bindings/python/tests_compatibility/test_ngraph/test_pooling.py b/runtime/bindings/python/tests_compatibility/test_ngraph/test_pooling.py index 423c519272b4ed..38f4fded429986 100644 --- a/runtime/bindings/python/tests_compatibility/test_ngraph/test_pooling.py +++ b/runtime/bindings/python/tests_compatibility/test_ngraph/test_pooling.py @@ -26,14 +26,18 @@ def test_avg_pool_2d(_ndarray_1x1x4x4): exclude_pad = True expected = [[[[13.5, 15.5], [21.5, 23.5]]]] - avg_pool_node = ng.avg_pool(param, strides, pads_begin, pads_end, kernel_shape, exclude_pad) + avg_pool_node = ng.avg_pool( + param, strides, pads_begin, pads_end, kernel_shape, exclude_pad + ) computation = runtime.computation(avg_pool_node, param) result = computation(input_data) assert np.allclose(result, expected) expected = [[[[13.5, 14.5, 15.5], [17.5, 18.5, 19.5], [21.5, 22.5, 23.5]]]] strides = [1, 1] - avg_pool_node = ng.avg_pool(param, strides, pads_begin, pads_end, kernel_shape, exclude_pad) + avg_pool_node = ng.avg_pool( + param, strides, pads_begin, pads_end, kernel_shape, exclude_pad + ) computation = runtime.computation(avg_pool_node, param) result = computation(input_data) assert np.allclose(result, expected) @@ -44,14 +48,18 @@ def test_avg_pool_2d(_ndarray_1x1x4x4): exclude_pad = True expected = [[[[11.0, 12.5, 14.0], [17.0, 18.5, 20.0], [23.0, 24.5, 26.0]]]] - avg_pool_node = ng.avg_pool(param, strides, pads_begin, pads_end, kernel_shape, exclude_pad) + avg_pool_node = ng.avg_pool( + param, strides, pads_begin, pads_end, kernel_shape, exclude_pad + ) computation = runtime.computation(avg_pool_node, param) result = computation(input_data) assert np.allclose(result, expected) exclude_pad = False expected = [[[[2.75, 6.25, 3.5], [8.5, 18.5, 10.0], [5.75, 12.25, 6.5]]]] - avg_pool_node = ng.avg_pool(param, strides, pads_begin, pads_end, kernel_shape, exclude_pad) + avg_pool_node = ng.avg_pool( + param, strides, pads_begin, pads_end, kernel_shape, exclude_pad + ) computation = runtime.computation(avg_pool_node, param) result = computation(input_data) assert np.allclose(result, expected) @@ -69,7 +77,9 @@ def test_avg_pooling_3d(_ndarray_1x1x4x4): pads_end = [0] * spatial_dim_count exclude_pad = True - avgpool = ng.avg_pool(param, strides, pads_begin, pads_end, kernel_shape, exclude_pad) + avgpool = ng.avg_pool( + param, strides, pads_begin, pads_end, kernel_shape, exclude_pad + ) comp = rt.computation(avgpool, param) result = comp(data) result_ref = [[[[[13.5, 15.5], [21.5, 23.5]], [[13.5, 15.5], [21.5, 23.5]]]]] @@ -85,35 +95,20 @@ def test_max_pool_basic(): # [12.5, 13.5, 14.5, 15.5]]]], dtype=float32) data = np.arange(0.5, 16, dtype=np.float32).reshape((1, 1, 4, 4)) strides = [1, 1] - dilations = [1, 1] pads_begin = [0, 0] pads_end = [0, 0] kernel_shape = [2, 2] - rounding_type = "floor" - auto_pad = None - index_et = "i32" data_node = ng.parameter(data.shape, name="A", dtype=np.float32) - maxpool_node = ng.max_pool( - data_node, - strides, - dilations, - pads_begin, - pads_end, - kernel_shape, - rounding_type, - auto_pad, - index_et, - ) + maxpool_node = ng.max_pool(data_node, strides, pads_begin, pads_end, kernel_shape) comp = rt.computation(maxpool_node, data_node) + result = comp(data) expected = np.array( [[[[5.5, 6.5, 7.5], [9.5, 10.5, 11.5], [13.5, 14.5, 15.5]]]], dtype=np.float32 ) - expected_idx = np.array([[[[5, 6, 7], [9, 10, 11], [13, 14, 15]]]], dtype=np.int32) - assert np.allclose(result[0], expected) - assert np.allclose(result[1], expected_idx) + assert np.allclose(result, expected) def test_max_pool_strides(): @@ -125,33 +120,17 @@ def test_max_pool_strides(): # [12.5, 13.5, 14.5, 15.5]]]], dtype=float32) data = np.arange(0.5, 16, dtype=np.float32).reshape((1, 1, 4, 4)) strides = [2, 1] - dilations = [1, 1] pads_begin = [0, 0] pads_end = [0, 0] kernel_shape = [2, 2] - rounding_type = "floor" - auto_pad = None - index_et = "i32" data_node = ng.parameter(data.shape, name="A", dtype=np.float32) - maxpool_node = ng.max_pool( - data_node, - strides, - dilations, - pads_begin, - pads_end, - kernel_shape, - rounding_type, - auto_pad, - index_et, - ) + maxpool_node = ng.max_pool(data_node, strides, pads_begin, pads_end, kernel_shape) comp = rt.computation(maxpool_node, data_node) result = comp(data) expected = np.array([[[[5.5, 6.5, 7.5], [13.5, 14.5, 15.5]]]], dtype=np.float32) - expected_idx = np.array([[[[5, 6, 7], [13, 14, 15]]]], dtype=np.int32) - assert np.allclose(result[0], expected) - assert np.allclose(result[1], expected_idx) + assert np.allclose(result, expected) def test_max_pool_kernel_shape1x1(): @@ -163,31 +142,16 @@ def test_max_pool_kernel_shape1x1(): # [12.5, 13.5, 14.5, 15.5]]]], dtype=float32) data = np.arange(0.5, 16, dtype=np.float32).reshape((1, 1, 4, 4)) strides = [1, 1] - dilations = [1, 1] pads_begin = [0, 0] pads_end = [0, 0] kernel_shape = [1, 1] - rounding_type = "floor" - auto_pad = None - index_et = "i32" data_node = ng.parameter(data.shape, name="A", dtype=np.float32) - maxpool_node = ng.max_pool( - data_node, - strides, - dilations, - pads_begin, - pads_end, - kernel_shape, - rounding_type, - auto_pad, - index_et, - ) + maxpool_node = ng.max_pool(data_node, strides, pads_begin, pads_end, kernel_shape) comp = rt.computation(maxpool_node, data_node) result = comp(data) - assert np.allclose(result[0], data) - assert np.allclose(result[1], np.arange(0, 16, dtype=np.int32).reshape((1, 1, 4, 4))) + assert np.allclose(result, data) def test_max_pool_kernel_shape3x3(): @@ -199,31 +163,17 @@ def test_max_pool_kernel_shape3x3(): # [12.5, 13.5, 14.5, 15.5]]]], dtype=float32) data = np.arange(0.5, 16, dtype=np.float32).reshape((1, 1, 4, 4)) strides = [1, 1] - dilations = [1, 1] pads_begin = [0, 0] pads_end = [0, 0] kernel_shape = [3, 3] - rounding_type = "floor" - auto_pad = None - index_et = "i32" data_node = ng.parameter(data.shape, name="A", dtype=np.float32) - maxpool_node = ng.max_pool( - data_node, - strides, - dilations, - pads_begin, - pads_end, - kernel_shape, - rounding_type, - auto_pad, - index_et, - ) + maxpool_node = ng.max_pool(data_node, strides, pads_begin, pads_end, kernel_shape) comp = rt.computation(maxpool_node, data_node) result = comp(data) expected = np.array([[[[10.5, 11.5], [14.5, 15.5]]]], dtype=np.float32) - assert np.allclose(result[0], expected) + assert np.allclose(result, expected) def test_max_pool_non_zero_pads(): @@ -235,7 +185,6 @@ def test_max_pool_non_zero_pads(): # [12.5, 13.5, 14.5, 15.5]]]], dtype=float32) data = np.arange(0.5, 16, dtype=np.float32).reshape((1, 1, 4, 4)) strides = [1, 1] - dilations = [1, 1] pads_begin = [1, 1] pads_end = [1, 1] # 0 0 , 0 , 0 , 0, 0 @@ -245,22 +194,9 @@ def test_max_pool_non_zero_pads(): # 0 [12.5, 13.5, 14.5, 15.5], 0 # 0 0 , 0 , 0 , 0, 0 kernel_shape = [2, 2] - rounding_type = "floor" - auto_pad = None - index_et = "i32" data_node = ng.parameter(data.shape, name="A", dtype=np.float32) - maxpool_node = ng.max_pool( - data_node, - strides, - dilations, - pads_begin, - pads_end, - kernel_shape, - rounding_type, - auto_pad, - index_et, - ) + maxpool_node = ng.max_pool(data_node, strides, pads_begin, pads_end, kernel_shape) comp = rt.computation(maxpool_node, data_node) result = comp(data) @@ -278,22 +214,7 @@ def test_max_pool_non_zero_pads(): ], dtype=np.float32, ) - expected_idx = np.array( - [ - [ - [ - [0, 1, 2, 3, 3], - [4, 5, 6, 7, 7], - [8, 9, 10, 11, 11], - [12, 13, 14, 15, 15], - [12, 13, 14, 15, 15], - ] - ] - ], - dtype=np.int32, - ) - assert np.allclose(result[0], expected) - assert np.allclose(result[1], expected_idx) + assert np.allclose(result, expected) def test_max_pool_same_upper_auto_pads(): @@ -305,7 +226,6 @@ def test_max_pool_same_upper_auto_pads(): # [12.5, 13.5, 14.5, 15.5]]]], dtype=float32) data = np.arange(0.5, 16, dtype=np.float32).reshape((1, 1, 4, 4)) strides = [1, 1] - dilations = [1, 1] pads_begin = [0, 0] pads_end = [0, 0] # [ 0.5, 1.5, 2.5, 3.5], 0, @@ -315,20 +235,10 @@ def test_max_pool_same_upper_auto_pads(): # 0 , 0 , 0 , 0, 0 kernel_shape = [2, 2] auto_pad = "same_upper" - rounding_type = "floor" - index_et = "i32" data_node = ng.parameter(data.shape, name="A", dtype=np.float32) maxpool_node = ng.max_pool( - data_node, - strides, - dilations, - pads_begin, - pads_end, - kernel_shape, - rounding_type, - auto_pad, - index_et, + data_node, strides, pads_begin, pads_end, kernel_shape, auto_pad=auto_pad ) comp = rt.computation(maxpool_node, data_node) result = comp(data) @@ -346,21 +256,7 @@ def test_max_pool_same_upper_auto_pads(): ], dtype=np.float32, ) - expected_idx = np.array( - [ - [ - [ - [5, 6, 7, 7], - [9, 10, 11, 11], - [13, 14, 15, 15], - [13, 14, 15, 15], - ] - ] - ], - dtype=np.int32, - ) - assert np.allclose(result[0], expected) - assert np.allclose(result[1], expected_idx) + assert np.allclose(result, expected) def test_max_pool_same_lower_auto_pads(): @@ -372,7 +268,6 @@ def test_max_pool_same_lower_auto_pads(): # [12.5, 13.5, 14.5, 15.5]]]], dtype=float32) data = np.arange(0.5, 16, dtype=np.float32).reshape((1, 1, 4, 4)) strides = [1, 1] - dilations = [1, 1] pads_begin = [0, 0] pads_end = [0, 0] # 0 0 , 0 , 0 , 0, @@ -382,20 +277,10 @@ def test_max_pool_same_lower_auto_pads(): # 0 [12.5, 13.5, 14.5, 15.5], kernel_shape = [2, 2] auto_pad = "same_lower" - rounding_type = "floor" - index_et = "i32" data_node = ng.parameter(data.shape, name="A", dtype=np.float32) maxpool_node = ng.max_pool( - data_node, - strides, - dilations, - pads_begin, - pads_end, - kernel_shape, - rounding_type, - auto_pad, - index_et, + data_node, strides, pads_begin, pads_end, kernel_shape, auto_pad=auto_pad ) comp = rt.computation(maxpool_node, data_node) result = comp(data) @@ -413,18 +298,4 @@ def test_max_pool_same_lower_auto_pads(): ], dtype=np.float32, ) - expected_idx = np.array( - [ - [ - [ - [0, 1, 2, 3], - [4, 5, 6, 7], - [8, 9, 10, 11], - [12, 13, 14, 15], - ] - ] - ], - dtype=np.int32, - ) - assert np.allclose(result[0], expected) - assert np.allclose(result[1], expected_idx) + assert np.allclose(result, expected) diff --git a/runtime/bindings/python/tests_compatibility/test_ngraph/test_random_uniform.py b/runtime/bindings/python/tests_compatibility/test_ngraph/test_random_uniform.py deleted file mode 100644 index c82654c7167f07..00000000000000 --- a/runtime/bindings/python/tests_compatibility/test_ngraph/test_random_uniform.py +++ /dev/null @@ -1,27 +0,0 @@ -import ngraph as ng -import numpy as np -from tests_compatibility.runtime import get_runtime - - -def test_random_uniform(): - runtime = get_runtime() - input_tensor = ng.constant(np.array([2, 4, 3], dtype=np.int32)) - min_val = ng.constant(np.array([-2.7], dtype=np.float32)) - max_val = ng.constant(np.array([3.5], dtype=np.float32)) - - random_uniform_node = ng.random_uniform(input_tensor, min_val, max_val, - output_type="f32", global_seed=7461, - op_seed=1546) - computation = runtime.computation(random_uniform_node) - random_uniform_results = computation() - expected_results = np.array([[[2.8450181, -2.3457108, 2.2134445], - [-1.0436587, 0.79548645, 1.3023183], - [0.34447956, -2.0267959, 1.3989122], - [0.9607613, 1.5363653, 3.117298]], - - [[1.570041, 2.2782724, 2.3193843], - [3.3393657, 0.63299894, 0.41231918], - [3.1739233, 0.03919673, -0.2136085], - [-1.4519991, -2.277353, 2.630727]]], dtype=np.float32) - - assert np.allclose(random_uniform_results, expected_results) diff --git a/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py b/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py index ec31562e71909b..ed3b1647e0ed73 100644 --- a/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py +++ b/runtime/bindings/python/tests_compatibility/test_onnx/test_backend.py @@ -11,11 +11,9 @@ xfail_issue_33538, xfail_issue_33581, xfail_issue_33589, - xfail_issue_33593, xfail_issue_33595, xfail_issue_33596, xfail_issue_33606, - xfail_issue_33633, xfail_issue_33651, xfail_issue_38091, xfail_issue_38699, @@ -28,7 +26,6 @@ xfail_issue_38734, xfail_issue_38735, xfail_issue_39658, - xfail_issue_39659, xfail_issue_39662, xfail_issue_44854, xfail_issue_44858, @@ -36,25 +33,22 @@ xfail_issue_44965, xfail_issue_44968, xfail_issue_45180, - xfail_issue_45344, xfail_issue_47323, xfail_issue_47337, xfail_issue_48052, xfail_issue_49207, xfail_issue_49750, xfail_issue_52463, - xfail_issue_55760, xfail_issue_58033, xfail_issue_63033, xfail_issue_63036, xfail_issue_63039, xfail_issue_63043, xfail_issue_63044, - xfail_issue_63045, xfail_issue_63136, xfail_issue_63137, xfail_issue_63138, - skip_issue_69443, + xfail_issue_69443, xfail_issue_69444, ) from tests_compatibility.test_onnx.utils.onnx_backend import OpenVinoTestBackend @@ -119,7 +113,7 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_lstm_with_peepholes_cpu", ), ( - skip_issue_69443, + xfail_issue_69443, "OnnxBackendNodeModelTest.test_constant_pad_cpu", "OnnxBackendNodeModelTest.test_edge_pad_cpu", "OnnxBackendNodeModelTest.test_reflect_pad_cpu", @@ -129,36 +123,11 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_tile_cpu", "OnnxBackendNodeModelTest.test_tile_precomputed_cpu", ), - ( - xfail_issue_39659, - "OnnxBackendNodeModelTest.test_constantofshape_int_shape_zero_cpu", - ), - ( - xfail_issue_45344, - "OnnxBackendNodeModelTest.test_nonmaxsuppression_center_point_box_format_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_flipped_coordinates_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_identical_boxes_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_limit_output_size_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_single_box_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_and_scores_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_suppress_by_IOU_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_batches_cpu", - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu", - ), ( xfail_issue_39662, - "OnnxBackendNodeModelTest.test_nonmaxsuppression_two_classes_cpu", "OnnxBackendNodeModelTest.test_scatter_elements_with_negative_indices_cpu", "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu", ), - (xfail_issue_33633, "OnnxBackendNodeModelTest.test_maxpool_2d_dilations_cpu"), - ( - xfail_issue_55760, - "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_example_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_example_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmax_negative_axis_keepdims_random_select_last_index_cpu", - "OnnxBackendNodeModelTest.test_argmin_negative_axis_keepdims_random_select_last_index_cpu", - ), ( xfail_issue_38091, "OnnxBackendNodeModelTest.test_gather_negative_indices_cpu", @@ -253,15 +222,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_align_corners_cpu", "OnnxBackendNodeModelTest.test_resize_downsample_scales_cubic_A_n0p5_exclude_outside_cpu", "OnnxBackendNodeModelTest.test_resize_upsample_scales_cubic_A_n0p5_exclude_outside_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_round_prefer_ceil_asymmetric_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_floor_align_corners_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_nearest_ceil_half_pixel_cpu", - "OnnxBackendNodeModelTest.test_resize_upsample_sizes_cubic_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_linear_pytorch_half_pixel_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_cpu", - "OnnxBackendNodeModelTest.test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn_cpu", ), ( xfail_issue_33581, @@ -355,11 +315,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_squeeze_cpu", "OnnxBackendNodeModelTest.test_squeeze_negative_axes_cpu", ), - ( - xfail_issue_33593, - "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_strides_cpu", - "OnnxBackendNodeModelTest.test_maxpool_with_argmax_2d_precomputed_pads_cpu", - ), (xfail_issue_58033, "OnnxBackendNodeModelTest.test_einsum_batch_diagonal_cpu"), ( xfail_issue_63033, @@ -404,11 +359,6 @@ def expect_fail(test_case_path, xfail): # type: (str) -> None "OnnxBackendNodeModelTest.test_triu_square_neg_cpu", "OnnxBackendNodeModelTest.test_triu_zero_cpu", ), - ( - xfail_issue_63045, - "OnnxBackendPyTorchConvertedModelTest.test_MaxPool1d_stride_padding_dilation_cpu", - "OnnxBackendPyTorchConvertedModelTest.test_MaxPool2d_stride_padding_dilation_cpu", - ), ( skip_rng_tests, "OnnxBackendNodeModelTest.test_bernoulli_cpu", diff --git a/samples/c/common/opencv_c_wrapper/CMakeLists.txt b/samples/c/common/opencv_c_wrapper/CMakeLists.txt index 45b2b3e9ed0025..9550b217edf594 100644 --- a/samples/c/common/opencv_c_wrapper/CMakeLists.txt +++ b/samples/c/common/opencv_c_wrapper/CMakeLists.txt @@ -28,3 +28,9 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER c_samples) if(COMMAND add_clang_format_target AND NOT IE_SAMPLE_EXCLUDE_CLANG_FORMAT) add_clang_format_target(${TARGET_NAME}_clang FOR_TARGETS ${TARGET_NAME}) endif() + +install( + TARGETS ${TARGET_NAME} + RUNTIME DESTINATION samples_bin/ COMPONENT samples_bin EXCLUDE_FROM_ALL + LIBRARY DESTINATION samples_bin/ COMPONENT samples_bin EXCLUDE_FROM_ALL +) diff --git a/samples/c/hello_classification/main.c b/samples/c/hello_classification/main.c index b4c3f4ed79c921..1f2831fa918612 100644 --- a/samples/c/hello_classification/main.c +++ b/samples/c/hello_classification/main.c @@ -122,15 +122,19 @@ int main(int argc, char** argv) { // ------------------------------------- IEStatusCode status = ie_core_create("", &core); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_create status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // Step 2. Read a model in OpenVINO Intermediate Representation (.xml and .bin // files) or ONNX (.onnx file) format status = ie_core_read_network(core, input_model, NULL, &network); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_read_network status %d, line %d\n", status, __LINE__); goto err; + } // check the network topology status = ie_network_get_inputs_number(network, &network_input_size); if (status != OK || network_input_size != 1) { @@ -140,7 +144,7 @@ int main(int argc, char** argv) { status = ie_network_get_outputs_number(network, &network_output_size); if (status != OK || network_output_size != 1) { - printf("Sample supports topologies with 1 output only\n"); + fprintf(stderr, "Sample supports topologies with 1 output only\n"); goto err; } // ----------------------------------------------------------------------------------------------------- @@ -151,8 +155,10 @@ int main(int argc, char** argv) { // ----------------------------------------------------- status = ie_network_get_input_name(network, 0, &input_name); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_get_input_name status %d, line %d\n", status, __LINE__); goto err; + } /* Mark input as resizable by setting of a resize algorithm. * In this case we will be able to set an input blob of any shape to an infer * request. Resize and layout conversions are executed automatically during @@ -160,15 +166,19 @@ int main(int argc, char** argv) { status |= ie_network_set_input_resize_algorithm(network, input_name, RESIZE_BILINEAR); status |= ie_network_set_input_layout(network, input_name, NHWC); status |= ie_network_set_input_precision(network, input_name, U8); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_set_input_* status %d, line %d\n", status, __LINE__); goto err; + } // --------------------------- Prepare output blobs // ---------------------------------------------------- status |= ie_network_get_output_name(network, 0, &output_name); status |= ie_network_set_output_precision(network, output_name, FP32); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_get_output_* status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- @@ -176,15 +186,19 @@ int main(int argc, char** argv) { // ------------------------------------------ ie_config_t config = {NULL, NULL, NULL}; status = ie_core_load_network(core, network, device_name, &config, &exe_network); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_load_network status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 5. Create infer request // ------------------------------------------------- status = ie_exec_network_create_infer_request(exe_network, &infer_request); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_exec_network_create_infer_request status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 6. Prepare input @@ -201,28 +215,34 @@ int main(int argc, char** argv) { // memory status = ie_blob_make_memory_from_preallocated(&tensorDesc, img.mat_data, size, &imgBlob); if (status != OK) { + fprintf(stderr, "ERROR ie_blob_make_memory_from_preallocated status %d, line %d\n", status, __LINE__); image_free(&img); goto err; } // infer_request accepts input blob of any size status = ie_infer_request_set_blob(infer_request, input_name, imgBlob); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_set_blob status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 7. Do inference // -------------------------------------------------------- /* Running the request synchronously */ status = ie_infer_request_infer(infer_request); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_infer status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 8. Process output // ------------------------------------------------------ status = ie_infer_request_get_blob(infer_request, output_name, &output_blob); if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_get_blob status %d, line %d\n", status, __LINE__); image_free(&img); goto err; } diff --git a/samples/c/hello_nv12_input_classification/main.c b/samples/c/hello_nv12_input_classification/main.c index 9effcdef06a97a..02715bb0709486 100644 --- a/samples/c/hello_nv12_input_classification/main.c +++ b/samples/c/hello_nv12_input_classification/main.c @@ -178,8 +178,10 @@ int main(int argc, char** argv) { } size_t input_width = 0, input_height = 0, img_size = 0; - if (!is_supported_image_size(argv[3], &input_width, &input_height)) + if (!is_supported_image_size(argv[3], &input_width, &input_height)) { + fprintf(stderr, "ERROR is_supported_image_size, line %d\n", __LINE__); return EXIT_FAILURE; + } const char* input_model = argv[1]; const char* input_image_path = argv[2]; @@ -196,15 +198,19 @@ int main(int argc, char** argv) { // --------------------------- Step 1. Initialize inference engine core // ------------------------------------- IEStatusCode status = ie_core_create("", &core); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_create status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // Step 2. Read a model in OpenVINO Intermediate Representation (.xml and .bin // files) or ONNX (.onnx file) format status = ie_core_read_network(core, input_model, NULL, &network); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_read_network status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 3. Configure input & output @@ -212,8 +218,10 @@ int main(int argc, char** argv) { // --------------------------- Prepare input blobs // ----------------------------------------------------- status = ie_network_get_input_name(network, 0, &input_name); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_get_input_name status %d, line %d\n", status, __LINE__); goto err; + } /* Mark input as resizable by setting of a resize algorithm. * In this case we will be able to set an input blob of any shape to an infer @@ -226,15 +234,19 @@ int main(int argc, char** argv) { // pre-processing status |= ie_network_set_color_format(network, input_name, NV12); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_set_input_* status %d, line %d\n", status, __LINE__); goto err; + } // --------------------------- Prepare output blobs // ---------------------------------------------------- status |= ie_network_get_output_name(network, 0, &output_name); status |= ie_network_set_output_precision(network, output_name, FP32); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_set_output_* status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- @@ -242,15 +254,19 @@ int main(int argc, char** argv) { // ------------------------------------------ ie_config_t config = {NULL, NULL, NULL}; status = ie_core_load_network(core, network, device_name, &config, &exe_network); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_load_network status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 5. Create infer request // ------------------------------------------------- status = ie_exec_network_create_infer_request(exe_network, &infer_request); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_exec_network_create_infer_request status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 6. Prepare input @@ -258,10 +274,14 @@ int main(int argc, char** argv) { // size converted to NV12 data size: height(NV12) = 3 / 2 * logical height img_size = input_width * (input_height * 3 / 2); img_data = (unsigned char*)calloc(img_size, sizeof(unsigned char)); - if (NULL == img_data) + if (NULL == img_data) { + fprintf(stderr, "ERROR calloc returned NULL, line %d\n", __LINE__); goto err; - if (img_size != read_image_from_file(input_image_path, img_data, img_size)) + } + if (img_size != read_image_from_file(input_image_path, img_data, img_size)) { + fprintf(stderr, "ERROR ie_exec_network_create_infer_request `img_size` missmatch, line %d\n", __LINE__); goto err; + } // --------------------------- Create a blob to hold the NV12 input data // ------------------------------- Create tensor descriptors for Y and UV @@ -279,27 +299,35 @@ int main(int argc, char** argv) { status |= ie_blob_make_memory_from_preallocated(&uv_tensor, img_data + y_plane_size, uv_plane_size, &uv_blob); // Create NV12Blob from Y and UV blobs status |= ie_blob_make_memory_nv12(y_blob, uv_blob, &nv12_blob); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_blob_make_memory_* status %d, line %d\n", status, __LINE__); goto err; + } status = ie_infer_request_set_blob(infer_request, input_name, nv12_blob); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_set_blob status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 7. Do inference // -------------------------------------------------------- /* Running the request synchronously */ status = ie_infer_request_infer(infer_request); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_infer status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 8. Process output // ------------------------------------------------------ status = ie_infer_request_get_blob(infer_request, output_name, &output_blob); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_get_blob status %d, line %d\n", status, __LINE__); goto err; + } size_t class_num; struct classify_res* cls = output_blob_to_classify_res(output_blob, &class_num); diff --git a/samples/c/object_detection_sample_ssd/main.c b/samples/c/object_detection_sample_ssd/main.c index c71d643950d022..8899fdb460234f 100644 --- a/samples/c/object_detection_sample_ssd/main.c +++ b/samples/c/object_detection_sample_ssd/main.c @@ -69,6 +69,7 @@ int ParseAndCheckCommandLine(int argc, char* argv[]) { config_msg = optarg; break; default: + fprintf(stderr, "Unknown argument `%c`. Please use -h option.\n", opt); return -1; } } @@ -76,11 +77,11 @@ int ParseAndCheckCommandLine(int argc, char* argv[]) { if (help) return -1; if (input_model == NULL) { - printf("Model is required but not set. Please set -m option.\n"); + fprintf(stderr, "Model is required but not set. Please set -m option.\n"); return -1; } if (img_msg == NULL) { - printf("Input is required but not set.Please set -i option.\n"); + fprintf(stderr, "Input is required but not set.Please set -i option.\n"); return -1; } @@ -96,14 +97,14 @@ int ParseAndCheckCommandLine(int argc, char* argv[]) { void readInputFilesArgument(const char* arg) { struct stat sb; if (stat(arg, &sb) != 0) { - printf("%sFile %s cannot be opened!\n", warn, arg); + fprintf(stderr, "%sFile %s cannot be opened!\n", warn, arg); return; } if (S_ISDIR(sb.st_mode)) { DIR* dp; dp = opendir(arg); if (dp == NULL) { - printf("%sFile %s cannot be opened!\n", warn, arg); + fprintf(stderr, "%sFile %s cannot be opened!\n", warn, arg); return; } @@ -189,6 +190,7 @@ void parseInputFilesArguments(int argc, char** argv) { ie_config_t* parseConfig(const char* config_file, char comment) { FILE* file = fopen(config_file, "r"); if (!file) { + fprintf(stderr, "ERROR file `%s` opening failure\n", config_file); return NULL; } @@ -323,7 +325,7 @@ int main(int argc, char** argv) { /** This file_paths stores paths to the processed images **/ parseInputFilesArguments(argc, argv_temp); if (!file_num) { - printf("No suitable images were found\n"); + fprintf(stderr, "No suitable images were found\n"); free(argv_temp); return EXIT_FAILURE; } @@ -334,16 +336,20 @@ int main(int argc, char** argv) { printf("%sLoading Inference Engine\n", info); IEStatusCode status = ie_core_create("", &core); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_create status %d, line %d\n", status, __LINE__); goto err; + } // ------------------------------ Get Available Devices // ------------------------------------------------------ ie_core_versions_t ver; printf("%sDevice info: \n", info); status = ie_core_get_versions(core, device_name, &ver); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_get_versions status %d, line %d\n", status, __LINE__); goto err; + } for (i = 0; i < ver.num_vers; ++i) { printf(" %s\n", ver.versions[i].device_name); printf(" %s version ......... %zu.%zu\n", @@ -358,8 +364,10 @@ int main(int argc, char** argv) { // Custom CPU extension is loaded as a shared library and passed as a // pointer to base extension status = ie_core_add_extension(core, custom_ex_library_msg, "CPU"); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_add_extension status %d, line %d\n", status, __LINE__); goto err; + } printf("%sCustom extension loaded: %s\n", info, custom_ex_library_msg); } @@ -369,8 +377,10 @@ int main(int argc, char** argv) { // description ie_config_t cfg = {"CONFIG_FILE", custom_plugin_cfg_msg, NULL}; status = ie_core_set_config(core, &cfg, device_name); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_set_config status %d, line %d\n", status, __LINE__); goto err; + } printf("%sConfig for device plugin custom extension loaded: %s\n", info, custom_plugin_cfg_msg); } // ----------------------------------------------------------------------------------------------------- @@ -380,8 +390,10 @@ int main(int argc, char** argv) { printf("%sLoading network:\n", info); printf("\t%s\n", input_model); status = ie_core_read_network(core, input_model, NULL, &network); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_read_network status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 3. Configure input & output @@ -394,7 +406,7 @@ int main(int argc, char** argv) { size_t input_num = 0; status = ie_network_get_inputs_number(network, &input_num); if (status != OK || (input_num != 1 && input_num != 2)) { - printf("Sample supports topologies only with 1 or 2 inputs\n"); + fprintf(stderr, "Sample supports topologies only with 1 or 2 inputs\n"); goto err; } @@ -435,7 +447,7 @@ int main(int argc, char** argv) { status = ie_network_set_input_precision(network, name, FP32); if (status != OK || (input_dim.dims[1] != 3 && input_dim.dims[1] != 6)) { - printf("Invalid input info. Should be 3 or 6 values length\n"); + fprintf(stderr, "Invalid input info. Should be 3 or 6 values length\n"); goto err; } } @@ -464,7 +476,7 @@ int main(int argc, char** argv) { for (i = 0; i < file_num; ++i) { c_mat_t img = {NULL, 0, 0, 0, 0, 0}; if (image_read(file_paths[i], &img) == -1) { - printf("%sImage %s cannot be read!\n", warn, file_paths[i]); + fprintf(stderr, "%sImage %s cannot be read!\n", warn, file_paths[i]); continue; } /** Store image data **/ @@ -504,7 +516,7 @@ int main(int argc, char** argv) { } if (!image_num) { - printf("Valid input images were not found!\n"); + fprintf(stderr, "Valid input images were not found!\n"); free(originalImages); free(images); goto err; @@ -512,8 +524,10 @@ int main(int argc, char** argv) { input_shapes_t shapes; status = ie_network_get_input_shapes(network, &shapes); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_get_input_shapes status %d, line %d\n", status, __LINE__); goto err; + } /** Using ie_network_reshape() to set the batch size equal to the number of * input images **/ @@ -521,14 +535,18 @@ int main(int argc, char** argv) { * **/ shapes.shapes[0].shape.dims[0] = image_num; status = ie_network_reshape(network, shapes); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_reshape status %d, line %d\n", status, __LINE__); goto err; + } ie_network_input_shapes_free(&shapes); input_shapes_t shapes2; status = ie_network_get_input_shapes(network, &shapes2); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_get_input_shapes status %d, line %d\n", status, __LINE__); goto err; + } size_t batchSize = shapes2.shapes[0].shape.dims[0]; ie_network_input_shapes_free(&shapes2); printf("%sBatch size is %zu\n", info, batchSize); @@ -541,20 +559,24 @@ int main(int argc, char** argv) { status = ie_network_get_outputs_number(network, &output_num); if (status != OK || !output_num) { - printf("Can't find a DetectionOutput layer in the topology\n"); + fprintf(stderr, "Can't find a DetectionOutput layer in the topology\n"); goto err; } status = ie_network_get_output_name(network, output_num - 1, &output_name); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_get_output_name status %d, line %d\n", status, __LINE__); goto err; + } dimensions_t output_dim; status = ie_network_get_output_dims(network, output_name, &output_dim); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_get_output_dims status %d, line %d\n", status, __LINE__); goto err; + } if (output_dim.ranks != 4) { - printf("Incorrect output dimensions for SSD model\n"); + fprintf(stderr, "Incorrect output dimensions for SSD model\n"); goto err; } @@ -569,8 +591,10 @@ int main(int argc, char** argv) { /** Set the precision of output data provided by the user, should be called * before load of the network to the device **/ status = ie_network_set_output_precision(network, output_name, FP32); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_network_set_output_precision status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 4. Loading model to the device @@ -581,13 +605,16 @@ int main(int argc, char** argv) { status = ie_core_load_network(core, network, device_name, config, &exe_network); config_free(config); if (status != OK) { + fprintf(stderr, "ERROR ie_core_load_network status %d, line %d\n", status, __LINE__); goto err; } } else { ie_config_t cfg = {NULL, NULL, NULL}; status = ie_core_load_network(core, network, device_name, &cfg, &exe_network); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_core_load_network status %d, line %d\n", status, __LINE__); goto err; + } } // ----------------------------------------------------------------------------------------------------- @@ -596,8 +623,10 @@ int main(int argc, char** argv) { // ------------------------------------------------- printf("%sCreate infer request\n", info); status = ie_exec_network_create_infer_request(exe_network, &infer_request); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_exec_network_create_infer_request status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 6. Prepare input @@ -605,22 +634,28 @@ int main(int argc, char** argv) { /** Creating input blob **/ status = ie_infer_request_get_blob(infer_request, imageInputName, &imageInput); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_get_blob status %d, line %d\n", status, __LINE__); goto err; + } /** Filling input tensor with images. First b channel, then g and r channels * **/ dimensions_t input_tensor_dims; status = ie_blob_get_dims(imageInput, &input_tensor_dims); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_blob_get_dims status %d, line %d\n", status, __LINE__); goto err; + } size_t num_channels = input_tensor_dims.dims[1]; size_t image_size = input_tensor_dims.dims[3] * input_tensor_dims.dims[2]; ie_blob_buffer_t blob_buffer; status = ie_blob_get_buffer(imageInput, &blob_buffer); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_blob_get_buffer status %d, line %d\n", status, __LINE__); goto err; + } unsigned char* data = (unsigned char*)(blob_buffer.buffer); /** Iterate over all input images **/ @@ -651,6 +686,7 @@ int main(int argc, char** argv) { ie_blob_buffer_t info_blob_buffer; status |= ie_blob_get_buffer(input2, &info_blob_buffer); if (status != OK) { + fprintf(stderr, "ERROR ie_blob_get_buffer status %d, line %d\n", status, __LINE__); ie_blob_free(&input2); goto err; } @@ -672,8 +708,10 @@ int main(int argc, char** argv) { printf("%sStart inference\n", info); status = ie_infer_request_infer_async(infer_request); status |= ie_infer_request_wait(infer_request, -1); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_infer_async status %d, line %d\n", status, __LINE__); goto err; + } // ----------------------------------------------------------------------------------------------------- // --------------------------- Step 8. Process output @@ -681,13 +719,17 @@ int main(int argc, char** argv) { printf("%sProcessing output blobs\n", info); status = ie_infer_request_get_blob(infer_request, output_name, &output_blob); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_infer_request_get_blob status %d, line %d\n", status, __LINE__); goto err; + } ie_blob_buffer_t output_blob_buffer; status = ie_blob_get_cbuffer(output_blob, &output_blob_buffer); - if (status != OK) + if (status != OK) { + fprintf(stderr, "ERROR ie_blob_get_cbuffer status %d, line %d\n", status, __LINE__); goto err; + } const float* detection = (float*)(output_blob_buffer.cbuffer); int** classes = (int**)calloc(image_num, sizeof(int*)); diff --git a/scripts/demo/run_sample_benchmark_app.bat b/scripts/demo/run_sample_benchmark_app.bat index b9499bcca4e076..18f78faea58d70 100644 --- a/scripts/demo/run_sample_benchmark_app.bat +++ b/scripts/demo/run_sample_benchmark_app.bat @@ -4,12 +4,18 @@ @echo off setlocal enabledelayedexpansion +set ROOT_DIR=%~dp0 + set TARGET=CPU set BUILD_FOLDER=%USERPROFILE%\Documents\Intel\OpenVINO :: command line arguments parsing :input_arguments_loop if not "%1"=="" ( + if "%1"=="-b" ( + set BUILD_FOLDER=%2 + shift + ) if "%1"=="-d" ( set TARGET=%2 echo target = !TARGET! @@ -25,6 +31,7 @@ if not "%1"=="" ( echo. echo Options: echo -help Print help message + echo -b BUILD_FOLDER Specify the sample build directory echo -d DEVICE Specify the target device to infer on; CPU, GPU, HDDL or MYRIAD are acceptable. Sample will look for a suitable plugin for device specified echo -sample-options OPTIONS Specify command line arguments for the sample exit /b @@ -33,12 +40,12 @@ if not "%1"=="" ( goto :input_arguments_loop ) +set "SOLUTION_DIR64=%BUILD_FOLDER%\inference_engine_cpp_samples_build" + IF "%SAMPLE_OPTIONS%"=="" ( set SAMPLE_OPTIONS=-niter 1000 ) -set ROOT_DIR=%~dp0 - set TARGET_PRECISION=FP16 echo target_precision = !TARGET_PRECISION! @@ -158,81 +165,21 @@ if "%PROCESSOR_ARCHITECTURE%" == "AMD64" ( set "PLATFORM=Win32" ) -set VSWHERE="false" -if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ( - set VSWHERE="true" - cd /d "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer" -) else if exist "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" ( - set VSWHERE="true" - cd /d "%ProgramFiles%\Microsoft Visual Studio\Installer" -) else ( - echo "vswhere tool is not found" -) - -if !VSWHERE! == "true" ( - for /f "usebackq tokens=*" %%i in (`vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath`) do ( - set VS_PATH=%%i - ) - if exist "!VS_PATH!\MSBuild\14.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\14.0\Bin\MSBuild.exe" - ) - if exist "!VS_PATH!\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\15.0\Bin\MSBuild.exe" - ) - if exist "!VS_PATH!\MSBuild\Current\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\Current\Bin\MSBuild.exe" - ) - for /f "usebackq tokens=1 delims=." %%i in (`vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationVersion`) do ( - set VS_MAJOR_VER=%%i - ) - if "!VS_MAJOR_VER!"=="16" set "MSBUILD_VERSION=16 2019" - if "!VS_MAJOR_VER!"=="15" set "MSBUILD_VERSION=15 2017" -) - -if "!MSBUILD_BIN!" == "" ( - if exist "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=14 2015" - ) - if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) - if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) - if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) -) else ( - if not "!MSBUILD_BIN:2019=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=16 2019" - if not "!MSBUILD_BIN:2017=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=15 2017" - if not "!MSBUILD_BIN:2015=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=14 2015" -) - -if "!MSBUILD_BIN!" == "" ( - echo Build tools for Visual Studio 2015 / 2017 / 2019 cannot be found. If you use Visual Studio 2017, please download and install build tools from https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017 - GOTO errorHandling -) - -set "SOLUTION_DIR64=%BUILD_FOLDER%\inference_engine_cpp_samples_build" - -echo Creating Visual Studio !MSBUILD_VERSION! %PLATFORM% files in %SOLUTION_DIR64%... && ^ if exist "%SOLUTION_DIR64%\CMakeCache.txt" del "%SOLUTION_DIR64%\CMakeCache.txt" -cd /d "%INTEL_OPENVINO_DIR%\samples\cpp" && cmake -E make_directory "%SOLUTION_DIR64%" && cd /d "%SOLUTION_DIR64%" && cmake -G "Visual Studio !MSBUILD_VERSION!" -A %PLATFORM% "%INTEL_OPENVINO_DIR%\samples\cpp" + +cd /d "%INTEL_OPENVINO_DIR%\samples\cpp" && cmake -E make_directory "%SOLUTION_DIR64%" && cd /d "%SOLUTION_DIR64%" && cmake -G "Visual Studio 16 2019" -A %PLATFORM% "%INTEL_OPENVINO_DIR%\samples\cpp" if ERRORLEVEL 1 GOTO errorHandling CALL :delay 7 echo. -echo ###############^|^| Build Inference Engine samples using MS Visual Studio (MSBuild.exe) ^|^|############### +echo ###############^|^| Build Inference Engine samples using cmake ^|^|############### echo. + CALL :delay 3 -echo "!MSBUILD_BIN!" Samples.sln /p:Configuration=Release /t:cpp_samples\benchmark_app /clp:ErrorsOnly /m -"!MSBUILD_BIN!" Samples.sln /p:Configuration=Release /t:cpp_samples\benchmark_app /clp:ErrorsOnly /m +echo cmake --build . --config Release --target benchmark_app +cmake --build . --config Release --target benchmark_app if ERRORLEVEL 1 GOTO errorHandling CALL :delay 7 diff --git a/scripts/demo/run_sample_benchmark_app.sh b/scripts/demo/run_sample_benchmark_app.sh index 9e273d6c2a515e..d7b1077afcca76 100755 --- a/scripts/demo/run_sample_benchmark_app.sh +++ b/scripts/demo/run_sample_benchmark_app.sh @@ -6,6 +6,7 @@ echo -ne "\e[0;33mWARNING: If you get an error when running the sample in the Docker container, you may need to install additional packages. To do this, run the container as root (-u 0) and run install_openvino_dependencies.sh script. If you get a package-independent error, try setting additional parameters using -sample-options.\e[0m\n" ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]-$0}" )" && pwd )" +build_dir="$HOME/inference_engine_cpp_samples_build" . "$ROOT_DIR/utils.sh" @@ -14,6 +15,7 @@ usage() { echo echo "Options:" echo " -help Print help message" + echo " -b BUILD_DIR Specify the sample build directory" echo " -d DEVICE Specify the target device to infer on; CPU, GPU, HDDL or MYRIAD are acceptable. Sample will look for a suitable plugin for device specified" echo " -sample-options OPTIONS Specify command line arguments for the sample" echo @@ -30,6 +32,10 @@ do key="$1" case $key in + -b | --build_dir) + build_dir="$2/inference_engine_cpp_samples_build" + shift + ;; -h | -help | --help) usage ;; @@ -58,9 +64,9 @@ target_precision="FP16" echo -ne "target_precision = ${target_precision}\n" -models_path="$HOME/openvino_models/models" -models_cache="$HOME/openvino_models/cache" -irs_path="$HOME/openvino_models/ir" +models_path="$build_dir/../openvino_models/models" +models_cache="$build_dir/../openvino_models/cache" +irs_path="$build_dir/../openvino_models/ir" model_name="squeezenet1.1" @@ -163,7 +169,6 @@ if [ "$OS_PATH" == "x86_64" ]; then fi samples_path="${INTEL_OPENVINO_DIR}/samples/cpp" -build_dir="$HOME/inference_engine_cpp_samples_build" binaries_dir="${build_dir}/${OS_PATH}/Release" if [ -e "$build_dir/CMakeCache.txt" ]; then diff --git a/scripts/demo/run_sample_squeezenet.bat b/scripts/demo/run_sample_squeezenet.bat index 293168cb9e710d..2ccb9e7c18b022 100644 --- a/scripts/demo/run_sample_squeezenet.bat +++ b/scripts/demo/run_sample_squeezenet.bat @@ -4,12 +4,18 @@ @echo off setlocal enabledelayedexpansion +set ROOT_DIR=%~dp0 + set TARGET=CPU set BUILD_FOLDER=%USERPROFILE%\Documents\Intel\OpenVINO :: command line arguments parsing :input_arguments_loop if not "%1"=="" ( + if "%1"=="-b" ( + set BUILD_FOLDER=%2 + shift + ) if "%1"=="-d" ( set TARGET=%2 echo target = !TARGET! @@ -25,6 +31,7 @@ if not "%1"=="" ( echo. echo Options: echo -help Print help message + echo -b BUILD_FOLDER Specify the sample build directory echo -d DEVICE Specify the target device to infer on; CPU, GPU, HDDL or MYRIAD are acceptable. Sample will look for a suitable plugin for device specified echo -sample-options OPTIONS Specify command line arguments for the sample exit /b @@ -33,7 +40,7 @@ if not "%1"=="" ( goto :input_arguments_loop ) -set ROOT_DIR=%~dp0 +set "SOLUTION_DIR64=%BUILD_FOLDER%\inference_engine_cpp_samples_build" set TARGET_PRECISION=FP16 @@ -154,81 +161,21 @@ if "%PROCESSOR_ARCHITECTURE%" == "AMD64" ( set "PLATFORM=Win32" ) -set VSWHERE="false" -if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ( - set VSWHERE="true" - cd /d "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer" -) else if exist "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" ( - set VSWHERE="true" - cd /d "%ProgramFiles%\Microsoft Visual Studio\Installer" -) else ( - echo "vswhere tool is not found" -) - -if !VSWHERE! == "true" ( - for /f "usebackq tokens=*" %%i in (`vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationPath`) do ( - set VS_PATH=%%i - ) - if exist "!VS_PATH!\MSBuild\14.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\14.0\Bin\MSBuild.exe" - ) - if exist "!VS_PATH!\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\15.0\Bin\MSBuild.exe" - ) - if exist "!VS_PATH!\MSBuild\Current\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=!VS_PATH!\MSBuild\Current\Bin\MSBuild.exe" - ) - for /f "usebackq tokens=1 delims=." %%i in (`vswhere -latest -products * -requires Microsoft.Component.MSBuild -property installationVersion`) do ( - set VS_MAJOR_VER=%%i - ) - if "!VS_MAJOR_VER!"=="16" set "MSBUILD_VERSION=16 2019" - if "!VS_MAJOR_VER!"=="15" set "MSBUILD_VERSION=15 2017" -) - -if "!MSBUILD_BIN!" == "" ( - if exist "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=14 2015" - ) - if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) - if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) - if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" ( - set "MSBUILD_BIN=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" - set "MSBUILD_VERSION=15 2017" - ) -) else ( - if not "!MSBUILD_BIN:2019=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=16 2019" - if not "!MSBUILD_BIN:2017=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=15 2017" - if not "!MSBUILD_BIN:2015=!"=="!MSBUILD_BIN!" set "MSBUILD_VERSION=14 2015" -) - -if "!MSBUILD_BIN!" == "" ( - echo Build tools for Visual Studio 2015 / 2017 / 2019 cannot be found. If you use Visual Studio 2017, please download and install build tools from https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017 - GOTO errorHandling -) - -set "SOLUTION_DIR64=%BUILD_FOLDER%\inference_engine_cpp_samples_build" - -echo Creating Visual Studio !MSBUILD_VERSION! %PLATFORM% files in %SOLUTION_DIR64%... && ^ if exist "%SOLUTION_DIR64%\CMakeCache.txt" del "%SOLUTION_DIR64%\CMakeCache.txt" -cd /d "%INTEL_OPENVINO_DIR%\samples\cpp" && cmake -E make_directory "%SOLUTION_DIR64%" && cd /d "%SOLUTION_DIR64%" && cmake -G "Visual Studio !MSBUILD_VERSION!" -A %PLATFORM% "%INTEL_OPENVINO_DIR%\samples\cpp" + +cd /d "%INTEL_OPENVINO_DIR%\samples\cpp" && cmake -E make_directory "%SOLUTION_DIR64%" && cd /d "%SOLUTION_DIR64%" && cmake -G "Visual Studio 16 2019" -A %PLATFORM% "%INTEL_OPENVINO_DIR%\samples\cpp" if ERRORLEVEL 1 GOTO errorHandling CALL :delay 7 echo. -echo ###############^|^| Build Inference Engine samples using MS Visual Studio (MSBuild.exe) ^|^|############### +echo ###############^|^| Build Inference Engine samples using cmake ^|^|############### echo. + CALL :delay 3 -echo "!MSBUILD_BIN!" Samples.sln /p:Configuration=Release /t:cpp_samples\classification_sample_async /clp:ErrorsOnly /m -"!MSBUILD_BIN!" Samples.sln /p:Configuration=Release /t:cpp_samples\classification_sample_async /clp:ErrorsOnly /m +echo cmake --build . --config Release --target classification_sample_async +cmake --build . --config Release --target classification_sample_async if ERRORLEVEL 1 GOTO errorHandling CALL :delay 7 diff --git a/scripts/demo/run_sample_squeezenet.sh b/scripts/demo/run_sample_squeezenet.sh index 3d1b12a1fec6fc..1ce3a61cb9d5c7 100755 --- a/scripts/demo/run_sample_squeezenet.sh +++ b/scripts/demo/run_sample_squeezenet.sh @@ -6,6 +6,7 @@ echo -ne "\e[0;33mWARNING: If you get an error when running the sample in the Docker container, you may need to install additional packages. To do this, run the container as root (-u 0) and run install_openvino_dependencies.sh script. If you get a package-independent error, try setting additional parameters using -sample-options.\e[0m\n" ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]-$0}" )" && pwd )" +build_dir="$HOME/inference_engine_cpp_samples_build" . "$ROOT_DIR/utils.sh" @@ -14,6 +15,7 @@ usage() { echo echo "Options:" echo " -help Print help message" + echo " -b BUILD_DIR Specify the sample build directory" echo " -d DEVICE Specify the target device to infer on; CPU, GPU, HDDL or MYRIAD are acceptable. Sample will look for a suitable plugin for device specified" echo " -sample-options OPTIONS Specify command line arguments for the sample" echo @@ -30,6 +32,10 @@ do key="$1" case $key in + -b | --build_dir) + build_dir="$2/inference_engine_cpp_samples_build" + shift + ;; -h | -help | --help) usage ;; @@ -54,9 +60,9 @@ target_precision="FP16" echo -ne "target_precision = ${target_precision}\n" -models_path="$HOME/openvino_models/models" -models_cache="$HOME/openvino_models/cache" -irs_path="$HOME/openvino_models/ir" +models_path="$build_dir/../openvino_models/models" +models_cache="$build_dir/../openvino_models/cache" +irs_path="$build_dir/../openvino_models/ir" model_name="squeezenet1.1" diff --git a/tests/fuzz/src/import_pdpd-fuzzer.cc b/tests/fuzz/src/import_pdpd-fuzzer.cc index b25338c4356f83..5d76b9974a4ffc 100644 --- a/tests/fuzz/src/import_pdpd-fuzzer.cc +++ b/tests/fuzz/src/import_pdpd-fuzzer.cc @@ -11,8 +11,8 @@ const char split_sequence[] = {'F', 'U', 'Z', 'Z', '_', 'N', 'E', 'X', 'T', '_', 'F', 'I', 'E', 'L', 'D'}; const char *PDPD = "paddle"; -using namespace ngraph; -using namespace ngraph::frontend; +using namespace ov; +using namespace ov::frontend; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /// split input buffer to model and params @@ -23,10 +23,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { const void *params_buf = tokenizer.next(¶ms_size); try { - ngraph::frontend::FrontEndManager frontend_manager = FrontEndManager(); - ngraph::frontend::FrontEnd::Ptr frontend = + ov::frontend::FrontEndManager frontend_manager = FrontEndManager(); + ov::frontend::FrontEnd::Ptr frontend = frontend_manager.load_by_framework(PDPD); - ngraph::frontend::InputModel::Ptr input_model; + ov::frontend::InputModel::Ptr input_model; std::stringstream model; std::stringstream params; model << std::string((const char *)model_buf, model_size); @@ -37,9 +37,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { input_model = frontend->load(in_model, in_params); } else input_model = frontend->load(in_model); - std::shared_ptr function = frontend->convert(input_model); + std::shared_ptr function = frontend->convert(input_model); } catch (const std::exception&) { return 0; // fail gracefully on expected exceptions } return 0; -} \ No newline at end of file +} diff --git a/tests/layer_tests/common/constants.py b/tests/layer_tests/common/constants.py index cf570fc40c2d88..26e6942d791db7 100644 --- a/tests/layer_tests/common/constants.py +++ b/tests/layer_tests/common/constants.py @@ -4,14 +4,6 @@ import os -if 'MO_ROOT' in os.environ: - mo_bin = os.environ['MO_ROOT'] - if not os.path.exists(mo_bin): - raise EnvironmentError( - "Environment variable MO_ROOT points to non existing path {}".format(mo_bin)) -else: - raise EnvironmentError("MO_ROOT variable is not set") - if os.environ.get('OUTPUT_DIR') is not None: out_path = os.environ['OUTPUT_DIR'] else: diff --git a/tests/layer_tests/common/layer_test_class.py b/tests/layer_tests/common/layer_test_class.py index c6e51d2c1f86dd..d501f535e94037 100644 --- a/tests/layer_tests/common/layer_test_class.py +++ b/tests/layer_tests/common/layer_test_class.py @@ -24,14 +24,15 @@ def produce_model_path(self, framework_model, save_path): def get_framework_results(self, inputs_dict, model_path): pass - def _test(self, framework_model, ref_net, ie_device, precision, ir_version, temp_dir, infer_timeout=60, - enabled_transforms='', disabled_transforms='', **kwargs): + def _test(self, framework_model, ref_net, ie_device, precision, ir_version, temp_dir, use_new_frontend=False, + infer_timeout=60, enabled_transforms='', disabled_transforms='', **kwargs): """ :param enabled_transforms/disabled_transforms: string with idxs of transforms that should be enabled/disabled. Example: "transform_1,transform_2" """ model_path = self.produce_model_path(framework_model=framework_model, save_path=temp_dir) + self.use_new_frontend = use_new_frontend # TODO Pass environment variables via subprocess environment os.environ['MO_ENABLED_TRANSFORMS'] = enabled_transforms os.environ['MO_DISABLED_TRANSFORMS'] = disabled_transforms @@ -50,6 +51,9 @@ def _test(self, framework_model, ref_net, ie_device, precision, ir_version, temp if 'input_names' in kwargs and len(kwargs['input_names']): mo_params.update(dict(input=','.join(kwargs['input_names']))) + if use_new_frontend: + mo_params["use_new_frontend"] = True + exit_code, stderr = generate_ir(**mo_params) del os.environ['MO_ENABLED_TRANSFORMS'] diff --git a/tests/layer_tests/common/tf_layer_test_class.py b/tests/layer_tests/common/tf_layer_test_class.py index ab19c29e9701f8..18ce17913d2f1f 100644 --- a/tests/layer_tests/common/tf_layer_test_class.py +++ b/tests/layer_tests/common/tf_layer_test_class.py @@ -4,10 +4,33 @@ import os from common.layer_test_class import CommonLayerTest - from common.utils.tf_utils import summarize_graph +def transpose_nchw_to_nhwc(data, use_new_frontend): + if use_new_frontend: + return data + + if len(data.shape) == 4: # reshaping for 4D tensors + return data.transpose(0, 2, 3, 1) + elif len(data.shape) == 5: # reshaping for 5D tensors + return data.transpose(0, 2, 3, 4, 1) + else: + return data + + +def transpose_nhwc_to_nchw(data, use_new_frontend): + if use_new_frontend: + return data + + if len(data.shape) == 4: # reshaping for 4D tensors + return data.transpose(0, 3, 1, 2) # 2, 0, 1 + elif len(data.shape) == 5: # reshaping for 5D tensors + return data.transpose(0, 4, 1, 2, 3) # 3, 0, 1, 2 + else: + return data + + def save_to_pb(tf_model, path_to_saved_tf_model): import tensorflow as tf tf.io.write_graph(tf_model, path_to_saved_tf_model, 'model.pb', False) @@ -41,21 +64,11 @@ def get_framework_results(self, inputs_dict, model_path): input = dict() for key in inputs_dict.keys(): data = inputs_dict.get(key) - if len(data.shape) == 4: # reshaping for 4D tensors - input[key+':0'] = data.transpose(0, 2, 3, 1) - elif len(data.shape) == 5: # reshaping for 5D tensors - input[key+':0'] = data.transpose(0, 2, 3, 4, 1) - else: - input[key+':0'] = data + input[key + ':0'] = transpose_nchw_to_nhwc(data, self.use_new_frontend) tf_res = sess.run([out + ":0" for out in outputs_list], input) result = dict() for i, output in enumerate(outputs_list): _tf_res = tf_res[i] - if len(_tf_res.shape) == 4: # reshaping for 4D tensors - result[output] = _tf_res.transpose(0, 3, 1, 2) # 2, 0, 1 - elif len(_tf_res.shape) == 5: # reshaping for 5D tensors - result[output] = _tf_res.transpose(0, 4, 1, 2, 3) # 3, 0, 1, 2 - else: - result[output] = _tf_res + result[output] = transpose_nhwc_to_nchw(_tf_res, self.use_new_frontend) return result diff --git a/tests/layer_tests/common/utils/common_utils.py b/tests/layer_tests/common/utils/common_utils.py index f92daf51c26bcc..e5fc5d93f3773b 100644 --- a/tests/layer_tests/common/utils/common_utils.py +++ b/tests/layer_tests/common/utils/common_utils.py @@ -2,24 +2,24 @@ # SPDX-License-Identifier: Apache-2.0 import logging -import os import subprocess import sys +from pathlib import Path +import mo import numpy as np - logger = logging.getLogger(__name__) def generate_ir(coverage=False, **kwargs): - # Get default mo args - mo = os.path.join(os.environ.get("MO_ROOT"), "mo.py") + mo_path = Path(mo.__file__).parent + mo_runner = mo_path.joinpath('main.py').as_posix() if coverage: - params = [sys.executable, '-m', 'coverage', 'run', '-p', '--source={}'.format(os.environ.get("MO_ROOT")), - '--omit=*_test.py', mo] + params = [sys.executable, '-m', 'coverage', 'run', '-p', '--source={}'.format(mo_path.parent), + '--omit=*_test.py', mo_runner] else: - params = [sys.executable, mo] + params = [sys.executable, mo_runner] for key, value in kwargs.items(): if key == "batch": params.extend(("-b", str(value))) diff --git a/tests/layer_tests/common/utils/tf_utils.py b/tests/layer_tests/common/utils/tf_utils.py index 7900586390cc1d..cae4cb0f17d039 100644 --- a/tests/layer_tests/common/utils/tf_utils.py +++ b/tests/layer_tests/common/utils/tf_utils.py @@ -7,6 +7,7 @@ import tensorflow as tf import numpy as np +from mo.ops.op import PermuteAttrs os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' @@ -107,3 +108,23 @@ def summarize_graph(model_path, output_nodes_for_freeze=None, reshape_net=None): result['inputs'][layer]['shape'] = scoring_res[layer].shape return result + + +def permute_nhwc_to_nchw(shape, use_new_frontend=False): + if use_new_frontend: + return shape + perm = PermuteAttrs.get_nhwc_to_nchw_permutation(len(shape)).perm + new_shape = np.array(shape)[perm] + return new_shape + + +def permute_nchw_to_nhwc(shape, use_new_frontend=False): + if use_new_frontend: + return shape + perm = PermuteAttrs.get_nchw_to_nhwc_permutation(len(shape)).perm + new_shape = np.array(shape)[perm] + return new_shape + + +def permute_axis(axis, permutation_inv): + return permutation_inv[axis] diff --git a/tests/layer_tests/conftest.py b/tests/layer_tests/conftest.py index 350fd22a3b20f5..94b3deb5c1e039 100644 --- a/tests/layer_tests/conftest.py +++ b/tests/layer_tests/conftest.py @@ -59,6 +59,11 @@ def pytest_addoption(parser): required=True, action="store", help="Version of IR to generate by Model Optimizer") + parser.addoption( + "--use_new_frontend", + required=False, + action="store_true", + help="Use Model Optimizer with new FrontEnd") @pytest.fixture(scope="session") @@ -67,6 +72,12 @@ def ir_version(request): return request.config.getoption('ir_version') +@pytest.fixture(scope="session") +def use_new_frontend(request): + """Fixture function for command-line option.""" + return request.config.getoption('use_new_frontend') + + @pytest.fixture(scope="function") def temp_dir(request): """Create directory for test purposes.""" diff --git a/tests/layer_tests/tensorflow_tests/permutation_utils.py b/tests/layer_tests/tensorflow_tests/permutation_utils.py deleted file mode 100644 index c26c7b690f72ec..00000000000000 --- a/tests/layer_tests/tensorflow_tests/permutation_utils.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import numpy as np - -from mo.ops.op import PermuteAttrs - - -def permute_nhwc_to_nchw(shape): - perm = PermuteAttrs.get_nhwc_to_nchw_permutation(len(shape)).perm - new_shape = np.array(shape)[perm] - return new_shape - - -def permute_nchw_to_nhwc(shape): - perm = PermuteAttrs.get_nchw_to_nhwc_permutation(len(shape)).perm - new_shape = np.array(shape)[perm] - return new_shape - - -def permute_axis(axis, permutation_inv): - return permutation_inv[axis] diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Add.py b/tests/layer_tests/tensorflow_tests/test_tf_Add.py index 46508f610d7a6f..c629841b3804c0 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Add.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Add.py @@ -5,10 +5,11 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestAdd(CommonTFLayerTest): - def create_add_placeholder_const_net(self, x_shape, y_shape, ir_version): + def create_add_placeholder_const_net(self, x_shape, y_shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -30,11 +31,9 @@ def create_add_placeholder_const_net(self, x_shape, y_shape, ir_version): with tf.compat.v1.Session() as sess: tf_x_shape = x_shape.copy() tf_y_shape = y_shape.copy() - # reshaping - if len(tf_x_shape) >= 3: - tf_x_shape.append(tf_x_shape.pop(1)) - if len(tf_y_shape) >= 3: - tf_y_shape.append(tf_y_shape.pop(1)) + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + tf_y_shape = permute_nchw_to_nhwc(tf_y_shape, use_new_frontend) x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') constant_value = np.random.randint(-256, 256, tf_y_shape).astype(np.float32) @@ -55,23 +54,6 @@ def create_add_placeholder_const_net(self, x_shape, y_shape, ir_version): # Moreover, do not forget to validate ALL layer attributes!!! # - if len(add_shape) >= 3: - # Permute add_shape to (N,C,...) format - order = [0, len(add_shape) - 1] + list(range(1, len(add_shape) - 1)) - add_shape = [add_shape[i] for i in order] - - y_shape_to_compare = tf_y_shape.copy() - while len(y_shape_to_compare) < len(x_shape): - # Expand shape of constant with 1 - y_shape_to_compare = [1] + y_shape_to_compare - constant_value = np.expand_dims(constant_value, axis=0) - - if len(y_shape_to_compare) >= 3: - # Permute constant_value to (N,C,...) format for correct further reshape - order = [0, len(y_shape_to_compare) - 1] + list(range(1, len(y_shape_to_compare) - 1)) - y_shape_to_compare = [y_shape_to_compare[i] for i in order] - constant_value = np.transpose(constant_value, order) - ref_net = None return tf_net, ref_net @@ -87,9 +69,9 @@ def create_add_placeholder_const_net(self, x_shape, y_shape, ir_version): @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_add_placeholder_const_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [ # Power @@ -104,9 +86,9 @@ def test_add_placeholder_const_1D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_add_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ # Power @@ -122,9 +104,9 @@ def test_add_placeholder_const_2D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_add_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ # Power @@ -140,9 +122,9 @@ def test_add_placeholder_const_3D(self, params, ie_device, precision, ir_version # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_add_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ # Power @@ -159,9 +141,9 @@ def test_add_placeholder_const_4D(self, params, ie_device, precision, ir_version # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_add_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version=ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version=ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) ############################################################################################### # # @@ -176,9 +158,9 @@ def test_add_placeholder_const_5D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_broadcast_1D) @pytest.mark.nightly - def test_add_placeholder_const_broadcast_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version=ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_broadcast_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version=ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_2D = [ # Power @@ -195,9 +177,9 @@ def test_add_placeholder_const_broadcast_1D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_2D) @pytest.mark.nightly - def test_add_placeholder_const_broadcast_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version=ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_broadcast_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version=ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_3D = [ # Power @@ -218,9 +200,9 @@ def test_add_placeholder_const_broadcast_2D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_3D) @pytest.mark.nightly - def test_add_placeholder_const_broadcast_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version=ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_broadcast_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version=ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_4D = [ # Power @@ -236,9 +218,9 @@ def test_add_placeholder_const_broadcast_3D(self, params, ie_device, precision, # Eltwise dict(x_shape=[1, 3, 1, 1], y_shape=[3, 1]), # Eltwise - dict(x_shape=[1, 3, 1, 2], y_shape=[3, 1, 2]), + dict(x_shape=[1, 2, 1, 3], y_shape=[3, 1, 2]), # Eltwise - dict(x_shape=[1, 3, 1, 2], y_shape=[1, 3, 2]), + dict(x_shape=[1, 2, 1, 3], y_shape=[1, 3, 2]), # Eltwise dict(x_shape=[1, 3, 100, 224], y_shape=[1, 1, 1, 224]), # Eltwise @@ -248,9 +230,9 @@ def test_add_placeholder_const_broadcast_3D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_4D) @pytest.mark.nightly @pytest.mark.precommit - def test_add_placeholder_const_broadcast_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version=ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_broadcast_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version=ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_5D = [ # Power @@ -264,7 +246,7 @@ def test_add_placeholder_const_broadcast_4D(self, params, ie_device, precision, # Eltwise dict(x_shape=[1, 3, 1, 1, 1], y_shape=[3, 1]), # Eltwise - dict(x_shape=[1, 3, 1, 1, 2], y_shape=[1, 3, 2]), + dict(x_shape=[1, 2, 1, 1, 3], y_shape=[1, 3, 2]), # Eltwise dict(x_shape=[1, 3, 5, 1, 2], y_shape=[5, 3, 2, 1]), # Eltwise @@ -276,6 +258,7 @@ def test_add_placeholder_const_broadcast_4D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_5D) @pytest.mark.nightly @pytest.mark.precommit - def test_add_placeholder_const_broadcast_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version), ie_device, precision, - ir_version=ir_version, temp_dir=temp_dir) + def test_add_placeholder_const_broadcast_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + # we do not perform transpose in the test in case of new frontend + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, + ir_version=ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_BatchToSpace.py b/tests/layer_tests/tensorflow_tests/test_tf_BatchToSpace.py index f7d46dfcef4dba..c07727dbd7dd9b 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_BatchToSpace.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_BatchToSpace.py @@ -7,7 +7,7 @@ class TestBatchToSpace(CommonTFLayerTest): - def create_batch_to_space_net(self, in_shape, crops_value, block_shape_value, out_shape, ir_version): + def create_batch_to_space_net(self, in_shape, crops_value, block_shape_value, out_shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -28,7 +28,7 @@ def create_batch_to_space_net(self, in_shape, crops_value, block_shape_value, ou x = tf.compat.v1.placeholder(tf.float32, in_shape, 'Input') crops = tf.constant(crops_value) block_shape = tf.constant(block_shape_value) - tf.batch_to_space(x, block_shape, crops, name='Operation') + tf.batch_to_space_nd(x, block_shape, crops, name='Operation') tf.compat.v1.global_variables_initializer() tf_net = sess.graph_def @@ -61,9 +61,9 @@ def create_batch_to_space_net(self, in_shape, crops_value, block_shape_value, ou @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_batch_to_space_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_batch_to_space_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_batch_to_space_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_batch_to_space_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ dict(in_shape=[72, 2, 1, 4, 2], block_shape_value=[3, 4, 2], crops_value=[[1, 2], [0, 0], [3, 0]], @@ -75,6 +75,6 @@ def test_batch_to_space_4D(self, params, ie_device, precision, ir_version, temp_ @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_batch_to_space_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_batch_to_space_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_batch_to_space_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_batch_to_space_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_BiasAdd.py b/tests/layer_tests/tensorflow_tests/test_tf_BiasAdd.py index b7e997195f58ba..938702142f7f32 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_BiasAdd.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_BiasAdd.py @@ -4,10 +4,11 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestBiasAdd(CommonTFLayerTest): - def create_bias_add_placeholder_const_net(self, shape, ir_version): + def create_bias_add_placeholder_const_net(self, shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -29,9 +30,8 @@ def create_bias_add_placeholder_const_net(self, shape, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: tf_x_shape = shape.copy() - # reshaping - if len(tf_x_shape) >= 3: - tf_x_shape.append(tf_x_shape.pop(1)) + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) tf_y_shape = tf_x_shape[-1:] x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') @@ -56,7 +56,7 @@ def create_bias_add_placeholder_const_net(self, shape, ir_version): return tf_net, ref_net - def create_bias_add_2_consts_net(self, shape, ir_version): + def create_bias_add_2_consts_net(self, shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -82,9 +82,8 @@ def create_bias_add_2_consts_net(self, shape, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: tf_x_shape = shape.copy() - # reshaping - if len(tf_x_shape) >= 3: - tf_x_shape.append(tf_x_shape.pop(1)) + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) tf_y_shape = tf_x_shape[-1:] constant_value_x = np.random.randint(-256, 256, tf_x_shape).astype(np.float32) @@ -93,13 +92,10 @@ def create_bias_add_2_consts_net(self, shape, ir_version): y = tf.constant(constant_value_y) add = tf.nn.bias_add(x, y, name="Operation") - add_shape = add.shape.as_list() - add_value = add.eval() placeholder = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') # Input_1 in graph_def concat = tf.concat([placeholder, add], axis=tf_concat_axis, name='Operation') - concat_shape = concat.shape.as_list() tf.compat.v1.global_variables_initializer() tf_net = sess.graph_def @@ -110,15 +106,6 @@ def create_bias_add_2_consts_net(self, shape, ir_version): # Moreover, do not forget to validate ALL layer attributes!!! # - # Format axis to positive value - concat_ax = tf_concat_axis if tf_concat_axis >= 0 else tf_concat_axis + len(shape) - if len(shape) >= 3: - # Permute shapes to (N,C,...) format - order = [0, len(concat_shape) - 1] + list(range(1, len(concat_shape) - 1)) - concat_shape = [concat_shape[i] for i in order] - concat_ax = order.index(concat_ax) - add_value = np.transpose(add_value, order) - ref_net = None return tf_net, ref_net @@ -130,15 +117,15 @@ def create_bias_add_2_consts_net(self, shape, ir_version): @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_bias_add_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_bias_add_2_consts_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_2_consts_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ pytest.param(dict(shape=[1, 1, 224]), marks=pytest.mark.xfail(reason="*-19053")), @@ -147,15 +134,15 @@ def test_bias_add_2_consts_2D(self, params, ie_device, precision, ir_version, te @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_bias_add_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_bias_add_2_consts_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_2_consts_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ dict(shape=[1, 1, 100, 224]), @@ -165,15 +152,15 @@ def test_bias_add_2_consts_3D(self, params, ie_device, precision, ir_version, te @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly @pytest.mark.precommit - def test_bias_add_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_bias_add_2_consts_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_2_consts_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ dict(shape=[1, 1, 50, 100, 224]), @@ -183,12 +170,12 @@ def test_bias_add_2_consts_4D(self, params, ie_device, precision, ir_version, te @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly @pytest.mark.precommit - def test_bias_add_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_bias_add_2_consts_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bias_add_2_consts_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bias_add_2_consts_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_BinaryOps.py b/tests/layer_tests/tensorflow_tests/test_tf_BinaryOps.py new file mode 100644 index 00000000000000..5625ffe0aa1ffd --- /dev/null +++ b/tests/layer_tests/tensorflow_tests/test_tf_BinaryOps.py @@ -0,0 +1,129 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import numpy as np +import pytest + +from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc + + +def generate_input(op_type, size): + narrow_borders = ["Pow"] + + logical_type = ['LogicalAnd', 'LogicalOr', 'LogicalXor'] + + # usual function domain + lower = -256 + upper = 256 + + # specific domains + if op_type in narrow_borders: + lower = 0 + upper = 16 + + if op_type in logical_type: + return np.random.randint(0, 1, size).astype(np.bool) + elif op_type in narrow_borders: + return np.random.uniform(lower, upper, size).astype(np.float32) + else: + return np.random.uniform(lower, upper, size).astype(np.float32) + + +class TestBinaryOps(CommonTFLayerTest): + def _prepare_input(self, inputs_dict): + for input in inputs_dict.keys(): + inputs_dict[input] = generate_input(self.current_op_type, inputs_dict[input]) + return inputs_dict + + def create_add_placeholder_const_net(self, x_shape, y_shape, ir_version, op_type, use_new_frontend): + """ + Tensorflow net IR net + + Placeholder->BinaryOp => Placeholder->Eltwise or Power or ScaleShift + / / + Const-------/ Const-------/ + + """ + + self.current_op_type = op_type + + # + # Create Tensorflow model + # + import tensorflow as tf + + op_type_to_tf = { + 'Add': tf.math.add, + 'Sub': tf.math.subtract, + 'Mul': tf.math.multiply, + 'Div': tf.math.divide, + 'RealDiv': tf.realdiv, + 'SquaredDifference': tf.math.squared_difference, + 'Pow': tf.math.pow, + 'Maximum': tf.math.maximum, + 'Minimum': tf.math.minimum, + 'Equal': tf.math.equal, + 'NotEqual': tf.math.not_equal, + 'Mod': tf.math.mod, + 'Greater': tf.math.greater, + 'GreaterEqual': tf.math.greater_equal, + 'Less': tf.math.less, + 'LessEqual': tf.math.less_equal, + 'LogicalAnd': tf.math.logical_and, + 'LogicalOr': tf.math.logical_or, + 'LogicalXor': tf.math.logical_xor, + 'FloorMod': tf.math.floormod, + } + + type = np.float32 + if op_type in ["LogicalAnd", "LogicalOr", "LogicalXor"]: + type = np.bool + tf.compat.v1.reset_default_graph() + # Create the graph and model + with tf.compat.v1.Session() as sess: + tf_x_shape = x_shape.copy() + tf_y_shape = y_shape.copy() + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + tf_y_shape = permute_nchw_to_nhwc(tf_y_shape, use_new_frontend) + + x = tf.compat.v1.placeholder(type, tf_x_shape, 'Input') + constant_value = generate_input(op_type, tf_y_shape) + if (constant_value == 0).all(): + # Avoid elimination of the layer from IR + constant_value = constant_value + 1 + y = tf.constant(constant_value, dtype=type) + + op = op_type_to_tf[op_type](x, y, name="Operation") + + tf.compat.v1.global_variables_initializer() + tf_net = sess.graph_def + + # + # Create reference IR net + # Please, specify 'type': 'Input' for input node + # Moreover, do not forget to validate ALL layer attributes!!! + # + + ref_net = None + + return tf_net, ref_net + + test_data_precommits = [dict(x_shape=[2, 3, 4], y_shape=[2, 3, 4]), + dict(x_shape=[2, 3, 4, 5], y_shape=[2, 3, 4, 5])] + + @pytest.mark.parametrize("params", test_data_precommits) + @pytest.mark.parametrize("op_type", + ['Add', 'Sub', 'Mul', 'Div', 'RealDiv', 'SquaredDifference', 'Pow', 'Maximum', 'Minimum', + 'Equal', 'NotEqual', 'Mod', 'Greater', 'GreaterEqual', 'Less', 'LessEqual', + 'LogicalAnd', 'LogicalOr', 'LogicalXor', 'FloorMod']) + @pytest.mark.nightly + @pytest.mark.precommit + def test_binary_op(self, params, ie_device, precision, ir_version, temp_dir, op_type, use_new_frontend): + if ie_device == 'GPU' and precision == "FP16": + pytest.skip("BinaryOps tests temporary skipped on GPU with FP16 precision." + "Several tests don't pass accuracy checks.") + self._test(*self.create_add_placeholder_const_net(**params, ir_version=ir_version, op_type=op_type, + use_new_frontend=use_new_frontend), ie_device, precision, + ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Bucketize.py b/tests/layer_tests/tensorflow_tests/test_tf_Bucketize.py index 10d0bc6de74386..3a1d6725dee98b 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Bucketize.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Bucketize.py @@ -10,7 +10,7 @@ class TestBucketize(CommonTFLayerTest): - def create_bucketize_net(self, input_shape, input_type, boundaries_size, ir_version): + def create_bucketize_net(self, input_shape, input_type, boundaries_size, ir_version, use_new_frontend): """ Tensorflow net: IR net: Input => Input Boundaries @@ -30,7 +30,7 @@ def create_bucketize_net(self, input_shape, input_type, boundaries_size, ir_vers # create reference IR net ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: nodes_attributes = { 'input': {'kind': 'op', 'type': 'Parameter'}, 'input_data': {'shape': input_shape, 'kind': 'data'}, @@ -64,9 +64,9 @@ def create_bucketize_net(self, input_shape, input_type, boundaries_size, ir_vers @pytest.mark.parametrize("params", test_data_float32) @pytest.mark.nightly - def test_bucketize_float32(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bucketize_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bucketize_float32(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bucketize_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_int32 = [ dict(input_shape=[5], input_type=tf.int32, boundaries_size=1), @@ -78,6 +78,6 @@ def test_bucketize_float32(self, params, ie_device, precision, ir_version, temp_ @pytest.mark.parametrize("params", test_data_int32) @pytest.mark.nightly - def test_bucketize_int32(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_bucketize_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_bucketize_int32(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_bucketize_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Ceil.py b/tests/layer_tests/tensorflow_tests/test_tf_Ceil.py deleted file mode 100644 index c516a598b88f64..00000000000000 --- a/tests/layer_tests/tensorflow_tests/test_tf_Ceil.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import pytest - -from common.layer_test_class import check_ir_version -from common.tf_layer_test_class import CommonTFLayerTest -from unit_tests.utils.graph import build_graph - - -class TestCeil(CommonTFLayerTest): - def create_ceil_net(self, shape, ir_version): - """ - Tensorflow net IR net - - Input->Ceil => Input->Ceil - - """ - - # - # Create Tensorflow model - # - - import tensorflow as tf - - tf.compat.v1.reset_default_graph() - - # Create the graph and model - with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 3: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') - - tf.math.ceil(input, name='Operation') - - tf.compat.v1.global_variables_initializer() - tf_net = sess.graph_def - - ref_net = None - - if check_ir_version(10, None, ir_version): - nodes_attributes = { - 'input': {'kind': 'op', 'type': 'Parameter'}, - 'input_data': {'shape': shape, 'kind': 'data'}, - 'Ceiling': {'kind': 'op', 'type': 'Ceiling'}, - 'Ceiling_data': {'shape': shape, 'kind': 'data'}, - 'result': {'kind': 'op', 'type': 'Result'} - } - - ref_net = build_graph(nodes_attributes, - [('input', 'input_data'), - ('input_data', 'Ceiling'), - ('Ceiling', 'Ceiling_data'), - ('Ceiling_data', 'result') - ]) - - return tf_net, ref_net - - test_data_precommit = [dict(shape=[3, 2, 3, 7, 6])] - - @pytest.mark.parametrize("params", test_data_precommit) - @pytest.mark.precommit - def test_ceil_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_ceil_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) - - test_data = [dict(shape=[1]), - dict(shape=[2, 5]), - dict(shape=[5, 3, 7, 4]), - dict(shape=[3, 2, 3, 7, 6])] - - @pytest.mark.parametrize("params", test_data) - @pytest.mark.nightly - def test_ceil(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_ceil_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Concat.py b/tests/layer_tests/tensorflow_tests/test_tf_Concat.py index cfa6ca0e958c35..2fb5f54e84bc03 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Concat.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Concat.py @@ -4,10 +4,10 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest - +from common.utils.tf_utils import permute_nchw_to_nhwc class TestConcat(CommonTFLayerTest): - def create_concat_net(self, shape, axis, ir_version): + def create_concat_net(self, shape, axis, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -28,15 +28,14 @@ def create_concat_net(self, shape, axis, ir_version): ax = axis - input_shape_x = shape.copy() - # reshaping - if len(input_shape_x) >= 3: - input_shape_x.append(input_shape_x.pop(1)) + tf_x_shape = shape.copy() + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) # TODO: add concat with const inputs to check fusing (as in ONNX) - x = tf.compat.v1.placeholder(tf.float32, input_shape_x, 'Input') - y = tf.compat.v1.placeholder(tf.float32, input_shape_x, 'Input') # Input_1 in graph_def + x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') + y = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') # Input_1 in graph_def concat = tf.concat([x, y], axis=ax, name='Operation') concat_shape = concat.shape.as_list() @@ -50,14 +49,6 @@ def create_concat_net(self, shape, axis, ir_version): # Moreover, do not forget to validate ALL layer attributes!!! # - # Format axis to positive value - concat_ax = axis if axis >= 0 else axis + len(shape) - if len(shape) >= 3: - # Permute shape to (N,C,...) format and compute correct axis value - order = [0, len(concat_shape) - 1] + list(range(1, len(concat_shape) - 1)) - concat_shape = [concat_shape[i] for i in order] - concat_ax = order.index(concat_ax) - ref_net = None return tf_net, ref_net @@ -69,18 +60,18 @@ def create_concat_net(self, shape, axis, ir_version): @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_concat_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_concat_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_concat_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_concat_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [dict(shape=[1, 224], axis=0), dict(shape=[1, 224], axis=-1)] @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_concat_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_concat_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_concat_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_concat_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [pytest.param(dict(shape=[1, 3, 224], axis=0), marks=pytest.mark.xfail(reason="*-19053")), pytest.param(dict(shape=[1, 3, 224], axis=-1), marks=pytest.mark.xfail(reason="*-19053")), @@ -88,9 +79,9 @@ def test_concat_2D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_concat_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_concat_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_concat_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_concat_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [dict(shape=[1, 3, 100, 224], axis=0), dict(shape=[1, 3, 100, 224], axis=-1), @@ -99,9 +90,9 @@ def test_concat_3D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly @pytest.mark.precommit - def test_concat_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_concat_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_concat_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_concat_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [dict(shape=[1, 3, 50, 100, 224], axis=0), dict(shape=[1, 3, 50, 100, 224], axis=-1), @@ -109,6 +100,6 @@ def test_concat_4D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_concat_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_concat_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_concat_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_concat_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_ELU.py b/tests/layer_tests/tensorflow_tests/test_tf_ELU.py deleted file mode 100644 index 7e183cf9c3438d..00000000000000 --- a/tests/layer_tests/tensorflow_tests/test_tf_ELU.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import pytest -from common.layer_test_class import check_ir_version -from common.tf_layer_test_class import CommonTFLayerTest -from unit_tests.utils.graph import build_graph - - -class TestELU(CommonTFLayerTest): - def create_elu_net(self, shape, ir_version): - """ - Tensorflow net IR net - - Input->ELU => Input->ELU - - """ - - # - # Create Tensorflow model - # - - import tensorflow as tf - - tf.compat.v1.reset_default_graph() - - # Create the graph and model - with tf.compat.v1.Session() as sess: - - shapes = shape.copy() - # reshaping - if len(shapes) >= 4: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') - - tf.nn.elu(input, name='Operation') - - tf.compat.v1.global_variables_initializer() - tf_net = sess.graph_def - - # - # Create reference IR net - # Please, specify 'type': 'Input' for input node - # Moreover, do not forget to validate ALL layer attributes!!! - # - - ref_net = None - - if check_ir_version(10, None, ir_version): - nodes_attributes = { - 'input': {'kind': 'op', 'type': 'Parameter'}, - 'input_data': {'shape': shape, 'kind': 'data'}, - 'ELU': {'kind': 'op', 'type': 'Elu'}, - 'ELU_data': {'shape': shape, 'kind': 'data'}, - 'result': {'kind': 'op', 'type': 'Result'} - } - - ref_net = build_graph(nodes_attributes, - [('input', 'input_data'), - ('input_data', 'ELU'), - ('ELU', 'ELU_data'), - ('ELU_data', 'result') - ]) - - return tf_net, ref_net - - test_data_precommit = [dict(shape=[4, 6, 8, 10, 12])] - - @pytest.mark.parametrize("params", test_data_precommit) - @pytest.mark.precommit - def test_elu_precommit(self, params, ie_device, precision, ir_version, temp_dir): - if ie_device == 'GPU': - pytest.skip("5D tensors is not supported on GPU") - self._test(*self.create_elu_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) - - test_data = [dict(shape=[10, 12]), - dict(shape=[8, 10, 12]), - dict(shape=[6, 8, 10, 12]), - dict(shape=[4, 6, 8, 10, 12])] - - @pytest.mark.parametrize("params", test_data) - @pytest.mark.nightly - def test_elu(self, params, ie_device, precision, ir_version, temp_dir): - if ie_device == 'GPU': - pytest.skip("5D tensors is not supported on GPU") - self._test(*self.create_elu_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Eltwise.py b/tests/layer_tests/tensorflow_tests/test_tf_Eltwise.py index d6880f3e0a1e31..7277f044743f76 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Eltwise.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Eltwise.py @@ -4,10 +4,11 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestEltwise(CommonTFLayerTest): - def create_eltwise_net(self, shape, operation, ir_version): + def create_eltwise_net(self, shape, operation, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -26,13 +27,12 @@ def create_eltwise_net(self, shape, operation, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 4: - shapes.append(shapes.pop(1)) + tf_x_shape = shape.copy() - x = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') - y = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') # Input_1 in graph_def + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + + x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') + y = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') # Input_1 in graph_def if operation == 'sum': tf.add(x, y, name='Operation') @@ -62,9 +62,9 @@ def create_eltwise_net(self, shape, operation, ir_version): @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_eltwise(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_eltwise_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_eltwise(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_eltwise_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [] for operation in ['sum', 'max', 'mul']: @@ -72,8 +72,8 @@ def test_eltwise(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.precommit - def test_eltwise_5D_precommit(self, params, ie_device, precision, ir_version, temp_dir): + def test_eltwise_5D_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): if ie_device == 'GPU': pytest.skip("5D tensors is not supported on GPU") - self._test(*self.create_eltwise_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + self._test(*self.create_eltwise_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_FakeQuantize.py b/tests/layer_tests/tensorflow_tests/test_tf_FakeQuantize.py index d4d8fe91b845cb..501fe70cedf81d 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_FakeQuantize.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_FakeQuantize.py @@ -35,7 +35,7 @@ def _prepare_input(self, inputs_dict, kwargs): expected_nudged_input_max + expected_step ])} - def create_fake_quantize_net(self, il, ih, num_bits, narrow_range, nudged_il, nudged_ih, expected_step, ir_version): + def create_fake_quantize_net(self, il, ih, num_bits, narrow_range, nudged_il, nudged_ih, expected_step, ir_version, use_new_frontend): # original tf model import tensorflow as tf tf.compat.v1.reset_default_graph() @@ -50,7 +50,7 @@ def create_fake_quantize_net(self, il, ih, num_bits, narrow_range, nudged_il, nu # reference graph to compare with IR ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: levels = 2 ** num_bits - int(narrow_range) # data (shape, value) -> const (shape, vale) -> data (shape, no value) @@ -120,6 +120,6 @@ def create_fake_quantize_net(self, il, ih, num_bits, narrow_range, nudged_il, nu @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_fake_quantize(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_fake_quantize_net(**params, ir_version=ir_version), ie_device, precision, ir_version, - kwargs_to_prepare_input=params, temp_dir=temp_dir) + def test_fake_quantize(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_fake_quantize_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, + kwargs_to_prepare_input=params, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Floor.py b/tests/layer_tests/tensorflow_tests/test_tf_Floor.py deleted file mode 100644 index 9c47f1f5910bcc..00000000000000 --- a/tests/layer_tests/tensorflow_tests/test_tf_Floor.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import pytest - -from common.layer_test_class import check_ir_version -from common.tf_layer_test_class import CommonTFLayerTest -from unit_tests.utils.graph import build_graph - - -class TestFloor(CommonTFLayerTest): - def create_floor_net(self, shape, ir_version): - """ - Tensorflow net IR net - - Input->Floor => Input->Floor - - """ - - # - # Create Tensorflow model - # - - import tensorflow as tf - - tf.compat.v1.reset_default_graph() - - # Create the graph and model - with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 3: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') - - tf.floor(input, name='Operation') - - tf.compat.v1.global_variables_initializer() - tf_net = sess.graph_def - - ref_net = None - - if check_ir_version(10, None, ir_version): - nodes_attributes = { - 'input': {'kind': 'op', 'type': 'Parameter'}, - 'input_data': {'shape': shape, 'kind': 'data'}, - 'Floor': {'kind': 'op', 'type': 'Floor'}, - 'Floor_data': {'shape': shape, 'kind': 'data'}, - 'result': {'kind': 'op', 'type': 'Result'} - } - - ref_net = build_graph(nodes_attributes, - [('input', 'input_data'), - ('input_data', 'Floor'), - ('Floor', 'Floor_data'), - ('Floor_data', 'result') - ]) - - return tf_net, ref_net - - test_data_precommit = [dict(shape=[3, 2, 3, 7, 6])] - - @pytest.mark.parametrize("params", test_data_precommit) - @pytest.mark.precommit - def test_floor_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_floor_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) - - test_data = [dict(shape=[1]), - dict(shape=[2, 5]), - dict(shape=[5, 3, 7, 4]), - dict(shape=[3, 2, 3, 7, 6])] - - @pytest.mark.parametrize("params", test_data) - @pytest.mark.nightly - def test_floor(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_floor_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Gather.py b/tests/layer_tests/tensorflow_tests/test_tf_Gather.py index 403b33ab1a37af..955ce2c4d95899 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Gather.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Gather.py @@ -11,7 +11,7 @@ class TestGather(CommonTFLayerTest): def create_indices_constant(self): pass - def create_gather_net(self, data_shape, indices, axis, batch_dims, **kwargs): + def create_gather_net(self, data_shape, indices, axis, batch_dims, use_new_frontend, **kwargs): import tensorflow as tf tf.compat.v1.reset_default_graph() @@ -36,9 +36,9 @@ def create_gather_net(self, data_shape, indices, axis, batch_dims, **kwargs): @pytest.mark.parametrize("params", test_data_precommit) @pytest.mark.precommit - def test_gather(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_gather_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_gather(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_gather_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_nightly = [ dict(data_shape=[2, 3], axis=1, indices=[0, 2], batch_dims=0), @@ -56,6 +56,6 @@ def test_gather(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_nightly) @pytest.mark.nightly - def test_gather_nightly(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_gather_net(**params), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_gather_nightly(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_gather_net(**params, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Identity.py b/tests/layer_tests/tensorflow_tests/test_tf_Identity.py index 6e963e85c4e766..3858249ef6afd5 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Identity.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Identity.py @@ -5,11 +5,12 @@ from common.layer_test_class import check_ir_version from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc from unit_tests.utils.graph import build_graph class TestIdentity(CommonTFLayerTest): - def create_identity_net(self, shape, ir_version): + def create_identity_net(self, shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -27,12 +28,11 @@ def create_identity_net(self, shape, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: - x_shape = shape.copy() - # reshaping - if len(x_shape) >= 3: - x_shape.append(x_shape.pop(1)) + tf_x_shape = shape.copy() - x = tf.compat.v1.placeholder(tf.float32, x_shape, 'Input') + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + + x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') id = tf.identity(x, name="Operation") tf.nn.relu(id, name='Operation') @@ -47,7 +47,7 @@ def create_identity_net(self, shape, ir_version): ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: nodes_attributes = { 'inputX': {'kind': 'op', 'type': 'Parameter'}, 'inputX_data': {'shape': shape, 'kind': 'data'}, @@ -68,9 +68,9 @@ def create_identity_net(self, shape, ir_version): @pytest.mark.parametrize("params", test_data_precommit) @pytest.mark.precommit - def test_identity_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_identity_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_identity_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_identity_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data = [dict(shape=[1]), dict(shape=[1, 224]), @@ -80,6 +80,6 @@ def test_identity_precommit(self, params, ie_device, precision, ir_version, temp @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_identity(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_identity_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_identity(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_identity_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Log.py b/tests/layer_tests/tensorflow_tests/test_tf_Log.py deleted file mode 100644 index f979071395183e..00000000000000 --- a/tests/layer_tests/tensorflow_tests/test_tf_Log.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import pytest - -from common.layer_test_class import check_ir_version -from common.tf_layer_test_class import CommonTFLayerTest -from unit_tests.utils.graph import build_graph - - -class TestLog(CommonTFLayerTest): - def create_log_net(self, shape, ir_version): - """ - Tensorflow net IR net - - Input->Log => Input->Log - - """ - - # - # Create Tensorflow model - # - - import tensorflow as tf - - tf.compat.v1.reset_default_graph() - - # Create the graph and model - with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 3: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') - - tf.math.log(input, name='Operation') - - tf.compat.v1.global_variables_initializer() - tf_net = sess.graph_def - - ref_net = None - - if check_ir_version(10, None, ir_version): - nodes_attributes = { - 'input': {'kind': 'op', 'type': 'Parameter'}, - 'input_data': {'shape': shape, 'kind': 'data'}, - 'log': {'kind': 'op', 'type': 'Log'}, - 'log_data': {'shape': shape, 'kind': 'data'}, - 'result': {'kind': 'op', 'type': 'Result'} - } - - ref_net = build_graph(nodes_attributes, - [('input', 'input_data'), - ('input_data', 'log'), - ('log', 'log_data'), - ('log_data', 'result') - ]) - - return tf_net, ref_net - - test_data_precommit = [ - pytest.param(dict(shape=[3, 2, 3, 7, 6]), marks=pytest.mark.skip(reason="Skipped until fixed"))] - - @pytest.mark.parametrize("params", test_data_precommit) - @pytest.mark.precommit - def test_log_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_log_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) - - test_data = [dict(shape=[1]), - dict(shape=[2, 5]), - dict(shape=[5, 3, 7, 4]), - dict(shape=[3, 2, 3, 7, 6])] - - @pytest.mark.parametrize("params", test_data) - @pytest.mark.nightly - def test_log(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_log_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_LogSoftmax.py b/tests/layer_tests/tensorflow_tests/test_tf_LogSoftmax.py index 8cb3087cc3e2fc..35219b88f7abd7 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_LogSoftmax.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_LogSoftmax.py @@ -7,12 +7,13 @@ import pytest from common.layer_test_class import check_ir_version from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc from mo.front.common.partial_infer.utils import int64_array from unit_tests.utils.graph import build_graph class TestLogSoftmax(CommonTFLayerTest): - def create_log_softmax_net(self, shape, reduction_axis, ir_version): + def create_log_softmax_net(self, shape, reduction_axis, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -30,11 +31,10 @@ def create_log_softmax_net(self, shape, reduction_axis, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 3: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') + tf_x_shape = shape.copy() + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + input = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') if LooseVersion(tf.__version__) < LooseVersion('2.0.0'): tf.nn.log_softmax(input, name='Operation', axis=reduction_axis) else: @@ -57,7 +57,7 @@ def create_log_softmax_net(self, shape, reduction_axis, ir_version): reduce_sum_shape[reduction_axis] = 1 converted_shape = shape if rank != 1 else shape[0] - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: ref_nodes_attributes = { 'input': {'kind': 'op', 'type': 'Parameter', 'shape': converted_shape}, 'input_data': {'shape': shape, 'kind': 'data', 'value': None}, @@ -122,9 +122,9 @@ def create_log_softmax_net(self, shape, reduction_axis, ir_version): @pytest.mark.parametrize("params", test_data_precommit) @pytest.mark.precommit - def test_log_softmax_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_log_softmax_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_log_softmax_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_log_softmax_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data = [dict(shape=[1], reduction_axis=-1), dict(shape=[2, 5], reduction_axis=-1), @@ -133,6 +133,6 @@ def test_log_softmax_precommit(self, params, ie_device, precision, ir_version, t @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_log_softmax(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_log_softmax_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_log_softmax(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_log_softmax_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Mul.py b/tests/layer_tests/tensorflow_tests/test_tf_Mul.py index a877e639d6571a..8fbec72ec7f5dc 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Mul.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Mul.py @@ -5,10 +5,11 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestMul(CommonTFLayerTest): - def create_mul_placeholder_const_net(self, x_shape, y_shape, ir_version): + def create_mul_placeholder_const_net(self, x_shape, y_shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -30,11 +31,9 @@ def create_mul_placeholder_const_net(self, x_shape, y_shape, ir_version): with tf.compat.v1.Session() as sess: tf_x_shape = x_shape.copy() tf_y_shape = y_shape.copy() - # reshaping - if len(tf_x_shape) >= 3: - tf_x_shape.append(tf_x_shape.pop(1)) - if len(tf_y_shape) >= 3: - tf_y_shape.append(tf_y_shape.pop(1)) + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + tf_y_shape = permute_nchw_to_nhwc(tf_y_shape, use_new_frontend) x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') constant_value = np.random.randint(-255, 255, tf_y_shape).astype(np.float32) @@ -44,7 +43,6 @@ def create_mul_placeholder_const_net(self, x_shape, y_shape, ir_version): y = tf.constant(constant_value) mul = tf.multiply(x, y, name="Operation") - mul_shape = mul.shape.as_list() tf.compat.v1.global_variables_initializer() tf_net = sess.graph_def @@ -55,23 +53,6 @@ def create_mul_placeholder_const_net(self, x_shape, y_shape, ir_version): # Moreover, do not forget to validate ALL layer attributes!!! # - if len(mul_shape) >= 3: - # Permute mul_shape to (N,C,...) format - order = [0, len(mul_shape) - 1] + list(range(1, len(mul_shape) - 1)) - mul_shape = [mul_shape[i] for i in order] - - y_shape_to_compare = tf_y_shape.copy() - while len(y_shape_to_compare) < len(x_shape): - # Expand shape of constant with 1 - y_shape_to_compare = [1] + y_shape_to_compare - constant_value = np.expand_dims(constant_value, axis=0) - - if len(y_shape_to_compare) >= 3: - # Permute constant_value to (N,C,...) format for correct further reshape - order = [0, len(y_shape_to_compare) - 1] + list(range(1, len(y_shape_to_compare) - 1)) - y_shape_to_compare = [y_shape_to_compare[i] for i in order] - constant_value = np.transpose(constant_value, order) - ref_net = None return tf_net, ref_net @@ -87,9 +68,9 @@ def create_mul_placeholder_const_net(self, x_shape, y_shape, ir_version): @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_mul_placeholder_const_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [ # Power @@ -104,9 +85,9 @@ def test_mul_placeholder_const_1D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_mul_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ # Power @@ -122,9 +103,9 @@ def test_mul_placeholder_const_2D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_mul_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ # Power @@ -139,9 +120,9 @@ def test_mul_placeholder_const_3D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_mul_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ # Power @@ -158,9 +139,9 @@ def test_mul_placeholder_const_4D(self, params, ie_device, precision, ir_version # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_mul_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) ############################################################################################### # # @@ -174,9 +155,9 @@ def test_mul_placeholder_const_5D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_broadcast_1D) @pytest.mark.nightly - def test_mul_placeholder_const_broadcast_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_broadcast_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_2D = [ # Power @@ -193,9 +174,9 @@ def test_mul_placeholder_const_broadcast_1D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_2D) @pytest.mark.nightly - def test_mul_placeholder_const_broadcast_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_broadcast_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_3D = [ # Power @@ -217,9 +198,9 @@ def test_mul_placeholder_const_broadcast_2D(self, params, ie_device, precision, # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_broadcast_3D) @pytest.mark.nightly - def test_mul_placeholder_const_broadcast_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_broadcast_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_4D = [ # Power @@ -235,9 +216,9 @@ def test_mul_placeholder_const_broadcast_3D(self, params, ie_device, precision, # Eltwise dict(x_shape=[1, 3, 1, 1], y_shape=[3, 1]), # Eltwise - dict(x_shape=[1, 3, 1, 2], y_shape=[3, 1, 2]), + dict(x_shape=[1, 2, 1, 3], y_shape=[3, 1, 2]), # Eltwise - dict(x_shape=[1, 3, 1, 2], y_shape=[1, 3, 2]), + dict(x_shape=[1, 2, 1, 3], y_shape=[1, 3, 2]), # Eltwise dict(x_shape=[1, 3, 100, 224], y_shape=[1, 1, 1, 224]), # Eltwise @@ -247,9 +228,9 @@ def test_mul_placeholder_const_broadcast_3D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_4D) @pytest.mark.nightly @pytest.mark.precommit - def test_mul_placeholder_const_broadcast_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_broadcast_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_5D = [ # Power @@ -274,6 +255,6 @@ def test_mul_placeholder_const_broadcast_4D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_5D) @pytest.mark.nightly - def test_mul_placeholder_const_broadcast_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_mul_placeholder_const_broadcast_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_mul_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_NormalizeL2.py b/tests/layer_tests/tensorflow_tests/test_tf_NormalizeL2.py index 1dc4b914172645..00217ead0d9daf 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_NormalizeL2.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_NormalizeL2.py @@ -7,7 +7,7 @@ from common.tf_layer_test_class import CommonTFLayerTest from mo.front.common.partial_infer.utils import int64_array from unit_tests.utils.graph import build_graph -from tensorflow_tests.permutation_utils import permute_nchw_to_nhwc, permute_nhwc_to_nchw +from common.utils.tf_utils import permute_nchw_to_nhwc, permute_nchw_to_nhwc class TestNormalizeL2(CommonTFLayerTest): @@ -33,7 +33,7 @@ def build_tf_graph(shape, axes): return tf_net @staticmethod - def create_normalize_l2_net_fusable(shape, axes, output_axes, ir_version): + def create_normalize_l2_net_fusable(shape, axes, output_axes, ir_version, use_new_frontend): tf_net = TestNormalizeL2.build_tf_graph(shape, axes) nodes_attributes = { @@ -57,16 +57,18 @@ def create_normalize_l2_net_fusable(shape, axes, output_axes, ir_version): ('normalize_l2_data', 'result'), ]) + if use_new_frontend: + ref_net = None return tf_net, ref_net @staticmethod - def create_normalize_l2_net_non_fusable(shape, axes, output_axes, ir_version): + def create_normalize_l2_net_non_fusable(shape, axes, output_axes, ir_version, use_new_frontend): tf_net = TestNormalizeL2.build_tf_graph(shape, axes) reduced_shape = permute_nchw_to_nhwc(shape).copy() for axis in axes: reduced_shape[axis] = 1 - reduced_shape = permute_nhwc_to_nchw(reduced_shape) + reduced_shape = permute_nchw_to_nhwc(reduced_shape) eltwise_shapes = int64_array(np.ones(len(shape))) nodes_attributes = { @@ -136,6 +138,8 @@ def create_normalize_l2_net_non_fusable(shape, axes, output_axes, ir_version): ('multiply_data', 'result'), ]) + if use_new_frontend: + ref_net = None return tf_net, ref_net test_data_fusable_precommit = [ @@ -147,9 +151,9 @@ def create_normalize_l2_net_non_fusable(shape, axes, output_axes, ir_version): @pytest.mark.parametrize("params", test_data_fusable_precommit) @pytest.mark.precommit - def test_NormalizeL2_fusable_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_normalize_l2_net_fusable(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_NormalizeL2_fusable_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_normalize_l2_net_fusable(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_non_fusable_precommit = [ pytest.param(dict(shape=[2, 3, 5], axes=[0, 1, 2], output_axes=[0, 1, 2]), @@ -162,10 +166,10 @@ def test_NormalizeL2_fusable_precommit(self, params, ie_device, precision, ir_ve @pytest.mark.parametrize("params", test_data_non_fusable_precommit) @pytest.mark.precommit - def test_NormalizeL2_non_fusable_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_normalize_l2_net_non_fusable(**params, ir_version=ir_version), + def test_NormalizeL2_non_fusable_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_normalize_l2_net_non_fusable(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_fusable = [ dict(shape=[5, 6], axes=[1], output_axes=[1]), @@ -178,9 +182,9 @@ def test_NormalizeL2_non_fusable_precommit(self, params, ie_device, precision, i @pytest.mark.parametrize("params", test_data_fusable) @pytest.mark.nightly - def test_NormalizeL2_fusable(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_normalize_l2_net_fusable(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_NormalizeL2_fusable(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_normalize_l2_net_fusable(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_non_fusable = [ dict(shape=[5], axes=[0], output_axes=[0]), @@ -201,7 +205,7 @@ def test_NormalizeL2_fusable(self, params, ie_device, precision, ir_version, tem @pytest.mark.parametrize("params", test_data_non_fusable) @pytest.mark.nightly - def test_NormalizeL2_non_fusable(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_normalize_l2_net_non_fusable(**params, ir_version=ir_version), + def test_NormalizeL2_non_fusable(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_normalize_l2_net_non_fusable(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_OneHot.py b/tests/layer_tests/tensorflow_tests/test_tf_OneHot.py index 5e2d1d9131bf6b..feff58c11526f5 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_OneHot.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_OneHot.py @@ -4,12 +4,12 @@ import numpy as np import pytest from common.tf_layer_test_class import CommonTFLayerTest -from tensorflow_tests.permutation_utils import permute_nchw_to_nhwc +from common.utils.tf_utils import permute_nchw_to_nhwc class TestOneHot(CommonTFLayerTest): @staticmethod - def create_one_hot_net(shape, depth, on_value, off_value, axis, ir_version): + def create_one_hot_net(shape, depth, on_value, off_value, axis, ir_version, use_new_frontend): """ Tensorflow net @@ -53,13 +53,6 @@ def create_one_hot_net(shape, depth, on_value, off_value, axis, ir_version): # Create reference IR net # - if on_value is None: - on_value = 1.0 - if off_value is None: - off_value = 0.0 - - axis = len(shape) if axis is None else axis - ref_net = None return tf_net, ref_net @@ -71,9 +64,9 @@ def create_one_hot_net(shape, depth, on_value, off_value, axis, ir_version): @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_OneHot_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_one_hot_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_OneHot_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_one_hot_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [ dict(shape=[5, 6], depth=7, on_value=None, off_value=None, axis=None), @@ -90,9 +83,9 @@ def test_OneHot_1D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_OneHot_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_one_hot_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_OneHot_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_one_hot_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ dict(shape=[5, 6, 7], depth=8, on_value=None, off_value=None, axis=None), @@ -110,9 +103,9 @@ def test_OneHot_2D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_OneHot_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_one_hot_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_OneHot_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_one_hot_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ dict(shape=[5, 6, 7, 8], depth=9, on_value=None, off_value=None, axis=None), @@ -132,9 +125,9 @@ def test_OneHot_3D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly @pytest.mark.precommit - def test_OneHot_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_one_hot_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_OneHot_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_one_hot_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ dict(shape=[4, 5, 6, 7, 8], depth=9, on_value=None, off_value=None, axis=None), @@ -154,6 +147,6 @@ def test_OneHot_4D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_OneHot_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_one_hot_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_OneHot_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_one_hot_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Pooling.py b/tests/layer_tests/tensorflow_tests/test_tf_Pooling.py index 3074ccad19d6bb..4b236d868aacb5 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Pooling.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Pooling.py @@ -8,7 +8,7 @@ class TestPooling(CommonTFLayerTest): - def create_pooling_net(self, kernel_size, strides, pads, in_shape, out_shape, method, ir_version): + def create_pooling_net(self, kernel_size, strides, pads, in_shape, out_shape, method, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -66,7 +66,7 @@ def create_pooling_net(self, kernel_size, strides, pads, in_shape, out_shape, me ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: nodes_attributes = { 'input': {'kind': 'op', 'type': 'Parameter'}, 'input_data': {'shape': in_shape, 'kind': 'data'}, @@ -156,9 +156,9 @@ def create_pooling_net(self, kernel_size, strides, pads, in_shape, out_shape, me @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_pool_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_pooling_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_pool_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_pooling_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [] for method in ['max', 'avg']: @@ -229,8 +229,8 @@ def test_pool_4D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_pool_5D(self, params, ie_device, precision, ir_version, temp_dir): + def test_pool_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): if ie_device == 'GPU': pytest.skip("5D tensors is not supported on GPU") - self._test(*self.create_pooling_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + self._test(*self.create_pooling_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_RandomUniform.py b/tests/layer_tests/tensorflow_tests/test_tf_RandomUniform.py index 400ea147524cd0..347c092cddfa8f 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_RandomUniform.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_RandomUniform.py @@ -9,23 +9,23 @@ from common.layer_test_class import check_ir_version from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestTFRandomUniform(CommonTFLayerTest): def create_tf_random_uniform_net(self, global_seed, op_seed, x_shape, min_val, max_val, input_type, precision, - ir_version): + ir_version, use_new_frontend): tf.compat.v1.reset_default_graph() # Create the graph and model with tf.compat.v1.Session() as sess: tf_x_shape = x_shape.copy() - # reshaping - if len(tf_x_shape) >= 3: - tf_x_shape.append(tf_x_shape.pop(1)) - x = tf.compat.v1.placeholder(input_type, x_shape, 'Input') + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + + x = tf.compat.v1.placeholder(input_type, tf_x_shape, 'Input') if global_seed is not None: - tf.random.set_seed(global_seed) + tf.compat.v1.random.set_random_seed(global_seed) random_uniform = tf.random.uniform(x_shape, seed=op_seed, dtype=input_type, minval=min_val, maxval=max_val) + x @@ -33,7 +33,7 @@ def create_tf_random_uniform_net(self, global_seed, op_seed, x_shape, min_val, m tf_net = sess.graph_def ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: const_for_layer_tests = lambda name, value, shape, shape1: { **{name + '_dd': {'kind': 'data', 'value': value, 'shape': shape1}}, @@ -86,8 +86,9 @@ def create_tf_random_uniform_net(self, global_seed, op_seed, x_shape, min_val, m @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_tf_random_uniform(self, params, ie_device, precision, ir_version, temp_dir): + def test_tf_random_uniform(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): if ie_device == 'GPU': pytest.skip("RandomUniform is not supported on GPU") - self._test(*self.create_tf_random_uniform_net(**params, precision=precision, ir_version=ir_version), ie_device, - precision, temp_dir=temp_dir, ir_version=ir_version, **params) + self._test(*self.create_tf_random_uniform_net(**params, precision=precision, ir_version=ir_version, + use_new_frontend=use_new_frontend), ie_device, + precision, temp_dir=temp_dir, ir_version=ir_version, use_new_frontend=use_new_frontend, **params) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_ReLU.py b/tests/layer_tests/tensorflow_tests/test_tf_ReLU.py deleted file mode 100644 index c178e6f8b55aef..00000000000000 --- a/tests/layer_tests/tensorflow_tests/test_tf_ReLU.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import pytest - -from common.layer_test_class import check_ir_version -from common.tf_layer_test_class import CommonTFLayerTest -from unit_tests.utils.graph import build_graph - - -class TestReLU(CommonTFLayerTest): - def create_relu_net(self, shape, ir_version): - """ - Tensorflow net IR net - - Input->ReLU => Input->ReLU - - """ - - # - # Create Tensorflow model - # - - import tensorflow as tf - - tf.compat.v1.reset_default_graph() - - # Create the graph and model - with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 3: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') - - tf.nn.relu(input, name='Operation') - - tf.compat.v1.global_variables_initializer() - tf_net = sess.graph_def - - # - # Create reference IR net - # Please, specify 'type': 'Input' for input node - # Moreover, do not forget to validate ALL layer attributes!!! - # - - ref_net = None - - if check_ir_version(10, None, ir_version): - nodes_attributes = { - 'input': {'kind': 'op', 'type': 'Parameter'}, - 'input_data': {'shape': shape, 'kind': 'data'}, - 'ReLU': {'kind': 'op', 'type': 'ReLU'}, - 'ReLU_data': {'shape': shape, 'kind': 'data'}, - 'result': {'kind': 'op', 'type': 'Result'} - } - - ref_net = build_graph(nodes_attributes, - [('input', 'input_data'), - ('input_data', 'ReLU'), - ('ReLU', 'ReLU_data'), - ('ReLU_data', 'result') - ]) - - return tf_net, ref_net - - test_data_precommit = [dict(shape=[1, 3, 50, 100, 224])] - - @pytest.mark.parametrize("params", test_data_precommit) - @pytest.mark.precommit - def test_relu_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_relu_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) - - test_data = [dict(shape=[1]), - dict(shape=[1, 224]), - pytest.param(dict(shape=[1, 3, 224]), marks=pytest.mark.xfail(reason="*-19053")), - dict(shape=[1, 3, 100, 224]), - dict(shape=[1, 3, 50, 100, 224])] - - @pytest.mark.parametrize("params", test_data) - @pytest.mark.nightly - def test_relu(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_relu_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_ReLU6.py b/tests/layer_tests/tensorflow_tests/test_tf_ReLU6.py index fd846a82358428..e0db2713f9137b 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_ReLU6.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_ReLU6.py @@ -5,11 +5,12 @@ from common.layer_test_class import check_ir_version from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc from unit_tests.utils.graph import build_graph class TestReLU6(CommonTFLayerTest): - def create_relu6_net(self, shape, ir_version): + def create_relu6_net(self, shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -27,11 +28,10 @@ def create_relu6_net(self, shape, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 3: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') + tf_x_shape = shape.copy() + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + input = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') tf.nn.relu6(input, name='Operation') @@ -46,7 +46,7 @@ def create_relu6_net(self, shape, ir_version): ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: nodes_attributes = { 'input': {'kind': 'op', 'type': 'Parameter'}, 'input_data': {'shape': shape, 'kind': 'data'}, @@ -68,9 +68,9 @@ def create_relu6_net(self, shape, ir_version): @pytest.mark.parametrize("params", test_data_precommit) @pytest.mark.precommit - def test_relu6_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_relu6_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_relu6_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_relu6_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data = [dict(shape=[1]), dict(shape=[1, 224]), @@ -80,6 +80,6 @@ def test_relu6_precommit(self, params, ie_device, precision, ir_version, temp_di @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_relu6(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_relu6_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_relu6(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_relu6_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Reduce.py b/tests/layer_tests/tensorflow_tests/test_tf_Reduce.py index 53341943943606..3830c6504b79ba 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Reduce.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Reduce.py @@ -5,6 +5,7 @@ import numpy as np from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestReduceOps(CommonTFLayerTest): @@ -13,7 +14,7 @@ def _prepare_input(self, inputs_dict): inputs_dict[input] = np.random.random(inputs_dict[input]) return inputs_dict - def create_reduce_net(self, shape, operation, keep_dims, axis, ir_version): + def create_reduce_net(self, shape, operation, keep_dims, axis, ir_version, use_new_frontend): import tensorflow as tf fn_mapping = {'sum': tf.reduce_sum, 'max': tf.reduce_max, @@ -23,11 +24,10 @@ def create_reduce_net(self, shape, operation, keep_dims, axis, ir_version): } tf.compat.v1.reset_default_graph() with tf.compat.v1.Session() as sess: - shapes = shape.copy() - if len(shapes) >= 4: - shapes.append(shapes.pop(1)) + tf_x_shape = shape.copy() + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) - x = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') + x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') fn_mapping[operation](x, axis=axis, keepdims=keep_dims, name='Operation') tf.compat.v1.global_variables_initializer() tf_net = sess.graph_def @@ -46,9 +46,9 @@ def create_reduce_net(self, shape, operation, keep_dims, axis, ir_version): @pytest.mark.parametrize("params", test_data) @pytest.mark.parametrize("keep_dims", [True, False]) @pytest.mark.nightly - def test_reduce(self, params, keep_dims, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_reduce_net(**params, keep_dims=keep_dims, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_reduce(self, params, keep_dims, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_reduce_net(**params, keep_dims=keep_dims, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_pre_commit = [] for operation in ['sum', 'max', 'prod', 'min', 'mean']: @@ -58,6 +58,6 @@ def test_reduce(self, params, keep_dims, ie_device, precision, ir_version, temp_ @pytest.mark.parametrize("params", test_data_pre_commit) @pytest.mark.parametrize("keep_dims", [False]) @pytest.mark.precommit - def test_reduce_precommit(self, params, keep_dims, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_reduce_net(**params, keep_dims=keep_dims, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_reduce_precommit(self, params, keep_dims, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_reduce_net(**params, keep_dims=keep_dims, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Resample_pattern_new.py b/tests/layer_tests/tensorflow_tests/test_tf_Resample_pattern_new.py index e3afdda6972d02..6d2aa2ff24fee7 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Resample_pattern_new.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Resample_pattern_new.py @@ -14,7 +14,7 @@ def _prepare_input(self, inputs_dict): inputs_dict[input] = np.random.randint(1, 256, inputs_dict[input]).astype(np.float32) return inputs_dict - def create_resample_net(self, shape, factor): + def create_resample_net(self, shape, factor, use_new_frontend): """ The sub-graph in TF that could be expressed as a single Resample operation. """ @@ -29,10 +29,10 @@ def create_resample_net(self, shape, factor): # Create the graph and model with tf.compat.v1.Session() as sess: - tf_shape = shape.copy() - tf_shape = np.array(tf_shape)[[0, 2, 3, 1]] + tf_x_shape = shape.copy() + tf_x_shape = np.array(tf_x_shape)[[0, 2, 3, 1]] - input = tf.compat.v1.placeholder(tf.float32, tf_shape, 'Input') + input = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') transpose_1 = tf.transpose(a=input, perm=[1, 2, 3, 0]) expand_dims = tf.expand_dims(transpose_1, 0) @@ -50,22 +50,24 @@ def create_resample_net(self, shape, factor): # Moreover, do not forget to validate ALL layer attributes!!! # - new_shape = shape.copy() - new_shape[2] *= factor - new_shape[3] *= factor - nodes_attributes = { - 'input': {'kind': 'op', 'type': 'Input'}, - 'input_data': {'shape': shape, 'kind': 'data'}, - 'resample': {'kind': 'op', 'type': 'caffe.ResampleParameter.NEAREST', "factor": factor, - "height": 0, "width": 0, "antialias": 0}, - 'resample_data': {'shape': new_shape, 'kind': 'data'}, - } - - ref_net = build_graph(nodes_attributes, - [('input', 'input_data'), - ('input_data', 'resample'), - ('resample', 'resample_data') - ]) + ref_net = None + if not use_new_frontend: + new_shape = shape.copy() + new_shape[2] *= factor + new_shape[3] *= factor + nodes_attributes = { + 'input': {'kind': 'op', 'type': 'Input'}, + 'input_data': {'shape': shape, 'kind': 'data'}, + 'resample': {'kind': 'op', 'type': 'caffe.ResampleParameter.NEAREST', "factor": factor, + "height": 0, "width": 0, "antialias": 0}, + 'resample_data': {'shape': new_shape, 'kind': 'data'}, + } + + ref_net = build_graph(nodes_attributes, + [('input', 'input_data'), + ('input_data', 'resample'), + ('resample', 'resample_data') + ]) return tf_net, ref_net @@ -76,6 +78,6 @@ def create_resample_net(self, shape, factor): @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly @pytest.mark.xfail(reason="*-22273") - def test_resample(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_resample_net(params['shape'], params['factor']), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_resample(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_resample_net(params['shape'], params['factor'], use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Roll.py b/tests/layer_tests/tensorflow_tests/test_tf_Roll.py index 340adcc1eca60a..585bf5367ae578 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Roll.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Roll.py @@ -1,18 +1,18 @@ import pytest import tensorflow as tf from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestTFRoll(CommonTFLayerTest): - def create_tf_roll_net(self, shift, axis, x_shape, input_type, ir_version): + def create_tf_roll_net(self, shift, axis, x_shape, input_type, ir_version, use_new_frontend): tf.compat.v1.reset_default_graph() # Create the graph and model with tf.compat.v1.Session() as sess: tf_x_shape = x_shape.copy() - # reshaping - if len(tf_x_shape) >= 3: - tf_x_shape.append(tf_x_shape.pop(1)) + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) x = tf.compat.v1.placeholder(input_type, tf_x_shape, 'Input') roll = tf.roll(x, shift=shift, axis=axis) @@ -35,8 +35,8 @@ def create_tf_roll_net(self, shift, axis, x_shape, input_type, ir_version): @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_tf_roll(self, params, ie_device, precision, ir_version, temp_dir): + def test_tf_roll(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): if ie_device == 'GPU': pytest.skip("Roll is not supported on GPU") - self._test(*self.create_tf_roll_net(**params, ir_version=ir_version), ie_device, precision, - temp_dir=temp_dir, ir_version=ir_version, **params) + self._test(*self.create_tf_roll_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, + temp_dir=temp_dir, ir_version=ir_version, **params, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Rsqrt.py b/tests/layer_tests/tensorflow_tests/test_tf_Rsqrt.py index 953d73f6809b3a..c8013ae4010d17 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Rsqrt.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Rsqrt.py @@ -5,6 +5,7 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestRsqrt(CommonTFLayerTest): @@ -13,7 +14,7 @@ def _prepare_input(self, inputs_dict): inputs_dict[input] = np.random.randint(1, 256, inputs_dict[input]).astype(np.float32) return inputs_dict - def create_rsqrt_net(self, shape, ir_version): + def create_rsqrt_net(self, shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -31,11 +32,10 @@ def create_rsqrt_net(self, shape, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) >= 3: - shapes.append(shapes.pop(1)) - input = tf.compat.v1.placeholder(tf.float32, shapes, 'Input') + tf_x_shape = shape.copy() + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + input = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') tf.math.rsqrt(input, name='Operation') @@ -56,9 +56,9 @@ def create_rsqrt_net(self, shape, ir_version): @pytest.mark.parametrize("params", test_data_precommit) @pytest.mark.precommit - def test_rsqrt_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_rsqrt_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_rsqrt_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_rsqrt_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data = [dict(shape=[1]), dict(shape=[1, 224]), @@ -68,6 +68,6 @@ def test_rsqrt_precommit(self, params, ie_device, precision, ir_version, temp_di @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_rsqrt(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_rsqrt_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_rsqrt(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_rsqrt_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Select.py b/tests/layer_tests/tensorflow_tests/test_tf_Select.py index ee24964589b494..365ddf471a9142 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Select.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Select.py @@ -4,11 +4,11 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest -from tensorflow_tests.permutation_utils import permute_nchw_to_nhwc +from common.utils.tf_utils import permute_nchw_to_nhwc class TestSelect(CommonTFLayerTest): - def create_select_net(self, shape_condition, shape_input, ir_version): + def create_select_net(self, shape_condition, shape_input, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -56,9 +56,9 @@ def create_select_net(self, shape_condition, shape_input, ir_version): @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_select_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_select_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_select_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_select_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [ dict(shape_condition=[2], shape_input=[2, 3]), @@ -67,9 +67,9 @@ def test_select_1D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_select_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_select_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_select_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_select_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ dict(shape_condition=[3], shape_input=[3, 4, 5]), @@ -78,9 +78,9 @@ def test_select_2D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_select_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_select_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_select_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_select_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ dict(shape_condition=[3], shape_input=[3, 4, 5, 6]), @@ -90,9 +90,9 @@ def test_select_3D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly @pytest.mark.precommit - def test_select_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_select_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_select_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_select_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ dict(shape_condition=[3], shape_input=[3, 4, 5, 6, 7]), @@ -102,6 +102,6 @@ def test_select_4D(self, params, ie_device, precision, ir_version, temp_dir): # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_select_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_select_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_select_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_select_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Softplus.py b/tests/layer_tests/tensorflow_tests/test_tf_Softplus.py deleted file mode 100644 index a295e4660e9174..00000000000000 --- a/tests/layer_tests/tensorflow_tests/test_tf_Softplus.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (C) 2018-2021 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -import pytest - -from common.layer_test_class import check_ir_version -from common.tf_layer_test_class import CommonTFLayerTest -from unit_tests.utils.graph import build_graph - - -class TestSoftplus(CommonTFLayerTest): - def create_softplus_net(self, shape, ir_version): - """ - Tensorflow net IR net - - Input->Softplus => Input->Softplus - - """ - - # - # Create Tensorflow model - # - - import tensorflow as tf - - tf.reset_default_graph() - - # Create the graph and model - with tf.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) > 3: - shapes.append(shapes.pop(1)) - input = tf.placeholder(tf.float32, shapes, 'Input') - - tf.math.softplus(input, name='Operation') - - tf.global_variables_initializer() - tf_net = sess.graph_def - - # - # Create reference IR net - # Please, specify 'type': 'Input' for input node - # Moreover, do not forget to validate ALL layer attributes!!! - # - - ref_net = None - - if check_ir_version(10, None, ir_version): - nodes_attributes = { - 'input': {'kind': 'op', 'type': 'Parameter'}, - 'input_data': {'shape': shape, 'kind': 'data'}, - 'Softplus': {'kind': 'op', 'type': 'SoftPlus'}, - 'Softplus_data': {'shape': shape, 'kind': 'data'}, - 'result': {'kind': 'op', 'type': 'Result'} - } - - ref_net = build_graph(nodes_attributes, - [('input', 'input_data'), - ('input_data', 'Softplus'), - ('Softplus', 'Softplus_data'), - ('Softplus_data', 'result') - ]) - - return tf_net, ref_net - - test_data_precommit = [ - pytest.param(dict(shape=[1, 3, 100, 224]), - marks=pytest.mark.skip(reason="Skipped until fixed")), - pytest.param(dict(shape=[1, 3, 50, 100, 224]), - marks=pytest.mark.skip(reason="Skipped until fixed")) - ] - - @pytest.mark.parametrize("params", test_data_precommit) - @pytest.mark.precommit - def test_softplus_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_softplus_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) - - test_data = [dict(shape=[1]), - dict(shape=[1, 224]), - dict(shape=[1, 3, 224]), - dict(shape=[1, 3, 100, 224]), - dict(shape=[1, 3, 50, 100, 224])] - - @pytest.mark.parametrize("params", test_data) - @pytest.mark.nightly - def test_softplus(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_softplus_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_SpaceToBatch.py b/tests/layer_tests/tensorflow_tests/test_tf_SpaceToBatch.py index f86ab7dc2acf21..df22d3ed543d3d 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_SpaceToBatch.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_SpaceToBatch.py @@ -7,7 +7,7 @@ class TestSpaceToBatch(CommonTFLayerTest): - def create_space_to_batch_net(self, in_shape, pads_value, block_shape_value, out_shape, ir_version): + def create_space_to_batch_net(self, in_shape, pads_value, block_shape_value, out_shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -28,7 +28,7 @@ def create_space_to_batch_net(self, in_shape, pads_value, block_shape_value, out x = tf.compat.v1.placeholder(tf.float32, in_shape, 'Input') pads = tf.constant(pads_value) block_shape = tf.constant(block_shape_value) - tf.space_to_batch(x, block_shape, pads, name='Operation') + tf.space_to_batch_nd(x, block_shape, pads, name='Operation') tf.compat.v1.global_variables_initializer() tf_net = sess.graph_def @@ -61,9 +61,9 @@ def create_space_to_batch_net(self, in_shape, pads_value, block_shape_value, out @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_space_to_batch_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_space_to_batch_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_space_to_batch_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_space_to_batch_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ dict(in_shape=[3, 3, 4, 5, 2], block_shape_value=[3, 4, 2], pads_value=[[1, 2], [0, 0], [3, 0]], @@ -75,6 +75,6 @@ def test_space_to_batch_4D(self, params, ie_device, precision, ir_version, temp_ @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_space_to_batch_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_space_to_batch_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_space_to_batch_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_space_to_batch_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Squeeze.py b/tests/layer_tests/tensorflow_tests/test_tf_Squeeze.py index 0ef13751b3463e..84694709dd5b97 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Squeeze.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Squeeze.py @@ -4,10 +4,11 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestSqueeze(CommonTFLayerTest): - def create_squeeze_net(self, shape, axis, ir_version): + def create_squeeze_net(self, shape, axis, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -25,12 +26,11 @@ def create_squeeze_net(self, shape, axis, ir_version): # Create the graph and model with tf.compat.v1.Session() as sess: - x_shape = shape.copy() - # reshaping - if len(x_shape) >= 3: - x_shape.append(x_shape.pop(1)) + tf_x_shape = shape.copy() - x = tf.compat.v1.placeholder(tf.float32, x_shape, 'Input') + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + + x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') squeeze = tf.squeeze(x, axis=axis, name="Operation") tf.compat.v1.global_variables_initializer() @@ -42,25 +42,21 @@ def create_squeeze_net(self, shape, axis, ir_version): # Moreover, do not forget to validate ALL layer attributes!!! # - unsigned_axis = [ax if ax > -1 else len(x_shape) + ax for ax in axis] - if not unsigned_axis: - unsigned_axis = [i for i, dim in enumerate(shape) if dim == 1] - ref_net = None return tf_net, ref_net test_data_1D = [ - pytest.param(dict(shape=[1], axis=[]), marks=pytest.mark.xfail(reason="*-18807")), - pytest.param(dict(shape=[1], axis=[0]), marks=pytest.mark.xfail(reason="*-18859")), - pytest.param(dict(shape=[1], axis=[-1]), marks=pytest.mark.xfail(reason="*-18859")) + pytest.param(dict(shape=[1], axis=[])), + pytest.param(dict(shape=[1], axis=[0])), + pytest.param(dict(shape=[1], axis=[-1])) ] @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_squeeze_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_squeeze_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_squeeze_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_squeeze_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [ pytest.param(dict(shape=[1, 1], axis=[]), marks=pytest.mark.xfail(reason="*-18807")), @@ -70,9 +66,9 @@ def test_squeeze_1D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_squeeze_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_squeeze_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_squeeze_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_squeeze_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ pytest.param(dict(shape=[1, 1, 3], axis=[]), @@ -84,9 +80,9 @@ def test_squeeze_2D(self, params, ie_device, precision, ir_version, temp_dir): # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_squeeze_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_squeeze_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_squeeze_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_squeeze_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ pytest.param(dict(shape=[1, 1, 50, 100], axis=[]), marks=pytest.mark.xfail(reason="*-18807")), @@ -98,9 +94,9 @@ def test_squeeze_3D(self, params, ie_device, precision, ir_version, temp_dir): # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_squeeze_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_squeeze_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_squeeze_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_squeeze_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ pytest.param(dict(shape=[1, 1, 50, 100, 224], axis=[]), marks=pytest.mark.xfail(reason="*-18807")), @@ -119,6 +115,6 @@ def test_squeeze_4D(self, params, ie_device, precision, ir_version, temp_dir): reason="*-19394") @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_squeeze_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_squeeze_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_squeeze_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_squeeze_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py b/tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py index d03994c7052c13..8de592e805de4d 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_StridedSlice.py @@ -10,7 +10,7 @@ class TestStridedSlice(CommonTFLayerTest): @staticmethod def create_strided_slice_net(input_shape, begin, end, strides, begin_mask, end_mask, ellipsis_mask, - new_axis_mask, shrink_axis_mask, ir_version): + new_axis_mask, shrink_axis_mask, ir_version, use_new_frontend): # # Create Tensorflow model @@ -60,9 +60,9 @@ def create_strided_slice_net(input_shape, begin, end, strides, begin_mask, end_m @pytest.mark.parametrize('params', test_squeeze_data) @pytest.mark.nightly - def test_strided_slice_replace_with_squeeze(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_strided_slice_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_strided_slice_replace_with_squeeze(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_strided_slice_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_unsqueeze_data = [ dict(input_shape=[1, 5], begin=[0, 0], end=[1, 5], strides=[1, 1], begin_mask=0, @@ -85,6 +85,6 @@ def test_strided_slice_replace_with_squeeze(self, params, ie_device, precision, @pytest.mark.parametrize('params', test_unsqueeze_data) @pytest.mark.nightly - def test_strided_slice_replace_with_unsqueeze(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_strided_slice_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_strided_slice_replace_with_unsqueeze(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_strided_slice_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Sub.py b/tests/layer_tests/tensorflow_tests/test_tf_Sub.py index 00f63494255d5b..7d6532c0b3be5d 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Sub.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Sub.py @@ -5,10 +5,11 @@ import pytest from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc class TestSub(CommonTFLayerTest): - def create_sub_placeholder_const_net(self, x_shape, y_shape, ir_version): + def create_sub_placeholder_const_net(self, x_shape, y_shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -30,11 +31,9 @@ def create_sub_placeholder_const_net(self, x_shape, y_shape, ir_version): with tf.compat.v1.Session() as sess: tf_x_shape = x_shape.copy() tf_y_shape = y_shape.copy() - # reshaping - if len(tf_x_shape) >= 3: - tf_x_shape.append(tf_x_shape.pop(1)) - if len(tf_y_shape) >= 3: - tf_y_shape.append(tf_y_shape.pop(1)) + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + tf_y_shape = permute_nchw_to_nhwc(tf_y_shape, use_new_frontend) x = tf.compat.v1.placeholder(tf.float32, tf_x_shape, 'Input') constant_value = np.random.randint(-256, 256, tf_y_shape).astype(np.float32) @@ -55,23 +54,6 @@ def create_sub_placeholder_const_net(self, x_shape, y_shape, ir_version): # Moreover, do not forget to validate ALL layer attributes!!! # - if len(sub_shape) >= 3: - # Permute sub_shape to (N,C,...) format - order = [0, len(sub_shape) - 1] + list(range(1, len(sub_shape) - 1)) - sub_shape = [sub_shape[i] for i in order] - - y_shape_to_compare = tf_y_shape.copy() - while len(y_shape_to_compare) < len(x_shape): - # Expand shape of constant with 1 - y_shape_to_compare = [1] + y_shape_to_compare - constant_value = np.expand_dims(constant_value, axis=0) - - if len(y_shape_to_compare) >= 3: - # Permute constant_value to (N,C,...) format for correct further reshape - order = [0, len(y_shape_to_compare) - 1] + list(range(1, len(y_shape_to_compare) - 1)) - y_shape_to_compare = [y_shape_to_compare[i] for i in order] - constant_value = np.transpose(constant_value, order) - ref_net = None return tf_net, ref_net @@ -87,10 +69,10 @@ def create_sub_placeholder_const_net(self, x_shape, y_shape, ir_version): @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_sub_placeholder_const_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [ # Power @@ -105,10 +87,10 @@ def test_sub_placeholder_const_1D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_sub_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ # Power @@ -125,10 +107,10 @@ def test_sub_placeholder_const_2D(self, params, ie_device, precision, ir_version # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_sub_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ # Power @@ -144,10 +126,10 @@ def test_sub_placeholder_const_3D(self, params, ie_device, precision, ir_version # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_sub_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ # Power @@ -164,10 +146,10 @@ def test_sub_placeholder_const_4D(self, params, ie_device, precision, ir_version # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_sub_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) ############################################################################################### # # @@ -181,10 +163,10 @@ def test_sub_placeholder_const_5D(self, params, ie_device, precision, ir_version @pytest.mark.parametrize("params", test_data_broadcast_1D) @pytest.mark.nightly - def test_sub_placeholder_const_broadcast_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_broadcast_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_2D = [ # Power @@ -201,10 +183,10 @@ def test_sub_placeholder_const_broadcast_1D(self, params, ie_device, precision, @pytest.mark.parametrize("params", test_data_broadcast_2D) @pytest.mark.nightly - def test_sub_placeholder_const_broadcast_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_broadcast_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_3D = [ # Power @@ -226,10 +208,10 @@ def test_sub_placeholder_const_broadcast_2D(self, params, ie_device, precision, # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_broadcast_3D) @pytest.mark.nightly - def test_sub_placeholder_const_broadcast_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_broadcast_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_4D = [ # Power @@ -258,10 +240,10 @@ def test_sub_placeholder_const_broadcast_3D(self, params, ie_device, precision, # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_broadcast_4D) @pytest.mark.nightly - def test_sub_placeholder_const_broadcast_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_broadcast_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_broadcast_5D = [ # Power @@ -288,7 +270,7 @@ def test_sub_placeholder_const_broadcast_4D(self, params, ie_device, precision, # TODO mark as precommit (after successfully passing in nightly) @pytest.mark.parametrize("params", test_data_broadcast_5D) @pytest.mark.nightly - def test_sub_placeholder_const_broadcast_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version), + def test_sub_placeholder_const_broadcast_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_sub_placeholder_const_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), ie_device, precision, ir_version, - temp_dir=temp_dir) + temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Swish.py b/tests/layer_tests/tensorflow_tests/test_tf_Swish.py index 158a43353ac79c..13a4c1c98ad99c 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Swish.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Swish.py @@ -5,11 +5,12 @@ from common.layer_test_class import check_ir_version from common.tf_layer_test_class import CommonTFLayerTest +from common.utils.tf_utils import permute_nchw_to_nhwc from unit_tests.utils.graph import build_graph class TestSwish(CommonTFLayerTest): - def create_swish_net(self, shape, ir_version): + def create_swish_net(self, shape, ir_version, use_new_frontend): """ Tensorflow net IR net @@ -27,11 +28,10 @@ def create_swish_net(self, shape, ir_version): # Create the graph and model with tf.Session() as sess: - shapes = shape.copy() - # reshaping - if len(shapes) > 3: - shapes.append(shapes.pop(1)) - input = tf.placeholder(tf.float32, shapes, 'Input') + tf_x_shape = shape.copy() + + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + input = tf.placeholder(tf.float32, tf_x_shape, 'Input') tf.nn.swish(input) @@ -46,7 +46,7 @@ def create_swish_net(self, shape, ir_version): ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: nodes_attributes = { 'input': {'kind': 'op', 'type': 'Parameter'}, 'input_data': {'shape': shape, 'kind': 'data'}, @@ -71,9 +71,9 @@ def create_swish_net(self, shape, ir_version): @pytest.mark.parametrize("params", test_data_precommit) @pytest.mark.precommit - def test_swish_precommit(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_swish_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_swish_precommit(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_swish_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data = [dict(shape=[1]), dict(shape=[1, 224]), @@ -83,6 +83,6 @@ def test_swish_precommit(self, params, ie_device, precision, ir_version, temp_di @pytest.mark.parametrize("params", test_data) @pytest.mark.nightly - def test_swish(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_swish_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_swish(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_swish_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_TopK.py b/tests/layer_tests/tensorflow_tests/test_tf_TopK.py index c2d2fe54c07044..fe1b4e1949d51d 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_TopK.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_TopK.py @@ -7,12 +7,12 @@ from common.tf_layer_test_class import CommonTFLayerTest from mo.ops.op import PermuteAttrs from unit_tests.utils.graph import build_graph -from tensorflow_tests.permutation_utils import permute_nchw_to_nhwc, permute_axis +from common.utils.tf_utils import permute_nchw_to_nhwc, permute_axis class Test_TopK(CommonTFLayerTest): @staticmethod - def create_topK_net(shape, k, ir_version): + def create_topK_net(shape, k, ir_version, use_new_frontend): """ Tensorflow net: @@ -57,7 +57,7 @@ def create_topK_net(shape, k, ir_version): ref_net = None - if check_ir_version(10, None, ir_version): + if check_ir_version(10, None, ir_version) and not use_new_frontend: nodes_attributes = { 'input': {'kind': 'op', 'type': 'Parameter'}, 'input_data': {'shape': shape, 'kind': 'data'}, @@ -94,9 +94,9 @@ def create_topK_net(shape, k, ir_version): @pytest.mark.parametrize("params", test_data_1D) @pytest.mark.nightly - def test_TopK_1D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_topK_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_TopK_1D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_topK_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_2D = [ dict(shape=[14, 15], k=10), @@ -105,9 +105,9 @@ def test_TopK_1D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_2D) @pytest.mark.nightly - def test_TopK_2D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_topK_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_TopK_2D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_topK_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_3D = [ dict(shape=[13, 14, 15], k=10), @@ -116,9 +116,9 @@ def test_TopK_2D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_3D) @pytest.mark.nightly - def test_TopK_3D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_topK_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_TopK_3D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_topK_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_4D = [ dict(shape=[12, 13, 14, 15], k=10), @@ -127,9 +127,9 @@ def test_TopK_3D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_4D) @pytest.mark.nightly - def test_TopK_4D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_topK_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_TopK_4D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_topK_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) test_data_5D = [ dict(shape=[11, 12, 13, 14, 15], k=10), @@ -138,6 +138,6 @@ def test_TopK_4D(self, params, ie_device, precision, ir_version, temp_dir): @pytest.mark.parametrize("params", test_data_5D) @pytest.mark.nightly - def test_TopK_5D(self, params, ie_device, precision, ir_version, temp_dir): - self._test(*self.create_topK_net(**params, ir_version=ir_version), - ie_device, precision, ir_version, temp_dir=temp_dir) + def test_TopK_5D(self, params, ie_device, precision, ir_version, temp_dir, use_new_frontend): + self._test(*self.create_topK_net(**params, ir_version=ir_version, use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/layer_tests/tensorflow_tests/test_tf_UnaryOps.py b/tests/layer_tests/tensorflow_tests/test_tf_UnaryOps.py new file mode 100644 index 00000000000000..6281db52dce4b0 --- /dev/null +++ b/tests/layer_tests/tensorflow_tests/test_tf_UnaryOps.py @@ -0,0 +1,202 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import pytest +from common.layer_test_class import check_ir_version +from common.tf_layer_test_class import CommonTFLayerTest +from unit_tests.utils.graph import build_graph +from common.utils.tf_utils import permute_nchw_to_nhwc + +import numpy as np + + +class TestUnaryOps(CommonTFLayerTest): + current_op_type = None + + def _prepare_input(self, inputs_dict): + non_negative = ['Sqrt', 'Log'] + narrow_borders = ["Sinh", "Cosh", "Tanh", "Exp"] + within_one = ['Asin', 'Acos', 'Atanh'] + from_one = ['Acosh'] + + logical_type = ['LogicalNot'] + + # usual function domain + lower = -256 + upper = 256 + + # specific domains + if self.current_op_type in non_negative: + lower = 0 + elif self.current_op_type in narrow_borders: + lower = -16 + upper = 16 + elif self.current_op_type in from_one: + lower = 1 + elif self.current_op_type in within_one: + lower = -1 + upper = 1 + + for input in inputs_dict.keys(): + if self.current_op_type in logical_type: + inputs_dict[input] = np.random.randint(0, 1, inputs_dict[input]).astype(np.bool) + else: + inputs_dict[input] = np.random.uniform(lower, upper, inputs_dict[input]).astype(np.float32) + + return inputs_dict + + def create_net_with_unary_op(self, shape, ir_version, op_type, use_new_frontend): + """ + Tensorflow net IR net + + Input->UnaryOp => Input->UnaryOp + + """ + import tensorflow as tf + self.current_op_type = op_type + op_type_to_tf = { + 'Abs': tf.math.abs, + 'Acos': tf.math.acos, + 'Acosh': tf.math.acosh, + 'Asin': tf.math.asin, + 'Asinh': tf.math.asinh, + 'Atan': tf.math.atan, + 'Atanh': tf.math.atanh, + 'Ceiling': tf.math.ceil, + 'Cos': tf.math.cos, + 'Cosh': tf.math.cosh, + 'Elu': tf.nn.elu, + 'Exp': tf.math.exp, + 'Floor': tf.math.floor, + 'Log': tf.math.log, + 'LogicalNot': tf.math.logical_not, + 'Negative': tf.math.negative, + 'Sigmoid': tf.nn.sigmoid, + 'Sign': tf.math.sign, + 'Sin': tf.math.sin, + 'Sinh': tf.math.sinh, + 'SoftPlus': tf.nn.softplus, + 'Tan': tf.math.tan, + 'Tanh': tf.math.tanh, + 'ReLU': tf.nn.relu, + } + + # + # Create Tensorflow model + # + + tf.compat.v1.reset_default_graph() + + type = tf.float32 + if op_type == "LogicalNot": + type = tf.bool + # Create the graph and model + with tf.compat.v1.Session() as sess: + tf_x_shape = shape.copy() + tf_x_shape = permute_nchw_to_nhwc(tf_x_shape, use_new_frontend) + + input = tf.compat.v1.placeholder(type, tf_x_shape, 'Input') + op_type_to_tf[self.current_op_type](input, name='Operation') + + tf.compat.v1.global_variables_initializer() + tf_net = sess.graph_def + + # + # Create reference IR net + # Please, specify 'type': 'Input' for input node + # Moreover, do not forget to validate ALL layer attributes!!! + # + + ref_net = None + + if check_ir_version(10, None, ir_version) and not use_new_frontend: + nodes_attributes = { + 'input': {'kind': 'op', 'type': 'Parameter'}, + 'input_data': {'shape': shape, 'kind': 'data'}, + 'testing_op': {'kind': 'op', 'type': self.current_op_type}, + 'testing_data': {'shape': shape, 'kind': 'data'}, + 'result': {'kind': 'op', 'type': 'Result'} + } + + ref_net = build_graph(nodes_attributes, + [('input', 'input_data'), + ('input_data', 'testing_op'), + ('testing_op', 'testing_data'), + ('testing_data', 'result') + ]) + + return tf_net, ref_net + + test_data_precommit = [dict(shape=[4, 6, 8, 10, 12])] + + @pytest.mark.parametrize("params", test_data_precommit) + @pytest.mark.parametrize("op_type", ['Elu', + 'Sigmoid', + 'Sin', + 'Sinh', + 'Cos', + 'Cosh', + 'Abs', + 'Negative', + 'Exp', + 'Tan', + 'Tanh', + 'Floor', + 'ReLU', + 'Ceiling', + 'Asin', + 'Acos', + 'Atan', + 'Log', + 'Sign', + 'SoftPlus', + 'Atanh', + 'Acosh', + 'Asinh', + 'LogicalNot', + ]) + @pytest.mark.precommit + def test_unary_op_precommit(self, params, ie_device, precision, ir_version, temp_dir, op_type, use_new_frontend): + if ie_device == 'GPU': + pytest.skip("5D tensors is not supported on GPU") + self._test(*self.create_net_with_unary_op(**params, ir_version=ir_version, op_type=op_type, + use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) + + test_data = [dict(shape=[10, 12]), + dict(shape=[8, 10, 12]), + dict(shape=[6, 8, 10, 12]), + dict(shape=[4, 6, 8, 10, 12])] + + @pytest.mark.parametrize("params", test_data) + @pytest.mark.parametrize("op_type", ['Elu', + 'Sigmoid', + 'Sin', + 'Sinh', + 'Cos', + 'Cosh', + 'Abs', + 'Negative', + 'Exp', + 'Tan', + 'Tanh', + 'Floor', + 'ReLU', + 'Ceiling', + 'Asin', + 'Acos', + 'Atan', + 'Log', + 'LogicalNot', + 'Sign', + 'SoftPlus', + 'Atanh', + 'Acosh', + 'Asinh']) + @pytest.mark.nightly + def test_unary_op(self, params, ie_device, precision, ir_version, temp_dir, op_type, use_new_frontend): + if ie_device == 'GPU': + pytest.skip("5D tensors is not supported on GPU") + self._test(*self.create_net_with_unary_op(**params, ir_version=ir_version, op_type=op_type, + use_new_frontend=use_new_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, use_new_frontend=use_new_frontend) diff --git a/tests/memory_tests/test_runner/conftest.py b/tests/memory_tests/test_runner/conftest.py index a863eda8533222..1886249e99f9ed 100644 --- a/tests/memory_tests/test_runner/conftest.py +++ b/tests/memory_tests/test_runner/conftest.py @@ -430,8 +430,7 @@ def prepare_timeline_report(pytestconfig): import jinja2 # pylint: disable=import-outside-toplevel env = jinja2.Environment( - loader=jinja2.FileSystemLoader( - searchpath=Path().absolute() / 'memory_template'), + loader=jinja2.FileSystemLoader(searchpath=os.path.join(abs_path('.'), 'memory_template')), autoescape=False) template = env.get_template('timeline_report.html') template.stream(records=records, timelines=timelines).dump(report_path) diff --git a/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml b/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml index 042e7745a1260c..05d67549066b7d 100644 --- a/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml +++ b/tests/stress_tests/.automation/memcheck_tests/precommit_configs/desktop_references_config.xml @@ -10,12 +10,12 @@ - - - - - - + + + + + + @@ -39,12 +39,12 @@ - - - - - - + + + + + + diff --git a/tests/time_tests/src/timetests/timetest_infer.cpp b/tests/time_tests/src/timetests/timetest_infer.cpp index 83f47f837e1690..e4870ec500c4be 100644 --- a/tests/time_tests/src/timetests/timetest_infer.cpp +++ b/tests/time_tests/src/timetests/timetest_infer.cpp @@ -3,6 +3,7 @@ // #include +#include #include #include "common_utils.h" @@ -29,6 +30,8 @@ int runPipeline(const std::string &model, const std::string &device) { { SCOPED_TIMER(load_plugin); ie.GetVersions(device); + // enables performance hint for specified device + ie.SetConfig({{CONFIG_KEY(PERFORMANCE_HINT), CONFIG_VALUE(LATENCY)}}, device); } { SCOPED_TIMER(create_exenetwork); diff --git a/tests/time_tests/src/timetests/timetest_infer_cache.cpp b/tests/time_tests/src/timetests/timetest_infer_cache.cpp index f1c657f6aa463f..0b0ee0c28e1c7c 100644 --- a/tests/time_tests/src/timetests/timetest_infer_cache.cpp +++ b/tests/time_tests/src/timetests/timetest_infer_cache.cpp @@ -3,6 +3,7 @@ // #include +#include #include #include "common_utils.h" @@ -31,7 +32,8 @@ int runPipeline(const std::string &model, const std::string &device) { } { SCOPED_TIMER(load_network); - ie.SetConfig({{"CACHE_DIR", "models_cache"}}); + // enables cache + ie.SetConfig({{CONFIG_KEY(CACHE_DIR), "models_cache"}}); exeNetwork = ie.LoadNetwork(model, device); } { diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 781e75a34ece54..35f327ca8eab1d 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -10,16 +10,17 @@ if(ENABLE_LTO) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON) endif() -add_subdirectory(ittapi EXCLUDE_FROM_ALL) +add_subdirectory(ittapi) add_subdirectory(itt_collector EXCLUDE_FROM_ALL) add_subdirectory(zlib EXCLUDE_FROM_ALL) add_subdirectory(cnpy EXCLUDE_FROM_ALL) if(ENABLE_CLDNN) - add_subdirectory(ocl EXCLUDE_FROM_ALL) + add_subdirectory(ocl) endif() add_subdirectory(xbyak EXCLUDE_FROM_ALL) openvino_developer_export_targets(COMPONENT openvino_common TARGETS xbyak) +ov_install_static_lib(xbyak openvino_common) # # Pugixml @@ -31,10 +32,14 @@ if(ENABLE_SYSTEM_PUGIXML) add_library(pugixml::static ALIAS pugixml) else() function(ie_build_pugixml) - set(BUILD_SHARED_LIBS OFF) - add_subdirectory(pugixml EXCLUDE_FROM_ALL) + function(ie_build_pugixml_static) + set(BUILD_SHARED_LIBS OFF) + add_subdirectory(pugixml EXCLUDE_FROM_ALL) + endfunction() + ie_build_pugixml_static() set_property(TARGET pugixml-static PROPERTY EXPORT_NAME pugixml) openvino_developer_export_targets(COMPONENT openvino_common TARGETS pugixml::static) + ov_install_static_lib(pugixml-static openvino_common) endfunction() ie_build_pugixml() @@ -52,6 +57,9 @@ add_subdirectory(fluid/modules/gapi EXCLUDE_FROM_ALL) set_target_properties(ade fluid PROPERTIES FOLDER thirdparty) openvino_developer_export_targets(COMPONENT openvino_common TARGETS ade fluid) +ov_install_static_lib(ade openvino_common) +ov_install_static_lib(fluid openvino_common) + # # Gflags # @@ -121,12 +129,6 @@ endif() # # oneDNN for GPU plugin # -if (ANDROID OR (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)) - # oneDNN doesn't support old compilers and android builds for now, so we'll build GPU plugin without oneDNN - set(ENABLE_ONEDNN_FOR_GPU OFF CACHE BOOL "") -else() - set(ENABLE_ONEDNN_FOR_GPU ON CACHE BOOL "") -endif() if(ENABLE_ONEDNN_FOR_GPU) function(build_onednn_gpu) @@ -136,6 +138,10 @@ if(ENABLE_ONEDNN_FOR_GPU) set(ONEDNN_LIBRARY "${ONEDNN_BUILD_DIR}/src/${CMAKE_STATIC_LIBRARY_PREFIX}onednn_gpu${CMAKE_STATIC_LIBRARY_SUFFIX}") set(ONEDNN_OUTPUT_LIBRARY "${ONEDNN_INSTALL_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}onednn_gpu${CMAKE_STATIC_LIBRARY_SUFFIX}") + if(CMAKE_COMPILER_IS_GNUCXX) + ie_add_compiler_flags(-Wno-undef) + endif() + # Get processors count to limit number of threads spawned by make include(ProcessorCount) ProcessorCount(CORES_COUNT) @@ -150,15 +156,22 @@ if(ENABLE_ONEDNN_FOR_GPU) EXCLUDE_FROM_ALL ON CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" + "-DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER}" + "-DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER}" + "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" + "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}" + "-DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=${ENABLE_LTO}" + "-DCMAKE_POLICY_DEFAULT_CMP0069=NEW" "-DDNNL_CPU_RUNTIME=NONE" "-DDNNL_GPU_RUNTIME=OCL" - "-DDNNL_GPU_RUNTIME=OCL" "-DDNNL_LIBRARY_NAME=onednn_gpu" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" "-DDNNL_ENABLE_CONCURRENT_EXEC=ON" "-DDNNL_ENABLE_PRIMITIVE_CACHE=ON" + "-DDNNL_ENABLE_JIT_PROFILING=${BUILD_SHARED_LIBS}" + "-DDNNL_ENABLE_ITT_TASKS=${BUILD_SHARED_LIBS}" "-DDNNL_BUILD_TESTS=OFF" "-DDNNL_BUILD_EXAMPLES=OFF" "-DDNNL_BLAS_VENDOR=NONE" @@ -171,6 +184,23 @@ if(ENABLE_ONEDNN_FOR_GPU) COMMAND ${CMAKE_COMMAND} -E echo "OneDNN $ build for GPU complete" BUILD_BYPRODUCTS ${ONEDNN_OUTPUT_LIBRARY} ) + + ExternalProject_Get_property(onednn_gpu_build SOURCE_DIR) + ExternalProject_Get_property(onednn_gpu_build BINARY_DIR) + + # WA: create temp 'include' directory + file(MAKE_DIRECTORY "${BINARY_DIR}/include") + + add_library(onednn_gpu STATIC IMPORTED GLOBAL) + set_target_properties(onednn_gpu PROPERTIES + IMPORTED_LOCATION ${ONEDNN_OUTPUT_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES "$;$" + INTERFACE_COMPILE_DEFINITIONS ENABLE_ONEDNN_FOR_GPU) + add_dependencies(onednn_gpu onednn_gpu_build) + + # TODO: does not work for imported targets; need to import this target in + # OpenVINOConfig.cmake explicitly + # ov_install_static_lib(onednn_gpu gpu) endfunction() build_onednn_gpu() diff --git a/thirdparty/cnpy/cnpy.cpp b/thirdparty/cnpy/cnpy.cpp index ea89bea9c088b2..859f898210a39e 100644 --- a/thirdparty/cnpy/cnpy.cpp +++ b/thirdparty/cnpy/cnpy.cpp @@ -170,7 +170,8 @@ void cnpy::parse_npy_header(FILE* fp, size_t& word_size, std::vector& sh void cnpy::parse_zip_footer(FILE* fp, uint16_t& nrecs, size_t& global_header_size, size_t& global_header_offset) { std::vector footer(22); - fseek(fp,-22,SEEK_END); + if(fseek(fp,-22,SEEK_END) != 0) + throw std::runtime_error("parse_zip_footer: failed fseek"); size_t res = fread(&footer[0],sizeof(char),22,fp); if(res != 22) throw std::runtime_error("parse_zip_footer: failed fread"); @@ -195,7 +196,7 @@ cnpy::NpyArray load_the_npy_file(FILE* fp) { size_t word_size = 0; bool fortran_order = false; cnpy::parse_npy_header(fp,word_size,shape,fortran_order); - if (word_size >= 0 && word_size < ULLONG_MAX) { + if (word_size > 0 && word_size < ULLONG_MAX) { cnpy::NpyArray arr(shape, word_size, fortran_order); size_t nread = fread(arr.data(), 1, arr.num_bytes(), fp); if (nread != arr.num_bytes()) @@ -223,6 +224,7 @@ cnpy::NpyArray load_the_npz_array(FILE* fp, uint32_t compr_bytes, uint32_t uncom d_stream.opaque = Z_NULL; d_stream.avail_in = 0; d_stream.next_in = Z_NULL; + d_stream.total_out = 0; err = inflateInit2(&d_stream, -MAX_WBITS); d_stream.avail_in = compr_bytes; @@ -237,7 +239,7 @@ cnpy::NpyArray load_the_npz_array(FILE* fp, uint32_t compr_bytes, uint32_t uncom size_t word_size = 0; bool fortran_order = false; cnpy::parse_npy_header(&buffer_uncompr[0],word_size,shape,fortran_order); - if (word_size >= 0 && word_size < ULLONG_MAX) { + if (word_size > 0 && word_size < ULLONG_MAX) { cnpy::NpyArray array(shape, word_size, fortran_order); size_t offset = uncompr_bytes - array.num_bytes(); @@ -344,7 +346,8 @@ cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) { else { //skip past the data uint32_t size = *(uint32_t*) &local_header[22]; - fseek(fp,size,SEEK_CUR); + if (fseek(fp,size,SEEK_CUR) !=0) + throw std::runtime_error("npz_load: failed fseek"); } } @@ -370,5 +373,3 @@ cnpy::NpyArray cnpy::npy_load(std::string fname) { } } - - diff --git a/thirdparty/cnpy/cnpy.h b/thirdparty/cnpy/cnpy.h index e8935e8937e89c..40b959a6a8a0cd 100644 --- a/thirdparty/cnpy/cnpy.h +++ b/thirdparty/cnpy/cnpy.h @@ -155,7 +155,8 @@ namespace cnpy { //below, we will write the the new data at the start of the global header then append the global header and footer below it size_t global_header_size; parse_zip_footer(fp,nrecs,global_header_size,global_header_offset); - fseek(fp,global_header_offset,SEEK_SET); + if(fseek(fp,global_header_offset,SEEK_SET)!=0 ) + throw std::runtime_error("npz_save: failed fseek"); global_header.resize(global_header_size); size_t res = fread(&global_header[0],sizeof(char),global_header_size,fp); if(res != global_header_size){ diff --git a/thirdparty/ittapi/CMakeLists.txt b/thirdparty/ittapi/CMakeLists.txt index c50ff92fa272b3..87cf02a851be5d 100644 --- a/thirdparty/ittapi/CMakeLists.txt +++ b/thirdparty/ittapi/CMakeLists.txt @@ -11,13 +11,19 @@ if(ENABLE_PROFILING_ITT) message(WARNING "Profiling option enabled, but no ITT library was found under INTEL_VTUNE_DIR") endif() else() - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ittapi ${CMAKE_BINARY_DIR}/_deps/ittapi) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ittapi ${CMAKE_BINARY_DIR}/_deps/ittapi EXCLUDE_FROM_ALL) target_compile_definitions(ittnotify INTERFACE ENABLE_PROFILING_ITT) - if (UNIX) + if(CMAKE_COMPILER_IS_GNUCXX) target_compile_options(ittnotify PRIVATE -Wno-undef) endif() + # override INTERFACE_INCLUDE_DIRECTORIES + set_property(TARGET ittnotify PROPERTY INTERFACE_INCLUDE_DIRECTORIES + $ + $) + openvino_developer_export_targets(COMPONENT openvino_common TARGETS ittnotify) + ov_install_static_lib(ittnotify openvino_common) endif() endif() diff --git a/thirdparty/ocl/CMakeLists.txt b/thirdparty/ocl/CMakeLists.txt index a0648080ea13a6..7a54e9558c75bb 100644 --- a/thirdparty/ocl/CMakeLists.txt +++ b/thirdparty/ocl/CMakeLists.txt @@ -43,10 +43,20 @@ set(CMAKE_C_FLAGS "") set(CMAKE_CXX_FLAGS "") set(CMAKE_C_FLAGS_RELEASE "") set(CMAKE_CXX_FLAGS_RELEASE "") +# OpenCL has absolute paths to include directories +set(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION OFF) +if(NOT DEFINED USE_DYNAMIC_VCXX_RUNTIME) + set(USE_DYNAMIC_VCXX_RUNTIME ON) +endif() -add_subdirectory(icd_loader) +add_subdirectory(icd_loader EXCLUDE_FROM_ALL) -target_include_directories(OpenCL SYSTEM PUBLIC ${OPENCL_HEADERS_DIR}) +# override INTERFACE_INCLUDE_DIRECTORIES +set_property(TARGET OpenCL PROPERTY INTERFACE_INCLUDE_DIRECTORIES + $) +foreach(dir IN LISTS OPENCL_HEADERS_DIR) + target_include_directories(OpenCL SYSTEM PUBLIC $) +endforeach() # The following varables are needed to make find_package(OpenCL) work set(OPENCL_VERSION_2_2 ON CACHE BOOL "" FORCE) @@ -58,3 +68,5 @@ get_lib_path("${OUTPUT_ROOT}/${BIN_FOLDER}" OPENCL_LIB_DIR) get_lib_name("OpenCL" OPENCL_LIB_NAME) set(OpenCL_LIBRARY "${OPENCL_LIB_DIR}/${OPENCL_LIB_NAME}" CACHE PATH "" FORCE) + +ov_install_static_lib(OpenCL gpu) diff --git a/thirdparty/onednn_gpu b/thirdparty/onednn_gpu index 1ab3f50381ae85..75d978369d0c5b 160000 --- a/thirdparty/onednn_gpu +++ b/thirdparty/onednn_gpu @@ -1 +1 @@ -Subproject commit 1ab3f50381ae85ab5ab0a29d5565ebe72ce77030 +Subproject commit 75d978369d0c5be04ec36c3cea2e00a14da1ec83 diff --git a/thirdparty/onnx/CMakeLists.txt b/thirdparty/onnx/CMakeLists.txt index 8c9d8b6e8c60bb..263802dd42fc69 100644 --- a/thirdparty/onnx/CMakeLists.txt +++ b/thirdparty/onnx/CMakeLists.txt @@ -23,7 +23,7 @@ endmacro() set(ONNX_USE_PROTOBUF_SHARED_LIBS ${BUILD_SHARED_LIBS} CACHE BOOL "Use dynamic protobuf by ONNX library" FORCE) set(ONNX_NAMESPACE ${NGRAPH_ONNX_NAMESPACE}) -set(ONNX_USE_LITE_PROTO ${NGRAPH_USE_PROTOBUF_LITE} CACHE BOOL "Use protobuf lite for ONNX library" FORCE) +set(ONNX_USE_LITE_PROTO ON CACHE BOOL "Use protobuf lite for ONNX library" FORCE) set(ONNX_ML ON CACHE BOOL "Use ONNX ML" FORCE) if(CMAKE_CROSSCOMPILING) set(ONNX_CUSTOM_PROTOC_EXECUTABLE ${SYSTEM_PROTOC}) diff --git a/thirdparty/onnx/onnx b/thirdparty/onnx/onnx index 1089b9e8045a3a..da889e6b957503 160000 --- a/thirdparty/onnx/onnx +++ b/thirdparty/onnx/onnx @@ -1 +1 @@ -Subproject commit 1089b9e8045a3a2882d7bb6a1dbaeaf9cae131da +Subproject commit da889e6b95750350726d149bf447bf0cd1245964 diff --git a/thirdparty/protobuf/CMakeLists.txt b/thirdparty/protobuf/CMakeLists.txt index 821c6764666ea2..97cb66b5462484 100644 --- a/thirdparty/protobuf/CMakeLists.txt +++ b/thirdparty/protobuf/CMakeLists.txt @@ -69,7 +69,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR OV_COMPILER_IS_CLANG OR INTERPROCEDURAL_OPTIMIZATION_RELEASE ${ENABLE_LTO}) endif() -if(protobuf_VERSION VERSION_LESS "3.9" AND NGRAPH_USE_PROTOBUF_LITE) +if(protobuf_VERSION VERSION_LESS "3.9") message(FATAL_ERROR "Minimum supported version of protobuf-lite library is 3.9.0 (provided ${protobuf_VERSION})") endif() diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9798bde8bb1767..fb4dd45ca856e7 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -63,4 +63,9 @@ if(ENABLE_PYTHON) COMPONENT python_tools_${PYTHON_VERSION}) ie_cpack(python_tools python_tools_${PYTHON_VERSION}) + + if(ENABLE_WHEEL) + add_subdirectory(openvino_dev) + endif() + endif() diff --git a/tools/benchmark_tool/openvino/tools/benchmark/main.py b/tools/benchmark_tool/openvino/tools/benchmark/main.py index 47fabb34c48fd7..422dc0d3991dc7 100644 --- a/tools/benchmark_tool/openvino/tools/benchmark/main.py +++ b/tools/benchmark_tool/openvino/tools/benchmark/main.py @@ -334,7 +334,10 @@ def set_throughput_streams(): paths_to_input = list() if args.paths_to_input: for path in args.paths_to_input: - paths_to_input.append(os.path.abspath(*path) if args.paths_to_input else None) + if ":" in next(iter(path), ""): + paths_to_input.extend(path) + else: + paths_to_input.append(os.path.abspath(*path)) set_inputs(paths_to_input, batch_size, app_inputs_info, infer_requests) if statistics: diff --git a/tools/benchmark_tool/openvino/tools/benchmark/parameters.py b/tools/benchmark_tool/openvino/tools/benchmark/parameters.py index 89a3c6283dc5fa..f7f42b1c16c4d3 100644 --- a/tools/benchmark_tool/openvino/tools/benchmark/parameters.py +++ b/tools/benchmark_tool/openvino/tools/benchmark/parameters.py @@ -33,7 +33,9 @@ def parse_args(): help='Show this help message and exit.') args.add_argument('-i', '--paths_to_input', action='append', nargs='+', type=str, required=False, help='Optional. ' - 'Path to a folder with images and/or binaries or to specific image or binary file.') + 'Path to a folder with images and/or binaries or to specific image or binary file.' + 'It is also allowed to map files to network inputs: ' + 'input_1:file_1,file_2,input_4:file_4 input_2:file_3') args.add_argument('-m', '--path_to_model', type=str, required=True, help='Required. Path to an .xml/.onnx file with a trained model or ' 'to a .blob file with a trained compiled model.') diff --git a/tools/benchmark_tool/openvino/tools/benchmark/utils/inputs_filling.py b/tools/benchmark_tool/openvino/tools/benchmark/utils/inputs_filling.py index 0566b9b6ea8c93..dcae3f0aefa4fb 100644 --- a/tools/benchmark_tool/openvino/tools/benchmark/utils/inputs_filling.py +++ b/tools/benchmark_tool/openvino/tools/benchmark/utils/inputs_filling.py @@ -3,12 +3,17 @@ import os import cv2 +import re import numpy as np from glob import glob +from collections import defaultdict +from pathlib import Path +from itertools import chain from .constants import IMAGE_EXTENSIONS, BINARY_EXTENSIONS from .logging import logger + def set_inputs(paths_to_input, batch_size, app_input_info, requests): requests_input_data = get_inputs(paths_to_input, batch_size, app_input_info, requests) for i in range(len(requests)): @@ -18,7 +23,11 @@ def set_inputs(paths_to_input, batch_size, app_input_info, requests): raise Exception(f"No input with name {k} found!") inputs[k].buffer[:] = v + def get_inputs(paths_to_input, batch_size, app_input_info, requests): + input_file_mapping = parse_paths_to_input(paths_to_input) + check_input_file_mapping(input_file_mapping, app_input_info) + input_image_sizes = {} for key in sorted(app_input_info.keys()): info = app_input_info[key] @@ -31,13 +40,15 @@ def get_inputs(paths_to_input, batch_size, app_input_info, requests): image_files = list() binary_files = list() - if paths_to_input: + if paths_to_input and not input_file_mapping: image_files = get_files_by_extensions(paths_to_input, IMAGE_EXTENSIONS) - image_files.sort() binary_files = get_files_by_extensions(paths_to_input, BINARY_EXTENSIONS) - binary_files.sort() - if (len(image_files) == 0) and (len(binary_files) == 0): + if input_file_mapping and len(input_file_mapping) < len(app_input_info): + not_provided_inputs = set(app_input_info) - set(input_file_mapping) + logger.warning("No input files were given for the inputs: " + f"{', '.join(not_provided_inputs)}. This inputs will be filled with random values!") + elif (len(image_files) == 0) and (len(binary_files) == 0): logger.warning("No input files were given: all inputs will be filled with random values!") else: binary_to_be_used = binaries_count * batch_size * len(requests) @@ -76,13 +87,23 @@ def get_inputs(paths_to_input, batch_size, app_input_info, requests): info = app_input_info[key] if info.is_image: # input is image + if key in input_file_mapping: + input_data[key] = fill_blob_with_image(input_file_mapping[key], request_id, batch_size, + keys.index(key), len(keys), info, from_map=True) + continue + if len(image_files) > 0: input_data[key] = fill_blob_with_image(image_files, request_id, batch_size, keys.index(key), len(keys), info) continue # input is binary - if len(binary_files): + if len(binary_files) or key in input_file_mapping: + if key in input_file_mapping: + input_data[key] = fill_blob_with_binary(input_file_mapping[key], request_id, batch_size, + keys.index(key), len(keys), info, from_map=True) + continue + input_data[key] = fill_blob_with_binary(binary_files, request_id, batch_size, keys.index(key), len(keys), info) continue @@ -106,9 +127,19 @@ def get_inputs(paths_to_input, batch_size, app_input_info, requests): def get_files_by_extensions(paths_to_input, extensions): - get_extension = lambda file_path: file_path.split(".")[-1].upper() + if len(paths_to_input) == 1: + files = [file for file in paths_to_input[0].split(",") if file] + if all(get_extension(file) in extensions for file in files): + check_files_exist(files) + return files + + return get_files_by_extensions_for_not_list_of_files(paths_to_input, extensions) + + +def get_files_by_extensions_for_not_list_of_files(paths_to_input, extensions): input_files = list() + for path_to_input in paths_to_input: if os.path.isfile(path_to_input): files = [os.path.normpath(path_to_input)] @@ -119,13 +150,21 @@ def get_files_by_extensions(paths_to_input, extensions): file_extension = get_extension(file) if file_extension in extensions: input_files.append(file) + input_files.sort() + return input_files + + +def get_extension(file_path): + return file_path.split(".")[-1].upper() - return input_files -def fill_blob_with_image(image_paths, request_id, batch_size, input_id, input_size, info): +def fill_blob_with_image(image_paths, request_id, batch_size, input_id, input_size, info, from_map=False): shape = info.shape images = np.ndarray(shape) - image_index = request_id * batch_size * input_size + input_id + if from_map: + image_index = request_id * batch_size + else: + image_index = request_id * batch_size * input_size + input_id scale_mean = (not np.array_equal(info.scale, (1.0, 1.0, 1.0)) or not np.array_equal(info.mean, (0.0, 0.0, 0.0))) @@ -154,7 +193,10 @@ def fill_blob_with_image(image_paths, request_id, batch_size, input_id, input_si images[b] = image - image_index += input_size + if from_map: + image_index += 1 + else: + image_index += input_size return images def get_dtype(precision): @@ -173,12 +215,15 @@ def get_dtype(precision): return format_map[precision] raise Exception("Can't find data type for precision: " + precision) -def fill_blob_with_binary(binary_paths, request_id, batch_size, input_id, input_size, info): +def fill_blob_with_binary(binary_paths, request_id, batch_size, input_id, input_size, info, from_map=False): binaries = np.ndarray(info.shape) shape = info.shape.copy() if 'N' in info.layout: shape[info.layout.index('N')] = 1 - binary_index = request_id * batch_size * input_size + input_id + if from_map: + binary_index = request_id * batch_size + else: + binary_index = request_id * batch_size * input_size + input_id dtype = get_dtype(info.precision)[0] for b in range(batch_size): binary_index %= len(binary_paths) @@ -191,7 +236,11 @@ def fill_blob_with_binary(binary_paths, request_id, batch_size, input_id, input_ raise Exception( f"File {binary_filename} contains {binary_file_size} bytes but network expects {blob_size}") binaries[b] = np.reshape(np.fromfile(binary_filename, dtype), shape) - binary_index += input_size + + if from_map: + binary_index += 1 + else: + binary_index += input_size return binaries @@ -214,3 +263,75 @@ def fill_blob_with_random(layer): if layer.shape: return rs.uniform(rand_min, rand_max, layer.shape).astype(dtype) return (dtype)(rs.uniform(rand_min, rand_max)) + + +def parse_paths_to_input(paths_to_inputs): + input_dicts_list = [parse_path(path) for path in paths_to_inputs] + inputs = defaultdict(list) + for input_dict in input_dicts_list: + for input_name, input_files in input_dict.items(): + inputs[input_name] += input_files + return {input_: files for input_, files in inputs.items() if files} + + +def parse_path(path): + """ + Parse "input_1:file1,file2,input_2:file3" into a dict + """ + inputs = re.findall(r"([^,]\w+):", path) + input_files = [file for file in re.split(r"[^,]\w+:", path) if file] + return { + input_: files.strip(",").split(",") for input_, files in zip(inputs, input_files) + } + + +def check_input_file_mapping(input_file_mapping, app_input_info): + check_inputs(app_input_info, input_file_mapping) + check_input_file_mapping_files_exists(input_file_mapping) + check_files_extensions(app_input_info, input_file_mapping) + + +def check_inputs(app_input_info, input_file_mapping): + wrong_inputs = [ + input_ for input_ in input_file_mapping if input_ not in app_input_info + ] + if wrong_inputs: + raise Exception( + f"Wrong input mapping! Cannot find inputs: {wrong_inputs}. " + f"Available inputs: {list(app_input_info)}. " + "Please check `-i` input data" + ) + + +def check_input_file_mapping_files_exists(input_file_mapping): + check_files_exist(chain.from_iterable(input_file_mapping.values())) + + +def check_files_exist(input_files_list): + not_files = [ + file for file in input_files_list if not Path(file).is_file() + ] + if not_files: + not_files = ",\n".join(not_files) + raise Exception( + f"Inputs are not files or does not exist!\n {not_files}" + ) + + +def check_files_extensions(app_input_info, input_file_mapping): + unsupported_files = [] + for input_, files in input_file_mapping.items(): + info = app_input_info[input_] + + proper_extentions = IMAGE_EXTENSIONS if info.is_image else BINARY_EXTENSIONS + unsupported = "\n".join( + [file for file in files if Path(file).suffix.upper().strip(".") not in proper_extentions] + ) + if unsupported: + unsupported_files.append(unsupported) + if unsupported_files: + unsupported_files = "\n".join(unsupported_files) + raise Exception( + f"This files has unsupported extensions: {unsupported_files}.\n" + f"Supported extentions:\nImages: {IMAGE_EXTENSIONS}\nBinary: {BINARY_EXTENSIONS}" + ) diff --git a/tools/openvino_dev/CMakeLists.txt b/tools/openvino_dev/CMakeLists.txt new file mode 100644 index 00000000000000..0418784dd52271 --- /dev/null +++ b/tools/openvino_dev/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (C) 2018-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +set(WHEEL_VERSION "${IE_VERSION}" CACHE STRING "Version of this release" FORCE) +set(WHEEL_BUILD "${IE_VERSION_BUILD}" CACHE STRING "Build number of this release" FORCE) +set(SETUP_PY "${CMAKE_CURRENT_SOURCE_DIR}/setup.py") + +set(openvino_wheel_name "openvino_dev-${WHEEL_VERSION}-${WHEEL_BUILD}-py3-none-any.whl") +set(openvino_wheels_output_dir "${CMAKE_BINARY_DIR}/wheels") +set(openvino_wheel_path "${openvino_wheels_output_dir}/${openvino_wheel_name}") + +add_custom_command(OUTPUT ${openvino_wheel_path} + COMMAND ${CMAKE_COMMAND} -E env OPENVINO_VERSION=${WHEEL_VERSION} + ${PYTHON_EXECUTABLE} ${SETUP_PY} clean bdist_wheel + --dist-dir ${openvino_wheels_output_dir} + --build=${WHEEL_BUILD} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Building Python wheel ${openvino_wheel_name}" + VERBATIM) + +add_custom_target(openvino_dev_wheel ALL DEPENDS ${openvino_wheel_path}) diff --git a/tools/openvino_dev/requirements.txt b/tools/openvino_dev/requirements.txt new file mode 100644 index 00000000000000..ccc569a0194b30 --- /dev/null +++ b/tools/openvino_dev/requirements.txt @@ -0,0 +1,28 @@ +defusedxml>=0.7.1 +scipy~=1.5.4 +jstyleson~=0.0.2 +numpy>=1.16.6,<1.20 +addict>=2.4.0 +pandas~=1.1.5 +hyperopt~=0.1.2 +networkx~=2.5 +tqdm>=4.54.1 +texttable~=1.6.3 +py-cpuinfo>=7.0.0 +PyYAML>=5.4.1 +pillow>=8.1.2 +scikit-image>=0.17.2 +scikit-learn>=0.24.1 +yamlloader>=0.5 +shapely>=1.7.1 +nibabel>=3.2.1 +pydicom>=2.1.2 +sentencepiece>=0.1.95 +tokenizers>=0.10.1 +editdistance>=0.5.3 +parasail>=1.2.4 +fast-ctc-decode>=0.2.5 +rawpy>=0.16.0 +nltk>=3.5 +opencv-python==4.5.* +progress>=1.5 diff --git a/tools/openvino_dev/setup.cfg b/tools/openvino_dev/setup.cfg new file mode 100644 index 00000000000000..0c1c44b4ca4a4d --- /dev/null +++ b/tools/openvino_dev/setup.cfg @@ -0,0 +1,21 @@ +[options] +setup_requires = + wheel + +[options.extras_require] + +[options.package_data] + * = * + +[options.entry_points] +console_scripts = + +[metadata] +license_files = + readme* + *LICENSE* + *license* + *third-party-programs* + *EULA* + ../../licensing/* + ../../LICENSE diff --git a/tools/openvino_dev/setup.py b/tools/openvino_dev/setup.py new file mode 100644 index 00000000000000..ffd8da71647e6b --- /dev/null +++ b/tools/openvino_dev/setup.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2018-2021 Intel Corporation SPDX-License-Identifier: Apache-2.0 + +""" Use this script to create a openvino-dev wheel package: + $ python3 setup.py bdist_wheel +""" +# pylint: disable-msg=line-too-long + +import os +import sys +import platform +import subprocess # nosec +import shutil +from distutils import log +from distutils.command.build import build +from distutils.command.clean import clean +from pathlib import Path +from fnmatch import fnmatchcase +import pkg_resources +from setuptools.command.install import install +from setuptools import setup, find_namespace_packages + +PYTHON_VERSION = f'python{sys.version_info.major}.{sys.version_info.minor}' +SCRIPT_DIR = Path(__file__).resolve().parents[0] +OPENVINO_DIR = Path(__file__).resolve().parents[2] +SRC_DIR = SCRIPT_DIR / 'src' + +PKG_INSTALL_CFG = { + 'openvino-mo': { + 'src_dir': OPENVINO_DIR / 'model-optimizer', + 'black_list': ['*unit_tests*'], + 'prefix': 'mo', + 'extract_entry_points': True, + 'extract_requirements': True, + 'extract_extras': True, + }, + 'benchmark_tool': { + 'src_dir': OPENVINO_DIR / 'tools' / 'benchmark_tool', + 'black_list': [], + 'prefix': 'benchmark_tool', + 'extract_entry_points': True, + }, + "accuracy_checker": { + 'src_dir': OPENVINO_DIR / 'tools' / 'pot' / 'thirdparty' / 'open_model_zoo' / 'tools' / 'accuracy_checker', # noqa:E501 + 'black_list': ['*tests*'], + 'prefix': 'accuracy_checker', + 'extract_entry_points': True, + }, + "omz_tools": { + 'src_dir': OPENVINO_DIR / 'tools' / 'pot' / 'thirdparty' / 'open_model_zoo' / 'tools' / 'model_tools', # noqa:E501 + 'black_list': [], + 'prefix': 'omz_tools', + 'extract_requirements': True, + 'extract_entry_points': True, + 'extract_extras': True, + }, + "pot": { + 'src_dir': OPENVINO_DIR / 'tools' / 'pot', + 'black_list': ['*tests*'], + 'prefix': 'pot', + 'extract_entry_points': True, + }, +} + + +def ignore_patterns(*patterns): + """ + Filter names by given patterns + """ + return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) + + +class CustomBuild(build): + """Custom implementation of build""" + + def run(self): + + # pylint: disable-msg=too-many-locals + self.announce('Installing packages', level=log.INFO) + for cmp, cmp_data in PKG_INSTALL_CFG.items(): + self.announce(f'Processing package: {cmp}', level=log.INFO) + subprocess.call([sys.executable, 'setup.py', 'install', + '--root', str(SCRIPT_DIR), + '--prefix', str(cmp_data.get("prefix"))], + cwd=str(cmp_data.get('src_dir'))) + + # grab installed modules + lib_dir = 'lib/site-packages' if platform.system() == 'Windows' else f'lib/{PYTHON_VERSION}/site-packages' + src = SCRIPT_DIR / cmp_data.get('prefix') / lib_dir + + egg_info = list(src.glob('**/*.egg-info')) + if egg_info: + + def raw_req(req): + req.marker = None + return str(req) + + distributions = pkg_resources.find_distributions(str(Path(egg_info[0]).parent)) + for dist in distributions: + self.announce(f'Distribution: {dist.egg_name()}', level=log.INFO) + + # load install_requires list + install_requires = list(sorted(map(raw_req, dist.requires()))) + self.announce(f'Install requires: {install_requires}', level=log.INFO) + if cmp_data.get("extract_requirements"): + self.distribution.install_requires.extend(install_requires) + + # load extras_require + if cmp_data.get("extract_extras"): + for extra in dist.extras: + if extra not in self.distribution.extras_require: + self.distribution.extras_require[extra] = [] + extras_require = set(map(raw_req, dist.requires((extra,)))) + self.announce(f'Extras: {extra}:{extras_require}', level=log.INFO) + self.distribution.extras_require[extra].extend(extras_require) + + # extract console scripts + if cmp_data.get("extract_entry_points"): + for console_scripts in dist.get_entry_map('console_scripts'): + self.announce(f'Entry point: {console_scripts}', level=log.INFO) + entry = dist.get_entry_info('console_scripts', console_scripts) + self.distribution.entry_points['console_scripts'].append(str(entry)) + + # copy modules to the build directory + dst = Path(self.build_lib) + black_list = cmp_data.get('black_list') + exclude = ignore_patterns('*ez_setup*', '*__pycache__*', '*.egg-info*', *black_list) + for path in src.glob('**/*'): + if path.is_dir() or exclude(str(path)): + continue + path_rel = path.relative_to(src) + (dst / path_rel.parent).mkdir(exist_ok=True, parents=True) + shutil.copyfile(path, dst / path_rel) + + # add dependecy on runtime package + runtime_req = [f'openvino=={self.distribution.get_version()}'] + self.distribution.install_requires.extend(runtime_req) + + self.announce(f'{self.distribution.install_requires}', level=log.DEBUG) + self.announce(f'{self.distribution.extras_require}', level=log.DEBUG) + self.announce(f'{self.distribution.entry_points}', level=log.DEBUG) + + +class CustomInstall(install): + """Enable build_clib during the installation""" + + def run(self): + self.run_command('build') + install.run(self) + + +class CustomClean(clean): + """Clean up staging directories""" + + def clean(self, install_cfg): + """Clean components staging directories""" + for comp, comp_data in install_cfg.items(): + install_prefix = comp_data.get('prefix') + self.announce(f'Cleaning {comp}: {install_prefix}', level=log.INFO) + if os.path.exists(install_prefix): + shutil.rmtree(install_prefix) + + def run(self): + self.clean(PKG_INSTALL_CFG) + for pattern in './build ./dist **/*.pyc **/*.tgz **/*.egg-info'.split(' '): + paths = SCRIPT_DIR.glob(pattern) + for path in paths: + if path.is_file() and path.exists(): + path = path.parent + self.announce(f'Cleaning: {path}', level=log.INFO) + shutil.rmtree(path) + clean.run(self) + + +def get_description(desc_file_path): + """read description from README.md""" + with open(desc_file_path, 'r', encoding='utf-8') as fstream: + description = fstream.read() + return description + +with (SCRIPT_DIR / 'requirements.txt').open() as requirements: + install_reqs = [ + str(requirement) + for requirement + in pkg_resources.parse_requirements(requirements) + ] + + +setup( + name='openvino-dev', + version=os.getenv('OPENVINO_VERSION', '0.0.0'), + author='Intel® Corporation', + license='OSI Approved :: Apache Software License', + author_email='openvino_pushbot@intel.com', + url='https://docs.openvinotoolkit.org/latest/index.html', + download_url='https://github.com/openvinotoolkit/openvino/tags', + description='OpenVINO™ Developer Package', + long_description=get_description(SCRIPT_DIR.parents[1] / 'docs/install_guides/pypi-openvino-dev.md'), + long_description_content_type='text/markdown', + classifiers=[ + 'Programming Language :: Python :: 3', + 'OSI Approved :: Apache Software License', + 'Operating System :: OS Independent', + ], + cmdclass={ + 'build': CustomBuild, + 'install': CustomInstall, + 'clean': CustomClean, + }, + entry_points = { + 'console_scripts': [], + }, + install_requires=install_reqs, + packages=find_namespace_packages(where=str(SRC_DIR)), + package_dir={'': str(SRC_DIR)}, +) diff --git a/tools/openvino_dev/src/openvino/__init__.py b/tools/openvino_dev/src/openvino/__init__.py new file mode 100644 index 00000000000000..855c54922a0cda --- /dev/null +++ b/tools/openvino_dev/src/openvino/__init__.py @@ -0,0 +1,3 @@ +# Copyright (C) 2020-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +__path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/tools/openvino_dev/src/openvino/tools/__init__.py b/tools/openvino_dev/src/openvino/tools/__init__.py new file mode 100644 index 00000000000000..855c54922a0cda --- /dev/null +++ b/tools/openvino_dev/src/openvino/tools/__init__.py @@ -0,0 +1,3 @@ +# Copyright (C) 2020-2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +__path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/tools/pot/openvino/tools/pot/algorithms/finetuning/layers.py b/tools/pot/openvino/tools/pot/algorithms/finetuning/layers.py index 79e89edd0a40e0..7d716db991e68b 100644 --- a/tools/pot/openvino/tools/pot/algorithms/finetuning/layers.py +++ b/tools/pot/openvino/tools/pot/algorithms/finetuning/layers.py @@ -93,8 +93,8 @@ def forward(self, x): scale = self.scale.exp() s = self.val_h * scale.reciprocal() x = x - self.min - x = x.clamp(max=self.val_h, min=self.val_l) x = x * s + x = x.clamp(max=self.val_h, min=self.val_l) x = STERound.apply(x, self.val_l, self.val_h) x = x * s.reciprocal() + self.min return x diff --git a/tools/pot/openvino/tools/pot/algorithms/quantization/bias_correction/algorithm.py b/tools/pot/openvino/tools/pot/algorithms/quantization/bias_correction/algorithm.py index 68f09a59b24460..ddf74a68a879b8 100644 --- a/tools/pot/openvino/tools/pot/algorithms/quantization/bias_correction/algorithm.py +++ b/tools/pot/openvino/tools/pot/algorithms/quantization/bias_correction/algorithm.py @@ -409,7 +409,7 @@ def register_statistics(self, model, stats_collector): input_name = biased_after_param_nodes[node.name] statistics_layout[input_name] = {'batch_mean_param_in': agf.batch_mean} self._collected_stat_inputs.append(input_name) - statistics_layout[add_node.name] =\ + statistics_layout[add_node_name] =\ {'mean_per_channel': TensorStatisticAxis(granularity='perchannel', type='mean', inplace_statistics=self.config['inplace_statistics'], diff --git a/tools/pot/openvino/tools/pot/algorithms/quantization/fake_quantize.py b/tools/pot/openvino/tools/pot/algorithms/quantization/fake_quantize.py index 8a1b4545ea1196..306def42cb6909 100644 --- a/tools/pot/openvino/tools/pot/algorithms/quantization/fake_quantize.py +++ b/tools/pot/openvino/tools/pot/algorithms/quantization/fake_quantize.py @@ -441,7 +441,33 @@ def _custom_broadcast(arrays_list): def create_renamed_layers_mapping(model, stats_layout): changed_names_map = {} for layer_name in stats_layout: - node = get_node_by_name(model, layer_name) + node_name = layer_name + port_id = None + if isinstance(layer_name, tuple): + node_name, port_id = layer_name + node = get_node_by_name(model, node_name) if node is not None and 'orig_node_name' in node: - changed_names_map[node.name] = node['orig_node_name'] + name_change_to = node['orig_node_name'] if port_id is None else (node['orig_node_name'], port_id) + changed_names_map[layer_name] = name_change_to return changed_names_map + + +def get_num_levels(x: np.ndarray) -> int: + """ + Calculates the number of discret levels of the values + in the input NumPy tensor x + :param x: the input tensor + :return the number of discret value levels in the input tensor x + """ + NUM_BINS = 256 + x = x.flatten() + hist, _ = np.histogram(x, NUM_BINS) + non_empty_bins = [i for i, v in enumerate(hist) if v > 0] + deltas = [non_empty_bins[i]-non_empty_bins[i-1] for i in range(1, len(non_empty_bins))] + if deltas == []: + return 0 + d = min(deltas) + if d == 1: + return -1 + + return round(NUM_BINS / d) diff --git a/tools/pot/openvino/tools/pot/configs/hardware/IgnoredPatterns.md b/tools/pot/openvino/tools/pot/configs/hardware/IgnoredPatterns.md index d0d9b17cf96d68..1580f677bcf3cb 100755 --- a/tools/pot/openvino/tools/pot/configs/hardware/IgnoredPatterns.md +++ b/tools/pot/openvino/tools/pot/configs/hardware/IgnoredPatterns.md @@ -292,6 +292,46 @@ graph TB --- +**Name:** se_block
+**Pattern:**
+ +```mermaid +graph TB + input(ReduceMean) --> conv_fc(Convolution, MatMul) + conv_fc(Convolution, MatMul) --> bias(Add) + bias_const(Const) --> bias(Add) + bias(Add) --> act(ReLU, PReLU) + act(ReLU, PReLU) --> conv_fc_1(Convolution, MatMul) + conv_fc_1(Convolution, MatMul) --> bias_1(Add) + bias_const_1(Const) --> bias_1(Add) + bias_1(Add) --> act_1(Sigmoid) + act_1(Sigmoid) --> output(Multiply) + style input fill:#73C2FB + style output fill:#73C2FB +``` + +--- + +**Name:** se_block_swish_activation
+**Pattern:**
+ +```mermaid +graph TB + input(ReduceMean) --> conv_fc(Convolution, MatMul) + conv_fc(Convolution, MatMul) --> bias(Add) + bias_const(Const) --> bias(Add) + bias(Add) --> swish(Swish) + swish(Swish) --> conv_fc_1(Convolution, MatMul) + conv_fc_1(Convolution, MatMul) --> bias_1(Add) + bias_const_1(Const) --> bias_1(Add) + bias_1(Add) --> act_1(Sigmoid) + act_1(Sigmoid) --> output(Multiply) + style input fill:#73C2FB + style output fill:#73C2FB +``` + +--- + **Name:** softmax
**Pattern:**
diff --git a/tools/pot/openvino/tools/pot/graph/passes.py b/tools/pot/openvino/tools/pot/graph/passes.py index 980d14f8972d9c..4705fbfa039d63 100644 --- a/tools/pot/openvino/tools/pot/graph/passes.py +++ b/tools/pot/openvino/tools/pot/graph/passes.py @@ -216,7 +216,7 @@ def check_split_concat(self, node): jump_split_concat_ops: jump_over_split_concat } - def find_nodes_fq_int(self, graph): + def delete_fq_non_quantizable_node_precision(self, graph): type_infer(graph) fq_removal = RemoveFakeQuantize() fq_removal.quantize_agnostic_operations = self.quantize_agnostic_operations @@ -227,7 +227,7 @@ def find_nodes_fq_int(self, graph): fq = fq_queue.popleft() if fq.in_port(0).get_source() is not None and fq.in_port(0).get_source().is_data_type_defined(): type_node = fq.in_port(0).get_source().get_data_type() - if type_node in (np.int32, np.int64): + if type_node in (np.int32, np.int64, bool): node_int_fq.append(fq.name) fq_removal.find_and_remove_node(graph, fq.name) @@ -649,12 +649,20 @@ def rename_fqs_in_the_end(self, graph: Graph): def change_names(_, match): fq_node = match['fq'] input_node = get_node_input(fq_node, 0) + new_fq_name = copy(input_node.name) + if 'orig_node_name' in input_node: + new_fq_name = copy(input_node['orig_node_name']) + + input_node_outputs = get_all_node_outputs(input_node) + if all([op.type == 'FakeQuantize' for op in input_node_outputs]): + new_fq_name += '.{}'.format(fq_node.in_port(0).get_source().idx) fq_node['orig_fq_name'] = copy(fq_node.name) - fq_node.name = copy(input_node.name) + fq_node.name = copy(new_fq_name) - input_node['orig_node_name'] = copy(input_node.name) - input_node.name = '{original_name}/pre_fq_input'.format(original_name=input_node.name) + if 'orig_node_name' not in input_node: + input_node['orig_node_name'] = copy(input_node.name) + input_node.name = '{original_name}/pre_fq_input'.format(original_name=input_node.name) pattern = get_fq_result_pattern() apply_pattern( diff --git a/tools/pot/openvino/tools/pot/graph/special_patterns.py b/tools/pot/openvino/tools/pot/graph/special_patterns.py index a4dfe24008d35c..2f32378aadaab4 100644 --- a/tools/pot/openvino/tools/pot/graph/special_patterns.py +++ b/tools/pot/openvino/tools/pot/graph/special_patterns.py @@ -28,6 +28,26 @@ def create_swish_pattern(): return pattern.set_name('swish_activation').pattern +@registry_ignore_patterns('blocks') +def create_se_pattern(): + """ + Removing this pattern can drop accuracy after quantization of model w/ SE-blocks + """ + pattern = PatternBuilder() + pattern.insert_se(start_name='input', end_name='output') + return pattern.set_name('se_block').pattern + + +@registry_ignore_patterns('blocks') +def create_se_swish_pattern(): + """ + Removing this pattern can drop accuracy after quantization of model w/ SE-blocks + """ + pattern = PatternBuilder() + pattern.insert_se(start_name='input', end_name='output', is_swish=True) + return pattern.set_name('se_block_swish_activation').pattern + + @registry_ignore_patterns('blocks') def create_biased_op_pattern(): pattern = PatternBuilder() diff --git a/tools/pot/openvino/tools/pot/graph/transformer.py b/tools/pot/openvino/tools/pot/graph/transformer.py index 77194c19455ca9..44e1fb4e8e830e 100644 --- a/tools/pot/openvino/tools/pot/graph/transformer.py +++ b/tools/pot/openvino/tools/pot/graph/transformer.py @@ -54,7 +54,7 @@ def _insert_fake_quantize(self, graph): self.fq_optimization.find_and_replace_pattern(graph) graph.clean_up() - self.fq_propagation.find_nodes_fq_int(graph) + self.fq_propagation.delete_fq_non_quantizable_node_precision(graph) graph.clean_up() self.fq_name_swapper.rename_fqs_in_the_end(graph) diff --git a/tools/pot/openvino/tools/pot/statistics/statistic_graph_builder.py b/tools/pot/openvino/tools/pot/statistics/statistic_graph_builder.py index 634243604905c9..6e537a29604dd2 100644 --- a/tools/pot/openvino/tools/pot/statistics/statistic_graph_builder.py +++ b/tools/pot/openvino/tools/pot/statistics/statistic_graph_builder.py @@ -80,7 +80,7 @@ def insert_abs_max(self, node, type_stat, node_name, **kwargs): abs_node = Abs(node.graph, {"name": type_stat + node_name}).create_node() abs_node.in_port(0).connect(node.out_port(0)) max_op = create_op_node_with_second_input(node.graph, ReduceMax, int64_array(axis_const), - dict(name='abs_max_' + node.name)) + dict(name='abs_max_' + node_name)) abs_node.out_port(0).connect(max_op.in_port(0)) self.insert_result(node, max_op, type_stat) return None diff --git a/tools/pot/openvino/tools/pot/utils/telemetry.py b/tools/pot/openvino/tools/pot/utils/telemetry.py index 688e54c33b9951..6268cfa3b9d214 100644 --- a/tools/pot/openvino/tools/pot/utils/telemetry.py +++ b/tools/pot/openvino/tools/pot/utils/telemetry.py @@ -13,7 +13,11 @@ logger = get_logger(__name__) -def send_event(action, label, telemetry=tm.Telemetry(app_name='pot', app_version=pot_version)): +def get_tid_telemetry(): + return 'UA-17808594-29' + + +def send_event(action, label, telemetry=tm.Telemetry(tid=get_tid_telemetry(), app_name='pot', app_version=pot_version)): try: telemetry.send_event('pot', action, label) except Exception as e: # pylint: disable=broad-except @@ -22,7 +26,7 @@ def send_event(action, label, telemetry=tm.Telemetry(app_name='pot', app_version def send_configuration(algo_config, engine, interface='API'): try: - telemetry = tm.Telemetry(app_name='pot', app_version=pot_version) + telemetry = tm.Telemetry(tid=get_tid_telemetry(), app_name='pot', app_version=pot_version) target_device = ','.join(set(algorithm['params'].get('target_device', 'ANY') for algorithm in algo_config)) algorithms = {f'algorithm_{i}': algorithm['name'] for i, algorithm in enumerate(algo_config)} @@ -54,7 +58,7 @@ def send_configuration(algo_config, engine, interface='API'): def start_session_telemetry(): try: - telemetry = tm.Telemetry(app_name='pot', app_version=pot_version) + telemetry = tm.Telemetry(tid=get_tid_telemetry(), app_name='pot', app_version=pot_version) telemetry.start_session('pot') return telemetry except Exception as e: # pylint: disable=broad-except diff --git a/tools/pot/tests/data/models/lstm_example/lstm_example.json b/tools/pot/tests/data/models/lstm_example/lstm_example.json new file mode 100644 index 00000000000000..de45bbb1b86724 --- /dev/null +++ b/tools/pot/tests/data/models/lstm_example/lstm_example.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ba5a652c26a0ff2d72d0a20fa4ea89801432e1a07f130d434bbac51f87704987 +size 186 diff --git a/tools/pot/tests/data/models/lstm_example/lstm_example.onnx b/tools/pot/tests/data/models/lstm_example/lstm_example.onnx new file mode 100644 index 00000000000000..30507001ee9d51 --- /dev/null +++ b/tools/pot/tests/data/models/lstm_example/lstm_example.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43ebd524dc790f0cdf08f4693f74d9b5be550c503c67aa1819bd13496fbee0be +size 341880 diff --git a/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.bin b/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.bin new file mode 100644 index 00000000000000..6610aea14ea82b --- /dev/null +++ b/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0af1173b44db9f52b9878032b87679cc16521ec0c21fc413228e0854da4efed0 +size 526864 diff --git a/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.json b/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.json new file mode 100644 index 00000000000000..4fc2ca9cd5e4f0 --- /dev/null +++ b/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de67711db3e1fb404a8b61be29954ab5b336d76b8cf7d3c5c98f7b9faab7c6e4 +size 283 diff --git a/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.xml b/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.xml new file mode 100644 index 00000000000000..d7035fe9d8705a --- /dev/null +++ b/tools/pot/tests/data/models/multiple_outputs_net_example/multiple_outputs_net_example.xml @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eafca25515ecb19d073a96fbaa234c5c9004bf9646419bb1d3f9c0faa25c19c2 +size 12739 diff --git a/tools/pot/tests/data/reference_models/efficientnet_b0_example_ig_pt_pytorch.xml b/tools/pot/tests/data/reference_models/efficientnet_b0_example_ig_pt_pytorch.xml index 90adca11bf106c..a3087ffbf1b913 100644 --- a/tools/pot/tests/data/reference_models/efficientnet_b0_example_ig_pt_pytorch.xml +++ b/tools/pot/tests/data/reference_models/efficientnet_b0_example_ig_pt_pytorch.xml @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df841d3e81aa6476e54787bcfec5e334bee27b80bbad7c8446b0f7f120ca5e7e -size 570777 +oid sha256:181402cfe46282cf96d82f1e0b68f2ba5ccbcaccbb1ce3e712fd1b4cb5883917 +size 463708 diff --git a/tools/pot/tests/data/reference_models/lstm_example_pytorch.xml b/tools/pot/tests/data/reference_models/lstm_example_pytorch.xml new file mode 100644 index 00000000000000..c49048bca97158 --- /dev/null +++ b/tools/pot/tests/data/reference_models/lstm_example_pytorch.xml @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d0db9b3aa632378aea94c872a9d4d4b3798b72432cab942aea14893872d0f56 +size 126939 diff --git a/tools/pot/tests/data/reference_models/multiple_outputs_net_example_dldt.xml b/tools/pot/tests/data/reference_models/multiple_outputs_net_example_dldt.xml new file mode 100644 index 00000000000000..1d8619041a5f45 --- /dev/null +++ b/tools/pot/tests/data/reference_models/multiple_outputs_net_example_dldt.xml @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76959e68b61e35bca1e4d0a815a2fdd2a50fbfa1ca6d4cb6218d6d57f76603b2 +size 23366 diff --git a/tools/pot/tests/test_graph.py b/tools/pot/tests/test_graph.py index febe190f2c707e..5ee601eb5653aa 100755 --- a/tools/pot/tests/test_graph.py +++ b/tools/pot/tests/test_graph.py @@ -18,13 +18,14 @@ GNA_CONFIG_PATH = HARDWARE_CONFIG_PATH / 'gna.json' TEST_MODELS = [ - ('mobilenetv2_example', 'pytorch'), - ('resnet_example', 'pytorch'), - ('googlenet_example', 'pytorch'), - ('mobilenetv2_ssd_example', 'pytorch'), - ('densenet121_example', 'pytorch'), - ('multiple_out_ports_net', 'tf'), # multiple output ports in node case check, - # ('rm_nnet4a', 'kaldi') + ('mobilenetv2_example', 'pytorch', 'ANY'), + ('resnet_example', 'pytorch', 'ANY'), + ('googlenet_example', 'pytorch', 'ANY'), + ('mobilenetv2_ssd_example', 'pytorch', 'ANY'), + ('densenet121_example', 'pytorch', 'ANY'), + ('multiple_out_ports_net', 'tf', 'ANY'), + ('lstm_example', 'pytorch', 'GNA'), + ('multiple_outputs_net_example', 'dldt', 'GNA') ] CASCADE_MAP = Dict({ @@ -37,15 +38,16 @@ @pytest.mark.parametrize( - 'model_name, model_framework', TEST_MODELS, + 'model_name, model_framework, target_device', TEST_MODELS, ids=['{}_{}'.format(m[0], m[1]) for m in TEST_MODELS]) -def test_build_quantization_graph(tmp_path, models, model_name, model_framework): +def test_build_quantization_graph(tmp_path, models, model_name, model_framework, target_device): model = models.get(model_name, model_framework, tmp_path) - model = load_model(model.model_params) + model = load_model(model.model_params, target_device=target_device) - hardware_config = HardwareConfig.from_json(CPU_CONFIG_PATH.as_posix()) - if model_framework == 'kaldi': + if target_device == 'GNA': hardware_config = HardwareConfig.from_json(GNA_CONFIG_PATH.as_posix()) + else: + hardware_config = HardwareConfig.from_json(CPU_CONFIG_PATH.as_posix()) quantization_model = GraphTransformer(hardware_config).insert_fake_quantize(model) @@ -246,27 +248,21 @@ def test_multibranch_propagation_without_fq_moving(): MODELS_WITH_LSTM = [ - # ('rm_lstm4f', 'kaldi', { - # 'prev_memory_output69': - # ['next_lstm_output108', 'lstmprojectedstreams/Shape', 'input_fullyconnected/WithoutBiases'], - # 'prev_memory_state82': - # ['state_filtered_tahn100', 'clamp_scaleshift101/Mul_', 'next_lstm_state98'], - # 'prev_memory_output': - # ['next_lstm_output', 'affinetransform/WithoutBiases'], - # 'prev_memory_state': - # ['state_filtered_tahn', 'clamp_scaleshift/Mul_', 'next_lstm_state'] - # }) + ('lstm_example', 'pytorch', { + 'LSTM_15/TensorIterator/22/variable_1': + ['Assign_298'], + 'LSTM_15/TensorIterator/24/variable_2': + ['Assign_305'], + 'LSTM_19/TensorIterator/22/variable_1': + ['Assign_327'], + 'LSTM_19/TensorIterator/24/variable_2': + ['Assign_334'] + }) ] -@pytest.fixture(scope='module', params=MODELS_WITH_LSTM, - ids=['{}_{}'.format(m[0], m[1]) for m in MODELS_WITH_LSTM]) -def _params(request): - return request.param - - -def test_lstm_ends(_params, tmp_path, models): - model_name, model_framework, lstm_ends_ref = _params +def test_lstm_ends(tmp_path, models): + model_name, model_framework, lstm_ends_ref = MODELS_WITH_LSTM[0] model = models.get(model_name, model_framework, tmp_path) model = load_model(model.model_params) read_values = get_nodes_by_type(model, ['ReadValue']) diff --git a/tools/pot/tests/test_tensor_statistics.py b/tools/pot/tests/test_tensor_statistics.py index 99489dadb452e4..8998c803b357c2 100644 --- a/tools/pot/tests/test_tensor_statistics.py +++ b/tools/pot/tests/test_tensor_statistics.py @@ -7,6 +7,8 @@ from openvino.tools.pot.statistics.function_selector import AGGREGATION_FN, ACTIVATIONS_STATS_FN, WEIGHTS_STATS_FN, \ get_aggregation_function, get_stats_function_for_activations, get_stats_function_for_weights, PERCHANNEL, PERTENSOR +from openvino.tools.pot.algorithms.quantization.fake_quantize import get_num_levels + INPUT_SHAPES = [(2, 2, 1), (2, 2, 2)] AGG_INPUTS = [np.reshape(np.array(range(np.prod(shape)), dtype=np.float32), shape) for shape in INPUT_SHAPES] @@ -137,14 +139,17 @@ def test_weights_function(name, scale): WEIGHTS_STATS_FN[PERCHANNEL].registry_dict.keys()] -@pytest.mark.parametrize( - 'name, transpose', WEIGHTS_CH_STATS_FUNCTIONS, - ids=['{}_{}'.format(fn[0], fn[1]) for fn in WEIGHTS_CH_STATS_FUNCTIONS]) -def test_weights_transpose_function(name, transpose): - fn = get_stats_function_for_weights(name, PERCHANNEL) - if name in ['quantile', 'abs_quantile']: - result = fn(INPUT, q=1e-2, transpose=transpose) - else: - result = fn(INPUT, transpose=transpose) - expected = GOLD_VALUES_CH_TRANS_WEIGHT_FUNCTIONS[name] - np.testing.assert_almost_equal(result, expected) +NUM_LEVELS_PARAMS = [ + (np.random.randint, (0, 2, (3, 100, 100)), 1, 1), + (np.random.randint, (-32, 32, (3, 100, 100)), 64, 1), + (np.random.randint, (-32, 32, (3, 100, 100)), 64, 1/512), + (np.random.rand, (3, 100, 100), -1, 1), + (np.random.randint, (0, 1, (3, 100, 100)), 0, 1) +] + + +@pytest.mark.parametrize('gen_func,params,expected,coef', NUM_LEVELS_PARAMS) +def test_get_num_levels_function(gen_func, params, expected, coef): + test_1 = gen_func(*params) * coef + result = get_num_levels(test_1) + assert result == expected