Merge remote-tracking branch 'upstream/master' into debian-packages

This commit is contained in:
Ilya Lavrenov 2021-12-27 16:06:40 +03:00
commit ab53b80e56
2668 changed files with 68864 additions and 39043 deletions

View File

@ -116,8 +116,8 @@ jobs:
python3 -m pip install -r $(REPO_DIR)/inference-engine/ie_bridges/python/wheel/requirements-dev.txt python3 -m pip install -r $(REPO_DIR)/inference-engine/ie_bridges/python/wheel/requirements-dev.txt
# For running Python API tests # For running Python API tests
python3 -m pip install -r $(REPO_DIR)/inference-engine/ie_bridges/python/src/requirements-dev.txt python3 -m pip install -r $(REPO_DIR)/inference-engine/ie_bridges/python/src/requirements-dev.txt
# For running PaddlePaddle frontend unit tests # For running Paddle frontend unit tests
python3 -m pip install -r $(REPO_DIR)/src/core/tests/frontend/paddlepaddle/requirements_dev.txt python3 -m pip install -r $(REPO_DIR)/src/core/tests/frontend/paddle/requirements_dev.txt
# For running ONNX frontend unit tests # For running ONNX frontend unit tests
python3 -m pip install -r $(REPO_DIR)/src/core/tests/requirements_test_onnx.txt python3 -m pip install -r $(REPO_DIR)/src/core/tests/requirements_test_onnx.txt
# For MO unit tests # For MO unit tests
@ -203,6 +203,9 @@ jobs:
- script: ls -alR $(INSTALL_DIR) - script: ls -alR $(INSTALL_DIR)
displayName: 'List install files' displayName: 'List install files'
- script: python3 -m pip install openvino-dev --find-links=$(INSTALL_DIR)/tools
displayName: 'Install wheels'
- script: | - script: |
set -e set -e
mkdir $(INSTALL_DIR)/opencv/ mkdir $(INSTALL_DIR)/opencv/
@ -241,15 +244,15 @@ jobs:
. $(SETUPVARS) -pyver 3.8 && python3 -m pytest -s $(INSTALL_DIR)/tests/mo/unit_tests --junitxml=TEST-ModelOptimizer.xml . $(SETUPVARS) -pyver 3.8 && python3 -m pytest -s $(INSTALL_DIR)/tests/mo/unit_tests --junitxml=TEST-ModelOptimizer.xml
displayName: 'Model Optimizer UT' displayName: 'Model Optimizer UT'
continueOnError: false continueOnError: false
enabled: false enabled: true
- script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/ov_core_unit_tests --gtest_print_time=1 --gtest_filter=-*IE_GPU* --gtest_output=xml:TEST-NGraphUT.xml - script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/ov_core_unit_tests --gtest_print_time=1 --gtest_filter=-*IE_GPU* --gtest_output=xml:TEST-NGraphUT.xml
workingDirectory: $(INSTALL_TEST_DIR) workingDirectory: $(INSTALL_TEST_DIR)
displayName: 'OV Core UT' displayName: 'OV Core UT'
continueOnError: false continueOnError: false
- script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/paddlepaddle_tests --gtest_print_time=1 --gtest_output=xml:TEST-PaddlePaddle.xml - script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/paddle_tests --gtest_print_time=1 --gtest_output=xml:TEST-Paddle.xml
displayName: 'PaddlePaddle Frontend UT' displayName: 'Paddle Frontend UT'
continueOnError: false continueOnError: false
- script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/tensorflow_tests --gtest_print_time=1 --gtest_output=xml:TEST-Tensorflow.xml - script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/tensorflow_tests --gtest_print_time=1 --gtest_output=xml:TEST-Tensorflow.xml
@ -290,7 +293,7 @@ jobs:
displayName: 'IE FuncTests' displayName: 'IE FuncTests'
continueOnError: false continueOnError: false
- script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/templateFuncTests --gtest_filter=*smoke* --gtest_output=xml:TEST-templateFuncTests.xml - script: . $(SETUPVARS) && $(INSTALL_TEST_DIR)/ov_template_func_tests --gtest_filter=*smoke* --gtest_output=xml:TEST-templateFuncTests.xml
displayName: 'TEMPLATE FuncTests' displayName: 'TEMPLATE FuncTests'
continueOnError: false continueOnError: false
@ -324,17 +327,17 @@ jobs:
continueOnError: false continueOnError: false
- script: | - script: |
export PATH=$HOME/.local/bin:$PATH
export IE_APP_PATH=$(INSTALL_DIR)/samples_bin export IE_APP_PATH=$(INSTALL_DIR)/samples_bin
export IE_APP_PYTHON_PATH=$(INSTALL_DIR)/samples/python/ export IE_APP_PYTHON_PATH=$(INSTALL_DIR)/samples/python/
export SHARE=$(INSTALL_DIR)/tests/smoke_tests/samples_smoke_tests_data/ export SHARE=$(INSTALL_DIR)/tests/smoke_tests/samples_smoke_tests_data/
export WORKSPACE=$(INSTALL_DIR) export WORKSPACE=$(INSTALL_DIR)
export IE_APP_PYTHON_TOOL_PATH=$(INSTALL_DIR)/tools/
. $(SETUPVARS) && python3 -m pytest $(INSTALL_DIR)/tests/smoke_tests/ --env_conf $(INSTALL_DIR)/tests/smoke_tests/env_config.yml -s --junitxml=$(BUILD_DIR)/TEST-SamplesSmokeTests.xml . $(SETUPVARS) && python3 -m pytest $(INSTALL_DIR)/tests/smoke_tests/ --env_conf $(INSTALL_DIR)/tests/smoke_tests/env_config.yml -s --junitxml=$(BUILD_DIR)/TEST-SamplesSmokeTests.xml
workingDirectory: $(INSTALL_DIR)/samples_bin workingDirectory: $(INSTALL_DIR)/samples_bin
displayName: 'Samples Smoke Tests' displayName: 'Samples Smoke Tests'
continueOnError: false continueOnError: false
condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON') condition: eq(variables['CMAKE_BUILD_SHARED_LIBS'], 'ON')
enabled: false enabled: true
- script: | - script: |
export DATA_PATH=$(MODELS_PATH) export DATA_PATH=$(MODELS_PATH)
@ -353,7 +356,7 @@ jobs:
workingDirectory: $(LAYER_TESTS_DIR) workingDirectory: $(LAYER_TESTS_DIR)
displayName: 'Layer Tests' displayName: 'Layer Tests'
continueOnError: false continueOnError: false
enabled: false enabled: true
- task: PublishTestResults@2 - task: PublishTestResults@2
condition: always() condition: always()

View File

@ -35,7 +35,7 @@ jobs:
- checkout: none - checkout: none
- script: git -C ~/work/openvino checkout -m --recurse-submodules $(Build.SourceVersion) - script: git -C ~/work/openvino checkout -m $(Build.SourceVersion) && git -C ~/work/openvino submodule update --init --recursive
displayName: checkout displayName: checkout
# Should be after 'Install dependencies' because Git lfs is not installed # Should be after 'Install dependencies' because Git lfs is not installed
@ -70,8 +70,8 @@ jobs:
env -C ~/work env -C ~/work
./buildreleasenolto.sh ./buildreleasenolto.sh
libinference_engine_preproc.so libinference_engine_preproc.so
MKLDNNPlugin ov_intel_cpu_plugin
clDNNPlugin ov_intel_gpu_plugin
clDNN_unit_tests64 clDNN_unit_tests64
gpuFuncTests gpuFuncTests
displayName: Build Lin displayName: Build Lin

View File

@ -98,7 +98,7 @@ jobs:
-DENABLE_OPENCV=OFF -DENABLE_OPENCV=OFF
-DENABLE_CPPLINT=OFF -DENABLE_CPPLINT=OFF
-DENABLE_TESTS=OFF -DENABLE_TESTS=OFF
-DENABLE_MKL_DNN=ON -DENABLE_INTEL_CPU=ON
-DENABLE_INTEL_GPU=OFF -DENABLE_INTEL_GPU=OFF
-DENABLE_PROFILING_ITT=OFF -DENABLE_PROFILING_ITT=OFF
-DENABLE_SAMPLES=OFF -DENABLE_SAMPLES=OFF

View File

@ -83,7 +83,7 @@ jobs:
displayName: 'Make dir' displayName: 'Make dir'
- script: | - script: |
certutil -urlcache -split -f https://openvinoweb.z5.web.core.windows.net/incredibuild/install_ib_console.bat install_ib_console.bat curl -O https://openvinoweb.z5.web.core.windows.net/incredibuild/install_ib_console.bat
call install_ib_console.bat call install_ib_console.bat
workingDirectory: $(WORK_DIR) workingDirectory: $(WORK_DIR)
displayName: 'Install IncrediBuild' displayName: 'Install IncrediBuild'
@ -109,17 +109,18 @@ jobs:
python -m pip install --upgrade pip python -m pip install --upgrade pip
rem For running Python API tests rem For running Python API tests
python -m pip install -r $(REPO_DIR)\inference-engine\ie_bridges\python\src\requirements-dev.txt python -m pip install -r $(REPO_DIR)\inference-engine\ie_bridges\python\src\requirements-dev.txt
rem For running PaddlePaddle frontend unit tests python -m pip install -r $(REPO_DIR)\inference-engine\ie_bridges\python\wheel\requirements-dev.txt
python -m pip install -r $(REPO_DIR)\src\core\tests\frontend\paddlepaddle\requirements_dev.txt rem For running Paddle frontend unit tests
python -m pip install -r $(REPO_DIR)\src\core\tests\frontend\paddle\requirements_dev.txt
rem For running ONNX frontend unit tests rem For running ONNX frontend unit tests
python -m pip install -r $(REPO_DIR)\src\core\tests\requirements_test_onnx.txt python -m pip install -r $(REPO_DIR)\src\core\tests\requirements_test_onnx.txt
rem For MO unit tests rem For MO unit tests
python -m pip install -r $(REPO_DIR)\tools\mo\requirements.txt python -m pip install -r $(REPO_DIR)\tools\mo\requirements.txt
python -m pip install -r $(REPO_DIR)\tools\mo\requirements_dev.txt python -m pip install -r $(REPO_DIR)\tools\mo\requirements_dev.txt
rem Speed up build rem Speed up build
certutil -urlcache -split -f https://github.com/Kitware/CMake/releases/download/v$(CMAKE_VERSION)/cmake-$(CMAKE_VERSION)-windows-x86_64.zip cmake-$(CMAKE_VERSION)-windows-x86_64.zip powershell -command "Invoke-WebRequest https://github.com/Kitware/CMake/releases/download/v$(CMAKE_VERSION)/cmake-$(CMAKE_VERSION)-windows-x86_64.zip -OutFile cmake-$(CMAKE_VERSION)-windows-x86_64.zip"
powershell -command "Expand-Archive -Force cmake-$(CMAKE_VERSION)-windows-x86_64.zip" powershell -command "Expand-Archive -Force cmake-$(CMAKE_VERSION)-windows-x86_64.zip"
certutil -urlcache -split -f https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip ninja-win.zip powershell -command "Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip -OutFile ninja-win.zip"
powershell -command "Expand-Archive -Force ninja-win.zip" powershell -command "Expand-Archive -Force ninja-win.zip"
git clone https://github.com/google/gtest-parallel.git git clone https://github.com/google/gtest-parallel.git
workingDirectory: $(WORK_DIR) workingDirectory: $(WORK_DIR)
@ -132,7 +133,7 @@ jobs:
- script: | - script: |
set PATH=$(WORK_DIR)\ninja-win;%PATH% set PATH=$(WORK_DIR)\ninja-win;%PATH%
call "$(MSVS_VARS_PATH)" && $(CMAKE_CMD) -G "Ninja Multi-Config" -DENABLE_ONEDNN_FOR_GPU=OFF -DENABLE_INTEL_GNA=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_INTEL_GPU=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_GAPI_PREPROCESSING=$(CMAKE_BUILD_SHARED_LIBS) -DBUILD_SHARED_LIBS=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_REQUIREMENTS_INSTALL=OFF -DENABLE_FASTER_BUILD=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" -DPYTHON_INCLUDE_DIR="C:\hostedtoolcache\windows\Python\3.7.6\x64\include" -DPYTHON_LIBRARY="C:\hostedtoolcache\windows\Python\3.7.6\x64\libs\python37.lib" -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_CMD) -G "Ninja Multi-Config" -DENABLE_ONEDNN_FOR_GPU=OFF -DENABLE_WHEEL=ON -DENABLE_INTEL_GNA=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_INTEL_GPU=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_GAPI_PREPROCESSING=$(CMAKE_BUILD_SHARED_LIBS) -DBUILD_SHARED_LIBS=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_REQUIREMENTS_INSTALL=OFF -DENABLE_FASTER_BUILD=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" -DPYTHON_INCLUDE_DIR="C:\hostedtoolcache\windows\Python\3.7.6\x64\include" -DPYTHON_LIBRARY="C:\hostedtoolcache\windows\Python\3.7.6\x64\libs\python37.lib" -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) workingDirectory: $(BUILD_DIR)
displayName: 'CMake' displayName: 'CMake'
@ -155,6 +156,9 @@ jobs:
- script: dir $(INSTALL_DIR) /s - script: dir $(INSTALL_DIR) /s
displayName: 'List install files' displayName: 'List install files'
- script: python -m pip install openvino-dev --find-links=$(INSTALL_DIR)\tools
displayName: 'Install Wheels'
- script: call "$(MSVS_VARS_PATH)" && $(CMAKE_CMD) -DCMAKE_C_COMPILER:PATH="$(MSVC_COMPILER_PATH)" -DCMAKE_CXX_COMPILER:PATH="$(MSVC_COMPILER_PATH)" $(REPO_DIR)\tests\samples_tests - script: call "$(MSVS_VARS_PATH)" && $(CMAKE_CMD) -DCMAKE_C_COMPILER:PATH="$(MSVC_COMPILER_PATH)" -DCMAKE_CXX_COMPILER:PATH="$(MSVC_COMPILER_PATH)" $(REPO_DIR)\tests\samples_tests
workingDirectory: $(BUILD_SAMPLES_TESTS_DIR) workingDirectory: $(BUILD_SAMPLES_TESTS_DIR)
displayName: 'CMake' displayName: 'CMake'
@ -191,7 +195,6 @@ jobs:
set IE_APP_PYTHON_PATH=$(INSTALL_DIR)\samples\python\ set IE_APP_PYTHON_PATH=$(INSTALL_DIR)\samples\python\
set SHARE=$(INSTALL_DIR)\tests\smoke_tests\samples_smoke_tests_data\ set SHARE=$(INSTALL_DIR)\tests\smoke_tests\samples_smoke_tests_data\
set WORKSPACE=$(INSTALL_DIR) set WORKSPACE=$(INSTALL_DIR)
set IE_APP_PYTHON_TOOL_PATH=$(INSTALL_DIR)\tools\
python -m pytest $(INSTALL_DIR)\tests\smoke_tests\ --env_conf $(INSTALL_DIR)\tests\smoke_tests\env_config.yml -s --junitxml=TEST-SamplesSmokeTests.xml python -m pytest $(INSTALL_DIR)\tests\smoke_tests\ --env_conf $(INSTALL_DIR)\tests\smoke_tests\env_config.yml -s --junitxml=TEST-SamplesSmokeTests.xml
workingDirectory: $(INSTALL_DIR) workingDirectory: $(INSTALL_DIR)
displayName: 'Samples Smoke Tests' displayName: 'Samples Smoke Tests'
@ -207,8 +210,8 @@ jobs:
displayName: 'OV Core UT' displayName: 'OV Core UT'
continueOnError: false continueOnError: false
- script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\paddlepaddle_tests --gtest_print_time=1 --gtest_output=xml:TEST-PaddlePaddle.xml - script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\paddle_tests --gtest_print_time=1 --gtest_output=xml:TEST-Paddle.xml
displayName: 'PaddlePaddle Frontend UT' displayName: 'Paddle Frontend UT'
continueOnError: false continueOnError: false
- script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\tensorflow_tests --gtest_print_time=1 --gtest_output=xml:TEST-Tensorflow.xml - script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\tensorflow_tests --gtest_print_time=1 --gtest_output=xml:TEST-Tensorflow.xml
@ -250,7 +253,7 @@ jobs:
displayName: 'IE FuncTests' displayName: 'IE FuncTests'
continueOnError: false continueOnError: false
- script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\templateFuncTests --gtest_output=xml:TEST-templateFuncTests.xml - script: call $(SETUPVARS) && $(INSTALL_TEST_DIR)\ov_template_func_tests --gtest_output=xml:TEST-templateFuncTests.xml
displayName: 'TEMPLATE FuncTests' displayName: 'TEMPLATE FuncTests'
continueOnError: false continueOnError: false

View File

@ -59,7 +59,7 @@ jobs:
- script: | - script: |
rem Speed up build rem Speed up build
certutil -urlcache -split -f https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip ninja-win.zip powershell -command "Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip -OutFile ninja-win.zip"
powershell -command "Expand-Archive -Force ninja-win.zip" powershell -command "Expand-Archive -Force ninja-win.zip"
workingDirectory: $(WORK_DIR) workingDirectory: $(WORK_DIR)
displayName: 'Install dependencies' displayName: 'Install dependencies'

View File

@ -60,7 +60,7 @@ RUN cmake .. \
-DENABLE_OPENCV=OFF \ -DENABLE_OPENCV=OFF \
-DENABLE_CPPLINT=OFF \ -DENABLE_CPPLINT=OFF \
-DENABLE_TESTS=OFF \ -DENABLE_TESTS=OFF \
-DENABLE_MKL_DNN=ON \ -DENABLE_INTEL_CPU=ON \
-DENABLE_INTEL_GPU=OFF \ -DENABLE_INTEL_GPU=OFF \
-DENABLE_PROFILING_ITT=OFF \ -DENABLE_PROFILING_ITT=OFF \
-DENABLE_SAMPLES=OFF \ -DENABLE_SAMPLES=OFF \

139
.github/github_org_control/check_org.py vendored Normal file
View File

@ -0,0 +1,139 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
"""
Check GitHub organization and invite members
"""
# pylint: disable=fixme,no-member,too-many-locals
import sys
from pathlib import Path
from argparse import ArgumentParser
sys.path.append(str(Path(__file__).resolve().parents[1]))
from github_org_control.configs import Config
from github_org_control.github_api import GithubOrgApi, get_dev_emails, print_users
from github_org_control.ldap_api import LdapApi, print_user_info, InfoLevel
def remove_members(gh_api, cfg_emails, org_emails, dev_emails, org_emails_no_in_ldap):
"""Checks and remove members"""
print(
f"\n{'=' * 10} Check accounts below and remove from the GitHub organization or "
f"configuration {'=' * 10}"
)
cfg_emails_no_in_org = sorted(cfg_emails.difference(org_emails))
print(
f"\nCfg developer emails - absent in GitHub organization {len(cfg_emails_no_in_org)}:",
"; ".join(cfg_emails_no_in_org),
)
non_member_ignored_logins = set(Config().IGNORE_LOGINS).difference(
set(gh_api.org_members_by_login.keys())
)
print(
f"\nIgnored logins - absent in GitHub organization {len(non_member_ignored_logins)}:\n",
"\n".join(non_member_ignored_logins),
)
org_emails_no_in_dev = sorted(org_emails.difference(dev_emails))
print(
f"\nOrg member emails - absent in cfg and LDAP PDLs {len(org_emails_no_in_dev)}:",
"; ".join(org_emails_no_in_dev),
)
print(
f"\nOrg member emails - absent in LDAP at all {len(org_emails_no_in_ldap)}:",
"; ".join(sorted(org_emails_no_in_ldap)),
)
print("\nOrg members - no real name:")
members_to_fix_name = sorted(gh_api.members_to_fix_name, key=lambda member: member.email)
print_users(members_to_fix_name)
print(
"\nOrg member emails - no real name:",
"; ".join([member.email.lower() for member in members_to_fix_name]),
)
print("\nOrg members - no Intel emails:")
print_users(gh_api.members_to_remove)
gh_api.remove_users(org_emails_no_in_ldap | gh_api.members_to_remove)
def main():
"""The main entry point function"""
arg_parser = ArgumentParser()
arg_parser.add_argument(
"--cfg-file",
metavar="PATH",
default=Config.default_cfg_path,
help=f"Path to json configuration file, e.g. {Config.default_cfg_path}",
)
arg_parser.add_argument("--teams", action="store_true", help="Check GitHub teams")
arg_parser.add_argument("--no-ldap", action="store_true", help="Don't use LDAP info")
args, unknown_args = arg_parser.parse_known_args()
Config(args.cfg_file, unknown_args)
gh_api = GithubOrgApi()
if args.teams:
gh_api.get_org_teams()
return
cfg_emails = get_dev_emails()
print(f"\nCfg developer emails {len(cfg_emails)}:", "; ".join(sorted(cfg_emails)))
dev_emails = set()
dev_emails.update(cfg_emails)
if not args.no_ldap:
ldap_api = LdapApi()
ldap_emails = ldap_api.get_user_emails()
dev_emails.update(ldap_emails)
print(f"\nLDAP developer emails {len(ldap_emails)}:", "; ".join(sorted(ldap_emails)))
cfg_emails_no_in_ldap = ldap_api.get_absent_emails(cfg_emails)
print(
f"\nCfg developer emails - absent in LDAP at all {len(cfg_emails_no_in_ldap)}:",
"; ".join(sorted(cfg_emails_no_in_ldap)),
)
cfg_ldap_inters = cfg_emails.intersection(ldap_emails)
print(
f"\nCfg developer emails - present in LDAP developers {len(cfg_ldap_inters)}:",
"; ".join(sorted(cfg_ldap_inters)),
)
org_emails = gh_api.get_org_emails()
print(f"\nOrg emails {len(org_emails)}:", "; ".join(sorted(org_emails)))
org_emails_no_in_ldap = set()
if not args.no_ldap:
org_ldap_diff = org_emails.difference(ldap_emails)
print(
f"\nOrg member emails - absent in LDAP developers {len(org_ldap_diff)}:",
"; ".join(sorted(org_ldap_diff)),
)
for email in org_ldap_diff:
user_info = ldap_api.get_user_info_by_email(email)
if user_info:
print_user_info(user_info, InfoLevel.PDL)
else:
org_emails_no_in_ldap.add(email)
org_pendig_invitation_emails = gh_api.get_org_invitation_emails()
invite_emails = dev_emails.difference(org_emails).difference(org_pendig_invitation_emails)
print(f"\nInvite emails {len(invite_emails)}:", "; ".join(sorted(invite_emails)))
valid_github_users = gh_api.get_valid_github_users(invite_emails)
gh_api.invite_users(valid_github_users)
remove_members(gh_api, cfg_emails, org_emails, dev_emails, org_emails_no_in_ldap)
if __name__ == "__main__":
main()

View File

@ -10,11 +10,13 @@ Check GitHub PRs and set labels by type and categories, e.g. 'ExternalPR', 'cate
import re import re
import sys import sys
import datetime import datetime
from argparse import ArgumentParser
from enum import Enum from enum import Enum
from pathlib import Path
from argparse import ArgumentParser
import github_api sys.path.append(str(Path(__file__).resolve().parents[1]))
from configs import Config from github_org_control import github_api
from github_org_control.configs import Config
class PrType(Enum): class PrType(Enum):

View File

@ -8,8 +8,10 @@
"lab-nerval", "lab-nerval",
"lab-nerval-onnx-ci", "lab-nerval-onnx-ci",
"onnx-watchdog-agent", "onnx-watchdog-agent",
"dependabot" "workbench-ci-bot",
"openvino-pot-ci"
], ],
"MAX_MEMBERS_TO_REMOVE": 15,
"EMAILS_FILE_PATH": "dev_emails-test.txt", "EMAILS_FILE_PATH": "dev_emails-test.txt",
"PROXIES": { "PROXIES": {
"HTTP_PROXY": null, "HTTP_PROXY": null,
@ -28,12 +30,16 @@
"openvino-ie-lpt-maintainers": "category: LP transformations", "openvino-ie-lpt-maintainers": "category: LP transformations",
"openvino-ie-multi-maintainers": "category: MULTI", "openvino-ie-multi-maintainers": "category: MULTI",
"openvino-ie-python-api-maintainers": "category: python api", "openvino-ie-python-api-maintainers": "category: python api",
"openvino-ie-template-maintainers": "category: TEMPLATE",
"openvino-ie-tests-maintainers": "category: IE Tests", "openvino-ie-tests-maintainers": "category: IE Tests",
"openvino-ie-vpu-maintainers": "category: VPU", "openvino-ie-vpu-maintainers": "category: VPU",
"openvino-mo-maintainers": "category: MO", "openvino-mo-maintainers": "category: MO",
"openvino-ngraph-maintainers": "category: nGraph", "openvino-ngraph-maintainers": "category: nGraph",
"openvino-scripts-maintainers": "category: build",
"openvino-tests-maintainers": "category: IE Tests", "openvino-tests-maintainers": "category: IE Tests",
"openvino-tools-maintainers": "category: tools", "openvino-tools-maintainers": "category: tools",
"openvino-configuration-mgmt": "category: dependency_changes" "openvino-pot-maintainers": "category: POT",
"openvino-configuration-mgmt": "category: dependency_changes",
"openvino-samples-maintainers": "category: samples"
} }
} }

View File

@ -15,7 +15,7 @@ from pathlib import Path
if sys.hexversion < 0x3060000: if sys.hexversion < 0x3060000:
raise Exception('Python version must be >= 3.6') raise Exception("Python version must be >= 3.6")
class ConfigException(Exception): class ConfigException(Exception):
@ -24,9 +24,11 @@ class ConfigException(Exception):
class Config: class Config:
"""Configuration wrapper""" """Configuration wrapper"""
_instance = None _instance = None
properties = None _properties = None
default_cfg_path = Path(__file__).resolve().parent / 'config.json'
default_cfg_path = Path(__file__).resolve().parent / "config.json"
def __new__(cls, *_args, **_kwargs): def __new__(cls, *_args, **_kwargs):
if not Config._instance: if not Config._instance:
@ -41,7 +43,7 @@ class Config:
:param args: List of argparse arguments with patterns: 'name=value' or 'name' :param args: List of argparse arguments with patterns: 'name=value' or 'name'
:type args: list :type args: list
""" """
if Config.properties: if Config._properties:
return return
self._file_path = file_path or Config.default_cfg_path self._file_path = file_path or Config.default_cfg_path
@ -53,10 +55,10 @@ class Config:
self._load_cfg() self._load_cfg()
self._parse_cli_args() self._parse_cli_args()
Config.properties = {} Config._properties = {}
for name, value in self._json_cfg.items(): for name, value in self._json_cfg.items():
if hasattr(self, name): if hasattr(self, name):
raise ConfigException(f'Duplicating prosperity: {name}') raise ConfigException(f"Duplicating prosperity: {name}")
property_value = self._args.get(name) or os.getenv(name) property_value = self._args.get(name) or os.getenv(name)
if property_value: if property_value:
# Try to set prosperity_value as Python literal structures, e.g. DRY_RUN=False # Try to set prosperity_value as Python literal structures, e.g. DRY_RUN=False
@ -65,49 +67,54 @@ class Config:
except Exception: except Exception:
pass pass
if not isinstance(property_value, type(value)): if not isinstance(property_value, type(value)):
raise ConfigException(f'Python type of {name} parameter must be {type(value)}') raise ConfigException(f"Python type of {name} parameter must be {type(value)}")
else: else:
property_value = value property_value = value
setattr(self, name, property_value) Config._properties[name] = property_value
Config.properties[name] = property_value
self.set_proxy() self.set_proxy()
def __getattr__(self, attr_name):
if attr_name in self._properties:
return self._properties.get(attr_name)
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attr_name}'")
def _load_cfg(self): def _load_cfg(self):
"""Load the json configuration file""" """Load the json configuration file"""
try: try:
with open(self._file_path) as conf: with open(self._file_path, encoding="utf-8") as conf:
self._json_cfg = json.load(conf) self._json_cfg = json.load(conf)
except Exception: except Exception as exc:
print('Failed to load configuration from:', self._file_path) raise ConfigException("Failed to load configuration from:", self._file_path) from exc
raise
def _parse_cli_args(self): def _parse_cli_args(self):
"""Parse argparse arguments with patterns: 'name=value' or 'name'""" """Parse argparse arguments with patterns: 'name=value' or 'name'"""
for cli_arg in self._cli_args: for cli_arg in self._cli_args:
arg = cli_arg.split('=') arg = cli_arg.split("=")
if arg[0] not in self._json_cfg: if arg[0] not in self._json_cfg:
raise ConfigException(f'Unsupported argument: {arg}') raise ConfigException(f"Unsupported argument: {arg}")
self._args[arg[0]] = True if len(arg) == 1 else '='.join(arg[1:]) self._args[arg[0]] = True if len(arg) == 1 else "=".join(arg[1:])
def get_properties(self): @property
def properties(self):
"""Get all properties as Dict""" """Get all properties as Dict"""
return self.properties return self._properties
def set_proxy(self): def set_proxy(self):
"""Set proxies""" """Set proxies"""
for proxy_name, url in self.properties['PROXIES'].items(): for proxy_name, url in self._properties["PROXIES"].items():
if url is not None: if url is not None:
print(f'Set proxy: {proxy_name}={url}') print(f"Set proxy: {proxy_name}={url}")
os.environ[proxy_name] = url os.environ[proxy_name] = url
def _test(): def _test():
"""Test and debug""" """Test and debug"""
print('Config.default_cfg_path:', Config.default_cfg_path) print("Config.default_cfg_path:", Config.default_cfg_path)
cfg = Config(cli_args=['DRY_RUN', 'PROXIES={"NO_PROXY": "localhost"}']) cfg = Config(cli_args=["DRY_RUN", 'PROXIES={"NO_PROXY": "localhost"}'])
print('Config.properties:', cfg.get_properties()) print("Config.properties:", cfg.properties)
print("cfg.PROXIES:", cfg.PROXIES)
if __name__ == '__main__': if __name__ == "__main__":
_test() _test()

384
.github/github_org_control/github_api.py vendored Normal file
View File

@ -0,0 +1,384 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
"""
GitHub API for controlling organization
"""
# pylint: disable=fixme,no-member
import re
import sys
import time
import typing
from pathlib import Path
from github import Github, GithubException, RateLimitExceededException, IncompletableObject
from github.PaginatedList import PaginatedList
sys.path.append(str(Path(__file__).resolve().parents[1]))
from github_org_control.configs import Config
class GithubApiException(Exception):
"""Base GitHub API exception"""
def is_valid_user(user):
"""Checks that user is valid github.Github object"""
try:
return user and user.login
except IncompletableObject:
return False
def is_user_ignored(user):
"""Checks that user should be ignored"""
if is_valid_user(user) and user.login.lower() not in Config().IGNORE_LOGINS:
return False
return True
def is_valid_name(name):
"""Checks that GitHub user's name is valid"""
return name and len(name) >= 3 and " " in name
def is_intel_email(email):
"""Checks that email is valid Intel email"""
return email and len(email) > 10 and " " not in email and email.lower().endswith("@intel.com")
def is_intel_company(company):
"""Checks that company contains intel"""
return company and "intel" in company.lower()
def is_valid_intel_user(user):
"""Checks that user is valid GitHub and Intel user"""
try:
return is_valid_user(user) and is_valid_name(user.name) and is_intel_email(user.email)
except IncompletableObject:
return False
def print_users(users):
"""Print list of users in different formats: list, set, PaginatedList"""
if isinstance(users, (list, set, PaginatedList)):
users_count = users.totalCount if isinstance(users, PaginatedList) else len(users)
print(f"GitHub users {users_count} (login - name - company - email - valid):")
else:
users = [users]
for user in users:
if not is_valid_user(user):
print("WRONG GitHub user: ???")
continue
try:
name = user.name
except IncompletableObject:
name = "???"
try:
company = user.company
except IncompletableObject:
company = "???"
try:
email = user.email
except IncompletableObject:
email = "???"
valid_check = "OK" if is_valid_intel_user(user) else "FIX"
if not is_intel_email(email):
valid_check += " email"
if not is_valid_name(name):
valid_check += " name"
print(f'{user.login} - "{name}" - "{company}" - {email} - {valid_check}')
def get_dev_emails():
"""
Read a file with developer emails. Supported email formats
first_name.last_name@intel.com
Import from Outlook: Last_name, First_name <first_name.last_name@intel.com>
"""
re_email = re.compile(r".+<(.+)>")
emails = set()
cfg = Config()
with open(cfg.properties["EMAILS_FILE_PATH"]) as file_obj:
for line in file_obj:
line = line.strip().lower()
if not line or line.startswith("#"):
continue
re_outlook_email = re_email.match(line)
if re_outlook_email:
line = re_outlook_email.group(1).strip()
if not is_intel_email(line):
print(f'Wrong email in {cfg.properties["EMAILS_FILE_PATH"]}: {line}')
continue
emails.add(line)
return emails
class GithubOrgApi:
"""Common API for GitHub organization"""
def __init__(self):
self._cfg = Config()
self.github = Github(self._cfg.GITHUB_TOKEN)
self.github_org = self.github.get_organization(self._cfg.GITHUB_ORGANIZATION)
self.repo = self.github.get_repo(f"{self._cfg.GITHUB_ORGANIZATION}/{self._cfg.GITHUB_REPO}")
self.github_users_by_email = {}
self.org_members_by_login = {}
self.members_to_remove = set()
self.members_to_fix_name = set()
def is_org_user(self, user):
"""Checks that user is a member of GitHub organization"""
if is_valid_user(user):
# user.get_organization_membership(self.github_org) doesn't work with org members
# permissions, GITHUB_TOKEN must be org owner now
return self.github_org.has_in_members(user)
return False
def get_org_emails(self):
"""Gets and prints emails of all GitHub organization members"""
org_members = self.github_org.get_members()
org_emails = set()
print(f"\nOrg members {org_members.totalCount} (login - name - company - email - valid):")
for org_member in org_members:
self.org_members_by_login[org_member.login.lower()] = org_member
print_users(org_member)
if is_intel_email(org_member.email):
email = org_member.email.lower()
org_emails.add(email)
self.github_users_by_email[email] = org_member
if not is_valid_name(org_member.name):
self.members_to_fix_name.add(org_member)
elif not is_user_ignored(org_member):
self.members_to_remove.add(org_member)
print("\nOrg members - no Intel emails:")
print_users(self.members_to_remove)
print("\nOrg members - no real name:")
print_users(self.members_to_fix_name)
print(
"\nOrg member emails - no real name:",
"; ".join([member.email.lower() for member in self.members_to_fix_name]),
)
return org_emails
def get_org_invitation_emails(self):
"""Gets GitHub organization teams prints info"""
org_invitations = self.github_org.invitations()
org_invitation_emails = set()
print(
f"\nOrg invitations {org_invitations.totalCount} "
"(login - name - company - email - valid):"
)
for org_invitation in org_invitations:
print_users(org_invitation)
if is_user_ignored(org_invitation):
continue
if is_intel_email(org_invitation.email):
org_invitation_emails.add(org_invitation.email.lower())
else:
print("Strange org invitation:", org_invitation)
print(
f"\nOrg invitation emails {len(org_invitation_emails)}:",
"; ".join(org_invitation_emails),
)
return org_invitation_emails
def get_org_teams(self):
"""Gets GitHub organization teams prints info"""
teams = []
org_teams = self.github_org.get_teams()
print("\nOrg teams count:", org_teams.totalCount)
for team in org_teams:
teams.append(team.name)
print(f"\nTeam: {team.name} - parent: {team.parent}")
repos = team.get_repos()
print("Repos:")
for repo in repos:
print(f" {repo.name} -", team.get_repo_permission(repo))
team_maintainers = team.get_members(role="maintainer")
team_maintainer_logins = set()
for maintainer in team_maintainers:
team_maintainer_logins.add(maintainer.login)
team_members = team.get_members(role="member")
team_member_logins = set()
for member in team_members:
team_member_logins.add(member.login)
members = team.get_members(role="all")
member_emails = []
print("Members (role - login - name - company - email - valid):")
for user in members:
if user.login in team_maintainer_logins:
print(" Maintainer - ", end="")
elif user.login in team_member_logins:
print(" Member - ", end="")
else:
# It is not possible to check child teams members
print(" ??? - ", end="")
print_users(user)
if is_intel_email(user.email) and not is_user_ignored(user):
member_emails.append(user.email.lower())
print(f"Intel emails {len(member_emails)}:", "; ".join(member_emails))
return teams
def get_github_user_by_email(self, email):
"""Gets GitHub user by email"""
if email in self.github_users_by_email:
return self.github_users_by_email.get(email)
def search_users():
paginated_users = self.github.search_users(f"{email} in:email")
# Minimize the GitHub Rate Limit
users = []
for user in paginated_users:
users.append(user)
if len(users) == 1:
return users[0]
if len(users) == 0:
return None
raise GithubApiException(
f"ERROR: Found {len(users)} GitHub accounts with the same email {email}"
)
try:
user = search_users()
except RateLimitExceededException:
print("WARNING: RateLimitExceededException")
time.sleep(30)
user = search_users()
self.github_users_by_email[email] = user
return user
def get_valid_github_users(self, emails):
"""Gets valid GitHub users by email and prints status"""
valid_users = set()
wrong_emails = set()
no_account_emails = set()
no_account_names = set()
print(f"\nGitHub users from {len(emails)} invite emails (email - status):")
for email in emails:
if not is_intel_email(email):
print(f"{email} - Non Intel email")
wrong_emails.add(email)
continue
# You can make up to 30 requests per minute; https://developer.github.com/v3/search/
time.sleep(2)
user = self.get_github_user_by_email(email)
if not user:
print(f"{email} - No valid GitHub account")
no_account_emails.add(email)
continue
if user.email and user.email.lower() == email:
if is_valid_name(user.name):
print(f"{email} - OK")
valid_users.add(user)
else:
print(f"{email} - No valid name in GitHub account: ", end="")
print_users(user)
no_account_names.add(email)
else:
print(f"{email} - Non public or wrong email in GitHub account: ", end="")
print_users(user)
no_account_emails.add(email)
print("\nValid users:")
print_users(valid_users)
print(f"\nWrong emails {len(wrong_emails)}:", "; ".join(wrong_emails))
print(
f"\nIntel emails - No valid GitHub account {len(no_account_emails)}:",
"; ".join(no_account_emails),
)
print(
f"\nIntel emails - No valid name in GitHub account {len(no_account_names)}:",
"; ".join(no_account_names),
)
return valid_users
def invite_users(self, users):
"""Invites users to GitHub organization and prints status"""
if not isinstance(users, typing.Iterable):
users = [users]
print(f"\nInvite {len(users)} users:")
for user in users:
if isinstance(user, str):
print(f"Email: {user}")
self.github_org.invite_user(email=user)
else:
print(f'{user.login} - "{user.name}" - {user.email} - ', end="")
try:
if is_user_ignored(user):
print("Ignored")
continue
if self._cfg.DRY_RUN:
print("Dry run")
continue
self.github_org.invite_user(user=user)
print("OK")
except GithubException as exc:
print(f'FAIL: {exc.data["errors"][0]["message"]}')
def remove_users(self, users):
"""Removes users from GitHub organization"""
if not isinstance(users, typing.Iterable):
users = [users]
print(f"\nRemove {len(users)} users:")
dry_run = self._cfg.DRY_RUN
if not dry_run and len(users) > self._cfg.MAX_MEMBERS_TO_REMOVE:
print(
"WARNING: Review is required for removing members more than "
f"{self._cfg.MAX_MEMBERS_TO_REMOVE}"
)
# TODO: Add notification
dry_run = True
for user in users:
member = self.get_github_user_by_email(user) if isinstance(user, str) else user
print(f'{member.login} - "{member.name}" - {member.email} - ', end="")
try:
if is_user_ignored(member):
print("Ignored")
continue
if dry_run:
print("Dry run")
continue
self.github_org.remove_from_membership(member)
print("OK")
except GithubException as exc:
print(f'FAIL: {exc.data["errors"][0]["message"]}')
def _test():
"""Test and debug"""
Config(cli_args=["DRY_RUN=True"])
dev_emails = get_dev_emails()
print("dev_emails:", dev_emails)
gh_api = GithubOrgApi()
gh_api.get_org_emails()
if __name__ == "__main__":
_test()

View File

@ -7,11 +7,14 @@ Gets info about users and groups via LDAP
# pylint: disable=fixme,no-member # pylint: disable=fixme,no-member
import sys
from enum import Enum from enum import Enum
from pathlib import Path
from ldap3 import Server, Connection, ALL, SUBTREE from ldap3 import Server, Connection, ALL, SUBTREE
from configs import Config sys.path.append(str(Path(__file__).resolve().parents[1]))
from github_org_control.configs import Config
class LdapApiException(Exception): class LdapApiException(Exception):
@ -20,49 +23,53 @@ class LdapApiException(Exception):
class InfoLevel(Enum): class InfoLevel(Enum):
"""Constants for printing user info from LDAP""" """Constants for printing user info from LDAP"""
PDL = 'PDL' # Public Distribution List (group of e-mail addresses)
FULL = 'Full' PDL = "PDL" # Public Distribution List (group of e-mail addresses)
FULL = "Full"
def print_user_info(info, info_level=None): def print_user_info(info, info_level=None):
"""Pretty-print of a user info data structure (dict). info_level is the InfoLevel Enum""" """Pretty-print of a user info data structure (dict). info_level is the InfoLevel Enum"""
if not info or not info.get('mail'): if not info or not info.get("mail"):
raise LdapApiException('ERROR: No info or absent mail') raise LdapApiException("ERROR: No info or absent mail")
def get_membership(): def get_membership():
if info_level == InfoLevel.PDL: if info_level == InfoLevel.PDL:
membership_info = ' PDLs:' membership_info = " PDLs:"
elif info_level == InfoLevel.FULL: elif info_level == InfoLevel.FULL:
membership_info = ' memberOf :' membership_info = " memberOf :"
else: else:
return '' return ""
# Grouping groups by purpose # Grouping groups by purpose
if info_level == InfoLevel.PDL: if info_level == InfoLevel.PDL:
sort_key = lambda i: i.split(',', 1)[0].lower() sort_key = lambda i: i.split(",", 1)[0].lower()
else: else:
sort_key = lambda i: i.split(',', 1)[1] + i.split(',', 1)[0].lower() sort_key = lambda i: i.split(",", 1)[1] + i.split(",", 1)[0].lower()
for item in sorted(info['memberOf'], key=sort_key): for item in sorted(info["memberOf"], key=sort_key):
if info_level == InfoLevel.PDL and 'OU=Delegated' not in item: if info_level == InfoLevel.PDL and "OU=Delegated" not in item:
continue continue
membership_info += f'\n {item}' membership_info += f"\n {item}"
return membership_info return membership_info
try: try:
text_info = \ text_info = (
f'\n{info["cn"]} <{info["mail"]}>; {info["sAMAccountName"]}; {info["employeeID"]}' \ f'\n{info["cn"]} <{info["mail"]}>; {info["sAMAccountName"]}; {info["employeeID"]}'
f'\n Org group: {info["intelSuperGroupDescr"]} ({info["intelSuperGroupShortName"]}) /'\ f'\n Org group: {info["intelSuperGroupDescr"]} ({info["intelSuperGroupShortName"]}) /'
f' {info["intelGroupDescr"]} ({info["intelGroupShortName"]}) /' \ f' {info["intelGroupDescr"]} ({info["intelGroupShortName"]}) /'
f' {info["intelDivisionDescr"]} ({info["intelDivisionShortName"]}) /' \ f' {info["intelDivisionDescr"]} ({info["intelDivisionShortName"]}) /'
f' {info["intelOrgUnitDescr"]}' \ f' {info["intelOrgUnitDescr"]}'
f'\n Manager: {info["manager"]}' \ f'\n Manager: {info.get("manager")}'
f'\n Location: {info["intelRegionCode"]} / {info["co"]} / {info["intelSiteCode"]} /' \ f'\n Location: {info["intelRegionCode"]} / {info["co"]} / {info["intelSiteCode"]} /'
f' {info["intelBldgCode"]} ({info["intelSiteName"]}) /' \ f' {info["intelBldgCode"]} ({info.get("intelSiteName")}) /'
f' {info["physicalDeliveryOfficeName"]}' \ f' {info["physicalDeliveryOfficeName"]}'
f'\n Other: {info["employeeType"]} | {info["intelExportCountryGroup"]} |' \ f'\n Other: {info["employeeType"]} | {info["intelExportCountryGroup"]} |'
f' {info["whenCreated"]} | {info["intelCostCenterDescr"]} | {info["jobDescription"]}' f' {info["whenCreated"]} | {info["intelCostCenterDescr"]} | {info["jobDescription"]}'
)
except Exception as exc: except Exception as exc:
raise LdapApiException(f'ERROR: Failed to get info about "{info["mail"]}". ' \ raise LdapApiException(
f'Exception occurred:\n{repr(exc)}') from exc f'ERROR: Failed to get info about "{info["mail"]}". '
f"Exception occurred:\n{repr(exc)}"
) from exc
print(text_info) print(text_info)
membership = get_membership() membership = get_membership()
@ -71,140 +78,144 @@ def print_user_info(info, info_level=None):
elif info_level == InfoLevel.FULL: elif info_level == InfoLevel.FULL:
for key in sorted(info): for key in sorted(info):
if isinstance(info[key], list): if isinstance(info[key], list):
if key == 'memberOf': if key == "memberOf":
print(membership) print(membership)
else: else:
print(f' {key} :') print(f" {key} :")
for item in info[key]: for item in info[key]:
print(' ', item) print(" ", item)
else: else:
print(f' {key} : {info[key]}') print(f" {key} : {info[key]}")
class LdapApi: class LdapApi:
"""LDAP API for getting user info and emails""" """LDAP API for getting user info and emails"""
_binary_blobs = ['thumbnailPhoto', 'msExchUMSpokenName', 'msExchBlockedSendersHash'] _binary_blobs = ["thumbnailPhoto", "msExchUMSpokenName", "msExchBlockedSendersHash"]
_check_existing = [ _check_existing = [
'intelExportCountryGroup', "intelExportCountryGroup",
'physicalDeliveryOfficeName', "physicalDeliveryOfficeName",
'intelSuperGroupShortName', "intelSuperGroupShortName",
'intelGroupShortName', "intelGroupShortName",
'intelDivisionShortName', "intelDivisionShortName",
] ]
null = '<null>' null = "<null>"
def __init__(self): def __init__(self):
self._cfg = Config() self._cfg = Config()
self.server = Server(self._cfg.LDAP_SERVER, get_info=ALL) self.server = Server(self._cfg.LDAP_SERVER, get_info=ALL)
self.connection = Connection(self.server, self.connection = Connection(
user=self._cfg.LDAP_USER, self.server, user=self._cfg.LDAP_USER, password=self._cfg.LDAP_PASSWORD, auto_bind=True
password=self._cfg.LDAP_PASSWORD, )
auto_bind=True)
self.connection.bind() self.connection.bind()
def get_user_emails(self, groups=None): def get_user_emails(self, groups=None):
"""Gets emails of LDAP groups and sub-groups""" """Gets emails of LDAP groups and sub-groups"""
print('\nGet emails from LDAP groups:') print("\nGet emails from LDAP groups:")
processed_ldap_members = {} processed_ldap_members = {}
def process_group_members(member, parent_group): def process_group_members(member, parent_group):
if member in processed_ldap_members: if member in processed_ldap_members:
processed_ldap_members[member]['parent_groups'].append(parent_group) processed_ldap_members[member]["parent_groups"].append(parent_group)
print('\nWARNING: Ignore LDAP member to avoid duplication and recursive cycling ' print(
f'of PDLs: {member}\n ' "\nWARNING: Ignore LDAP member to avoid duplication and recursive cycling "
f'email: {processed_ldap_members[member].get("email")}\n parent_groups:') f"of PDLs: {member}\n "
for group in processed_ldap_members[member].get('parent_groups', []): f'email: {processed_ldap_members[member].get("email")}\n parent_groups:'
print(7 * ' ', group) )
for group in processed_ldap_members[member].get("parent_groups", []):
print(7 * " ", group)
return return
processed_ldap_members[member] = {'email': None, 'parent_groups': [parent_group]} processed_ldap_members[member] = {"email": None, "parent_groups": [parent_group]}
# AD moves terminated users to the boneyard OU in case the user returns, # AD moves terminated users to the boneyard OU in case the user returns,
# so it can be reactivated with little effort. # so it can be reactivated with little effort.
# After 30 days it is removed and the unix personality becomes unlinked. # After 30 days it is removed and the unix personality becomes unlinked.
if 'OU=Boneyard' in member: if "OU=Boneyard" in member:
return return
self.connection.search(member, r'(objectClass=*)', SUBTREE, self.connection.search(
attributes=['cn', 'member', 'mail']) member, r"(objectClass=*)", SUBTREE, attributes=["cn", "member", "mail"]
)
#print(self.connection.entries) # print(self.connection.entries)
if not self.connection.response: if not self.connection.response:
raise LdapApiException(f'ERROR: empty response. LDAP member: {member}') raise LdapApiException(f"ERROR: empty response. LDAP member: {member}")
# Check that the member is worker. # Check that the member is worker.
# The response can contain several items, but the first item is valid only # The response can contain several items, but the first item is valid only
if 'OU=Workers' in member: if "OU=Workers" in member:
if self.connection.response[0]['attributes']['mail']: if self.connection.response[0]["attributes"]["mail"]:
processed_ldap_members[member]['email'] = \ processed_ldap_members[member]["email"] = self.connection.response[0][
self.connection.response[0]['attributes']['mail'].lower() "attributes"
]["mail"].lower()
return return
raise LdapApiException(f'ERROR: no mail. LDAP worker: {member}\n' raise LdapApiException(
f'{self.connection.entries}') f"ERROR: no mail. LDAP worker: {member}\n" f"{self.connection.entries}"
)
if len(self.connection.response) > 1: if len(self.connection.response) > 1:
raise LdapApiException(f'ERROR: multiple responses for {member}: ' raise LdapApiException(
f'{len(self.connection.response)}\n' f"ERROR: multiple responses for {member}: "
f'{self.connection.entries}') f"{len(self.connection.response)}\n"
f"{self.connection.entries}"
)
if self.connection.response[0]['attributes']['member']: if self.connection.response[0]["attributes"]["member"]:
for group_member in self.connection.response[0]['attributes']['member']: for group_member in self.connection.response[0]["attributes"]["member"]:
process_group_members(group_member, member) process_group_members(group_member, member)
else: else:
print(f'\nERROR: no members in LDAP group: {member}\n{self.connection.entries}') print(f"\nERROR: no members in LDAP group: {member}\n{self.connection.entries}")
for group in groups or self._cfg.LDAP_PDLs: for group in groups or self._cfg.LDAP_PDLs:
print('\nProcess ROOT LDAP group:', group) print("\nProcess ROOT LDAP group:", group)
process_group_members(group, 'ROOT') process_group_members(group, "ROOT")
return { return {
member.get('email') for member in processed_ldap_members.values() if member.get('email') member.get("email") for member in processed_ldap_members.values() if member.get("email")
} }
def _get_user_info(self, query): def _get_user_info(self, query):
"""Gets user info from LDAP as dict matching key and values pairs from query""" """Gets user info from LDAP as dict matching key and values pairs from query"""
query_filter = ''.join(f'({key}={value})' for key, value in query.items()) query_filter = "".join(f"({key}={value})" for key, value in query.items())
for domain in self._cfg.LDAP_DOMAINS: for domain in self._cfg.LDAP_DOMAINS:
search_base = f'OU=Workers,DC={domain},DC=corp,DC=intel,DC=com' search_base = f"OU=Workers,DC={domain},DC=corp,DC=intel,DC=com"
self.connection.search( self.connection.search(
search_base, search_base,
f'(&(objectcategory=person)(objectclass=user)(intelflags=1){query_filter})', f"(&(objectcategory=person)(objectclass=user)(intelflags=1){query_filter})",
SUBTREE, SUBTREE,
attributes=['*']) attributes=["*"],
)
if self.connection.response: if self.connection.response:
if len(self.connection.response) > 1: if len(self.connection.response) > 1:
raise LdapApiException(f'ERROR: multiple responses for {query_filter}: ' raise LdapApiException(
f'{len(self.connection.response)}\n' f"ERROR: multiple responses for {query_filter}: "
f'{self.connection.entries}') f"{len(self.connection.response)}\n"
info = self.connection.response[0]['attributes'] f"{self.connection.entries}"
)
info = self.connection.response[0]["attributes"]
# remove long binary blobs # remove long binary blobs
for blob in LdapApi._binary_blobs: for blob in LdapApi._binary_blobs:
info[blob] = b'' info[blob] = b""
for key in LdapApi._check_existing: for key in LdapApi._check_existing:
if not info.get(key): if not info.get(key):
info[key] = LdapApi.null info[key] = LdapApi.null
return info return info
return {} return {}
def get_user_info_by_idsid(self, idsid): def get_user_info_by_idsid(self, idsid):
"""Gets user info from LDAP as dict using account name for searching""" """Gets user info from LDAP as dict using account name for searching"""
return self._get_user_info({'sAMAccountName': idsid}) return self._get_user_info({"sAMAccountName": idsid})
def get_user_info_by_name(self, name): def get_user_info_by_name(self, name):
"""Gets user info from LDAP as dict using common name for searching""" """Gets user info from LDAP as dict using common name for searching"""
return self._get_user_info({'cn': name}) return self._get_user_info({"cn": name})
def get_user_info_by_email(self, email): def get_user_info_by_email(self, email):
"""Gets user info from LDAP as dict using emails for searching""" """Gets user info from LDAP as dict using emails for searching"""
return self._get_user_info({'mail': email}) return self._get_user_info({"mail": email})
def get_absent_emails(self, emails): def get_absent_emails(self, emails):
"""Checks users by email in LDAP and returns absent emails""" """Checks users by email in LDAP and returns absent emails"""
@ -222,15 +233,15 @@ def _test():
emails = ldap.get_user_emails() emails = ldap.get_user_emails()
print(f'\nLDAP emails count: {len(emails)}\n{"; ".join(emails)}') print(f'\nLDAP emails count: {len(emails)}\n{"; ".join(emails)}')
emails = ['foo@intel.com'] emails = ["foo@intel.com"]
for email in emails: for email in emails:
info = ldap.get_user_info_by_email(email) info = ldap.get_user_info_by_email(email)
if info: if info:
print_user_info(info, InfoLevel.PDL) print_user_info(info, InfoLevel.PDL)
else: else:
print(f'\n{email} - not found') print(f"\n{email} - not found")
if __name__ == '__main__': if __name__ == "__main__":
_test() _test()

View File

@ -0,0 +1 @@
pylint==2.11.1

View File

@ -0,0 +1,2 @@
PyGithub==1.55
ldap3==2.7

View File

@ -1,94 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
"""
Check GitHub organization and invite members
"""
# pylint: disable=fixme,no-member,too-many-locals
from argparse import ArgumentParser
from configs import Config
from github_api import GithubOrgApi, get_dev_emails
from ldap_api import LdapApi, print_user_info, InfoLevel
def main():
"""The main entry point function"""
arg_parser = ArgumentParser()
arg_parser.add_argument("--cfg-file", metavar="PATH", default=Config.default_cfg_path,
help=f"Path to json configuration file, e.g. {Config.default_cfg_path}")
arg_parser.add_argument("--teams", action="store_true", help="Check GitHub teams")
arg_parser.add_argument("--no-ldap", action="store_true", help="Don't use LDAP info")
args, unknown_args = arg_parser.parse_known_args()
Config(args.cfg_file, unknown_args)
gh_api = GithubOrgApi()
if args.teams:
gh_api.get_org_teams()
return
cfg_emails = get_dev_emails()
print(f'\nCfg developer emails {len(cfg_emails)}:', '; '.join(sorted(cfg_emails)))
dev_emails = set()
dev_emails.update(cfg_emails)
if not args.no_ldap:
ldap_api = LdapApi()
ldap_emails = ldap_api.get_user_emails()
dev_emails.update(ldap_emails)
print(f'\nLDAP developer emails {len(ldap_emails)}:', '; '.join(sorted(ldap_emails)))
cfg_emails_no_in_ldap = ldap_api.get_absent_emails(cfg_emails)
print(f'\nCfg developer emails - absent in LDAP at all {len(cfg_emails_no_in_ldap)}:',
'; '.join(sorted(cfg_emails_no_in_ldap)))
cfg_ldap_inters = cfg_emails.intersection(ldap_emails)
print(f'\nCfg developer emails - present in LDAP developers {len(cfg_ldap_inters)}:',
'; '.join(sorted(cfg_ldap_inters)))
org_emails, org_logins_no_intel_email = gh_api.get_org_emails()
print(f'\nOrg emails {len(org_emails)}:', '; '.join(sorted(org_emails)))
org_emails_no_in_ldap = set()
if not args.no_ldap:
org_ldap_diff = org_emails.difference(ldap_emails)
print(f'\nOrg member emails - absent in LDAP developers {len(org_ldap_diff)}:',
'; '.join(sorted(org_ldap_diff)))
for email in org_ldap_diff:
user_info = ldap_api.get_user_info_by_email(email)
if user_info:
print_user_info(user_info, InfoLevel.PDL)
else:
org_emails_no_in_ldap.add(email)
org_pendig_invitation_emails = gh_api.get_org_invitation_emails()
invite_emails = dev_emails.difference(org_emails).difference(org_pendig_invitation_emails)
print(f'\nInvite emails {len(invite_emails)}:', '; '.join(sorted(invite_emails)))
valid_github_users = gh_api.get_valid_github_users(invite_emails)
gh_api.invite_users(valid_github_users)
print('\nCheck accounts below and remove from the GitHub organization and cfg list')
cfg_emails_no_in_org = sorted(cfg_emails.difference(org_emails))
print(f'\nCfg developer emails - absent in GitHub organization {len(cfg_emails_no_in_org)}:',
'; '.join(cfg_emails_no_in_org))
org_emails_no_in_dev = sorted(org_emails.difference(dev_emails))
print(f'\nOrg member emails - absent in cfg and LDAP developers {len(org_emails_no_in_dev)}:',
'; '.join(org_emails_no_in_dev))
print(f'\nOrg member emails - absent in LDAP at all {len(org_emails_no_in_ldap)}:',
'; '.join(sorted(org_emails_no_in_ldap)))
print(f'\nOrg member logins - absent Intel email {len(org_logins_no_intel_email)}:',
'; '.join(sorted(org_logins_no_intel_email)))
if __name__ == '__main__':
main()

View File

@ -1,282 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
"""
GitHub API for controlling organization
"""
# pylint: disable=fixme,no-member
import re
import time
from github import Github, GithubException, RateLimitExceededException, IncompletableObject
from github.PaginatedList import PaginatedList
from configs import Config
def is_valid_user(user):
"""Checks that user is valid github.Github object"""
try:
return user and user.login
except IncompletableObject:
return False
def is_user_ignored(user):
"""Checks that user should be ignored"""
cfg = Config()
if is_valid_user(user) and user.login.lower() not in cfg.properties['IGNORE_LOGINS']:
return False
return True
def is_valid_name(name):
"""Checks that GitHub user's name is valid"""
return name and len(name) >= 3 and ' ' in name
def is_intel_email(email):
"""Checks that email is valid Intel email"""
return email and len(email) > 10 and ' ' not in email and email.lower().endswith('@intel.com')
def is_intel_company(company):
"""Checks that company contains intel"""
return company and 'intel' in company.lower()
def is_valid_intel_user(user):
"""Checks that user is valid GitHub and Intel user"""
return is_valid_user(user) and (is_valid_name(user.name) and is_intel_email(user.email) or
is_user_ignored(user))
def print_users(users):
"""Print list of users in different formats: list, set, PaginatedList"""
if isinstance(users, (list, set, PaginatedList)):
users_count = users.totalCount if isinstance(users, PaginatedList) else len(users)
print(f'\nGitHub users {users_count} (login - name - company - email - valid):')
else:
users = [users]
for user in users:
if not is_valid_user(user):
print('WRONG GitHub user: ???')
continue
valid_check = 'OK' if is_valid_intel_user(user) else 'FIX'
if not is_intel_email(user.email):
valid_check += ' email'
if not is_valid_name(user.name):
valid_check += ' name'
print(f'{user.login} - "{user.name}" - "{user.company}" - {user.email} - {valid_check}')
def get_dev_emails():
"""
Read a file with developer emails. Supported email formats
first_name.last_name@intel.com
Import from Outlook: Last_name, First_name <first_name.last_name@intel.com>
"""
re_email = re.compile(r'.+<(.+)>')
emails = set()
cfg = Config()
with open(cfg.properties['EMAILS_FILE_PATH']) as file_obj:
for line in file_obj:
line = line.strip().lower()
if not line or line.startswith('#'):
continue
re_outlook_email = re_email.match(line)
if re_outlook_email:
line = re_outlook_email.group(1).strip()
if not is_intel_email(line):
print(f'Wrong email in {cfg.properties["EMAILS_FILE_PATH"]}: {line}')
continue
emails.add(line)
return emails
class GithubOrgApi:
"""Common API for GitHub organization"""
def __init__(self):
self._cfg = Config()
self.github = Github(self._cfg.GITHUB_TOKEN)
self.github_org = self.github.get_organization(self._cfg.GITHUB_ORGANIZATION)
self.repo = self.github.get_repo(f'{self._cfg.GITHUB_ORGANIZATION}/'
f'{self._cfg.GITHUB_REPO}')
def is_org_user(self, user):
"""Checks that user is a member of GitHub organization"""
if is_valid_user(user):
# user.get_organization_membership(self.github_org) doesn't work with org members
# permissions, GITHUB_TOKEN must be org owner now
return self.github_org.has_in_members(user)
return False
def get_org_emails(self):
"""Gets and prints emails of all GitHub organization members"""
org_members = self.github_org.get_members()
org_emails = set()
org_members_fix = set()
org_emails_fix_name = set()
org_logins_fix_intel_email = set()
print(f'\nOrg members {org_members.totalCount} (login - name - company - email - valid):')
for org_member in org_members:
print_users(org_member)
if is_user_ignored(org_member):
continue
if is_intel_email(org_member.email):
org_emails.add(org_member.email.lower())
if not is_valid_name(org_member.name):
org_members_fix.add(org_member)
org_emails_fix_name.add(org_member.email.lower())
else:
org_members_fix.add(org_member)
org_logins_fix_intel_email.add(org_member.login.lower())
print_users(org_members_fix)
print(f'\nOrg members - no Intel emails {len(org_logins_fix_intel_email)}:',
'; '.join(org_logins_fix_intel_email))
print(f'\nOrg members - no real name {len(org_emails_fix_name)}:',
'; '.join(org_emails_fix_name))
return (org_emails, org_logins_fix_intel_email)
def get_org_invitation_emails(self):
"""Gets GitHub organization teams prints info"""
org_invitations = self.github_org.invitations()
org_invitation_emails = set()
print(f'\nOrg invitations {org_invitations.totalCount} (login - name - email - valid):')
for org_invitation in org_invitations:
# TODO: investigate GithubException while access to user name and enable print_users()
# github.GithubException.IncompletableObject: 400 "Returned object contains no URL"
#print_users(org_invitation)
print(f'{org_invitation.login} - ??? - {org_invitation.email} - ???')
if is_user_ignored(org_invitation):
continue
if is_intel_email(org_invitation.email):
org_invitation_emails.add(org_invitation.email.lower())
else:
print('Strange org invitation:', org_invitation)
print(f'\nOrg invitation emails {len(org_invitation_emails)}:',
'; '.join(org_invitation_emails))
return org_invitation_emails
def get_org_teams(self):
"""Gets GitHub organization teams prints info"""
teams = []
org_teams = self.github_org.get_teams()
print('\nOrg teams count:', org_teams.totalCount)
for team in org_teams:
teams.append(team.name)
print(f'\nTeam: {team.name} - parent: {team.parent}')
repos = team.get_repos()
print('Repos:')
for repo in repos:
print(f' {repo.name} -', team.get_repo_permission(repo))
team_maintainers = team.get_members(role='maintainer')
team_maintainer_logins = set()
for maintainer in team_maintainers:
team_maintainer_logins.add(maintainer.login)
team_members = team.get_members(role='member')
team_member_logins = set()
for member in team_members:
team_member_logins.add(member.login)
members = team.get_members(role='all')
member_emails = []
print('Members (role - login - name - company - email - valid):')
for user in members:
if user.login in team_maintainer_logins:
print(' Maintainer - ', end='')
elif user.login in team_member_logins:
print(' Member - ', end='')
else:
# It is not possible to check child teams members
print(' ??? - ', end='')
print_users(user)
if is_intel_email(user.email) and not is_user_ignored(user):
member_emails.append(user.email.lower())
print(f'Intel emails {len(member_emails)}:', '; '.join(member_emails))
return teams
def get_valid_github_users(self, emails):
"""Gets valid GitHub users by email and prints status"""
valid_users = set()
no_account_emails = set()
print(f'\nGitHub users from {len(emails)} invite emails (email - status):')
for email in emails:
if not is_intel_email(email):
print(f'{email} - Non Intel email')
continue
# You can make up to 30 requests per minute; https://developer.github.com/v3/search/
# Sleep 2.4 sec is about 25 requests per minute
time.sleep(2.4)
try:
users = self.github.search_users(f'{email} in:email')
except RateLimitExceededException:
time.sleep(5)
users = self.github.search_users(f'{email} in:email')
if users.totalCount == 0:
print(f'{email} - No valid GitHub account')
no_account_emails.add(email)
continue
if users.totalCount > 1:
print(f'{email} - Found {users.totalCount} GitHub accounts')
for user in users:
if user.email and user.email.lower() == email:
print(f'{email} - OK')
valid_users.add(user)
else:
print(f'{email} - Non public or wrong email - login: {user.login} - '
f'email: {user.email}')
print('Valid users count:', len(valid_users))
print_users(valid_users)
print(f'\nIntel emails - No valid GitHub account {len(no_account_emails)}:',
'; '.join(no_account_emails))
return valid_users
def invite_users(self, users):
"""Invites users and prints status"""
if isinstance(users, (list, set)):
print(f'\nInvite {len(users)} users:')
else:
users = [users]
for user in users:
if isinstance(user, str):
print(f'Email: {user}')
self.github_org.invite_user(email=user)
else:
print(f'{user.login} - "{user.name}" - {user.email} - ', end='')
try:
if is_user_ignored(user):
print('Ignored')
continue
if not self._cfg.DRY_RUN:
self.github_org.invite_user(user=user)
print('OK')
else:
print('Dry run')
except GithubException as exc:
print(f'FAIL: {exc.data["errors"][0]["message"]}')
def _test():
"""Test and debug"""
Config(cli_args=['DRY_RUN=True'])
dev_emails = get_dev_emails()
print('dev_emails:', dev_emails)
gh_api = GithubOrgApi()
gh_api.get_org_emails()
if __name__ == '__main__':
_test()

View File

@ -1 +0,0 @@
pylint==2.5.3

View File

@ -1,2 +0,0 @@
PyGithub==1.51
ldap3==2.7

View File

@ -14,15 +14,25 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
set -e
# install doc dependencies
sudo apt update sudo apt update
sudo apt --assume-yes install libusb-1.0-0-dev graphviz texlive sudo apt --assume-yes install libusb-1.0-0-dev graphviz texlive
python3 -m pip install lxml cd docs
python -m pip install -r requirements.txt --user
cd openvino_sphinx_theme
python setup.py install --user
cd ../..
# install doxyrest
wget https://github.com/vovkos/doxyrest/releases/download/doxyrest-2.1.3/doxyrest-2.1.3-linux-amd64.tar.xz
tar -xf doxyrest-2.1.3-linux-amd64.tar.xz
echo "$(pwd)/doxyrest-2.1.3-linux-amd64/bin/" >> $GITHUB_PATH
# install doxygen # install doxygen
mkdir doxygen mkdir doxygen
cd doxygen cd doxygen
git clone https://github.com/doxygen/doxygen.git git clone https://github.com/doxygen/doxygen.git
cd doxygen cd doxygen
git checkout Release_1_9_1 git checkout Release_1_9_2
mkdir build mkdir build
cd build cd build
cmake .. cmake ..
@ -33,15 +43,37 @@ jobs:
run: | run: |
mkdir build mkdir build
cd build cd build
cmake -DENABLE_DOCS=ON .. cmake -DENABLE_DOCS=ON -DENABLE_PYTHON=ON -DNGRAPH_PYTHON_BUILD_ENABLE=ON -DCMAKE_BUILD_TYPE=Release ..
- name: Build doc - name: Build doc
run: cmake --build . --target openvino_docs run: |
cmake --build . --target sphinx_docs
working-directory: build working-directory: build
- name: Archive HTML
run: |
zip -r openvino_html.zip _build
working-directory: build/docs
- name: Run Pytest
run: |
pytest --doxygen="./build/docs/doxygen.log" \
--confcutdir="./docs/scripts/tests/" \
--html="./build/docs/_artifacts/doc-generation.html" \
--doxygen-strip="$(pwd)" \
--doxygen-xfail="./docs/doxygen-xfail.txt" \
--self-contained-html ./docs/scripts/tests/test_docs.py
- name: 'Upload doc' - name: 'Upload test results'
if: always()
uses: actions/upload-artifact@v2
with:
name: openvino_doc_pytest
path: build/docs/_artifacts/
- name: 'Upload html'
if: github.event_name == 'push' if: github.event_name == 'push'
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: openvino_doc name: openvino_html
path: build/docs/html/ path: build/docs/openvino_html.zip

View File

@ -9,9 +9,9 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install dependencies - name: Install dependencies
run: python3 -m pip install -r ./.github/org_control/requirements.txt run: python3 -m pip install -r ./.github/github_org_control/requirements.txt
- name: PR commits - name: PR commits
run: python3 ./.github/org_control/check_pr.py --pr=${{ github.event.number }} --check-commits DRY_RUN run: python3 ./.github/github_org_control/check_pr.py --pr=${{ github.event.number }} --check-commits DRY_RUN
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2
.gitignore vendored
View File

@ -3,6 +3,8 @@ _*
# but ensure we don't skip __init__.py and __main__.py # but ensure we don't skip __init__.py and __main__.py
!__init__.py !__init__.py
!__main__.py !__main__.py
# and sphinx documentation folders
!docs/_*
# developer tools # developer tools
*.idea *.idea

6
.gitmodules vendored
View File

@ -1,5 +1,5 @@
[submodule "inference-engine/thirdparty/mkl-dnn"] [submodule "src/plugins/intel_cpu/thirdparty/mkl-dnn"]
path = inference-engine/thirdparty/mkl-dnn path = src/plugins/intel_cpu/thirdparty/mkl-dnn
url = https://github.com/openvinotoolkit/oneDNN.git url = https://github.com/openvinotoolkit/oneDNN.git
ignore = dirty ignore = dirty
[submodule "thirdparty/xbyak"] [submodule "thirdparty/xbyak"]
@ -57,7 +57,7 @@
path = thirdparty/onednn_gpu path = thirdparty/onednn_gpu
url = https://github.com/oneapi-src/oneDNN.git url = https://github.com/oneapi-src/oneDNN.git
[submodule "tools/pot/thirdparty/open_model_zoo"] [submodule "tools/pot/thirdparty/open_model_zoo"]
path = tools/pot/thirdparty/open_model_zoo path = thirdparty/open_model_zoo
url = https://github.com/openvinotoolkit/open_model_zoo.git url = https://github.com/openvinotoolkit/open_model_zoo.git
[submodule "thirdparty/json/nlohmann_json"] [submodule "thirdparty/json/nlohmann_json"]
path = thirdparty/json/nlohmann_json path = thirdparty/json/nlohmann_json

View File

@ -38,9 +38,9 @@ Jenkinsfile @openvinotoolkit/openvino-admins
/src/tests_deprecated/readers/ @openvinotoolkit/openvino-ngraph-maintainers /src/tests_deprecated/readers/ @openvinotoolkit/openvino-ngraph-maintainers
# IE CPU: # IE CPU:
/inference-engine/src/mkldnn_plugin/ @openvinotoolkit/openvino-ie-cpu-maintainers @openvinotoolkit/openvino-ie-cpu-developers /src/plugins/intel_cpu/ @openvinotoolkit/openvino-ie-cpu-maintainers @openvinotoolkit/openvino-ie-cpu-developers
/src/common/low_precision_transformations/ @openvinotoolkit/openvino-ie-cpu-maintainers @openvinotoolkit/openvino-ie-cpu-developers /src/common/low_precision_transformations/ @openvinotoolkit/openvino-ie-cpu-maintainers @openvinotoolkit/openvino-ie-cpu-developers
/inference-engine/thirdparty/mkl-dnn/ @openvinotoolkit/openvino-ie-cpu-maintainers @openvinotoolkit/openvino-ie-cpu-developers /src/plugins/intel_cpu/thirdparty/mkl-dnn/ @openvinotoolkit/openvino-ie-cpu-maintainers @openvinotoolkit/openvino-ie-cpu-developers
# IE GPU: # IE GPU:
/src/inference/include/ie/gpu/ @openvinotoolkit/openvino-ie-gpu-maintainers @openvinotoolkit/openvino-ie-gpu-developers /src/inference/include/ie/gpu/ @openvinotoolkit/openvino-ie-gpu-maintainers @openvinotoolkit/openvino-ie-gpu-developers
@ -66,7 +66,7 @@ Jenkinsfile @openvinotoolkit/openvino-admins
/src/inference/include/ie/gna/ @openvinotoolkit/openvino-ie-gna-maintainers /src/inference/include/ie/gna/ @openvinotoolkit/openvino-ie-gna-maintainers
# IE MULTI: # IE MULTI:
/inference-engine/src/multi_device/ @openvinotoolkit/openvino-ie-multi-maintainers /src/plugins/auto/ @openvinotoolkit/openvino-ie-multi-maintainers
/src/inference/include/ie/multi-device/ @openvinotoolkit/openvino-ie-multi-maintainers /src/inference/include/ie/multi-device/ @openvinotoolkit/openvino-ie-multi-maintainers
# IE Tests: # IE Tests:

View File

@ -58,10 +58,10 @@ ie_coverage_extract(INPUT "openvino" OUTPUT "template_plugin"
ie_coverage_genhtml(INFO_FILE "template_plugin" ie_coverage_genhtml(INFO_FILE "template_plugin"
PREFIX "${OV_COVERAGE_BASE_DIRECTORY}") PREFIX "${OV_COVERAGE_BASE_DIRECTORY}")
if(ENABLE_MKL_DNN) if(ENABLE_INTEL_CPU)
ie_coverage_extract(INPUT "openvino" OUTPUT "mkldnn_plugin" ie_coverage_extract(INPUT "openvino" OUTPUT "intel_cpu_plugin"
PATTERNS "${OV_COVERAGE_BASE_DIRECTORY}/inference-engine/src/mkldnn_plugin/*") PATTERNS "${OV_COVERAGE_BASE_DIRECTORY}/src/plugins/intel_cpu/*")
ie_coverage_genhtml(INFO_FILE "mkldnn_plugin" ie_coverage_genhtml(INFO_FILE "intel_cpu_plugin"
PREFIX "${OV_COVERAGE_BASE_DIRECTORY}") PREFIX "${OV_COVERAGE_BASE_DIRECTORY}")
endif() endif()

View File

@ -276,20 +276,8 @@ if(ENABLE_INTEL_GNA)
GNA_LIB_DIR GNA_LIB_DIR
libGNA_INCLUDE_DIRS libGNA_INCLUDE_DIRS
libGNA_LIBRARIES_BASE_PATH) libGNA_LIBRARIES_BASE_PATH)
if(GNA_LIBRARY_VERSION STREQUAL "GNA1") set(GNA_VERSION "03.00.00.1455")
RESOLVE_DEPENDENCY(GNA set(GNA_HASH "8ac1af18eb32777b00193f4f8c252ee4f8bd64a9069138b4a5aaeebd82ead464")
ARCHIVE_UNIFIED "GNA/gna_20181120.zip"
TARGET_PATH "${TEMP}/gna"
SHA256 "b631d6cc5f6cca4a89a3f5dfa383066f3282fee25d633d9085c605bdd8090210")
else()
if(GNA_LIBRARY_VERSION STREQUAL "GNA1_1401")
set(GNA_VERSION "01.00.00.1401")
set(GNA_HASH "cc954e67525006bf8bd353a6682e38bf208f6d74e973e0fc292850e721f17452")
endif()
if(GNA_LIBRARY_VERSION STREQUAL "GNA2")
set(GNA_VERSION "03.00.00.1455")
set(GNA_HASH "8ac1af18eb32777b00193f4f8c252ee4f8bd64a9069138b4a5aaeebd82ead464")
endif()
set(FILES_TO_EXTRACT_LIST gna_${GNA_VERSION}/include) set(FILES_TO_EXTRACT_LIST gna_${GNA_VERSION}/include)
if(WIN32) if(WIN32)
@ -304,7 +292,6 @@ if(ENABLE_INTEL_GNA)
VERSION_REGEX ".*_([0-9]+.[0-9]+.[0-9]+.[0-9]+).*" VERSION_REGEX ".*_([0-9]+.[0-9]+.[0-9]+.[0-9]+).*"
FILES_TO_EXTRACT FILES_TO_EXTRACT_LIST FILES_TO_EXTRACT FILES_TO_EXTRACT_LIST
SHA256 ${GNA_HASH}) SHA256 ${GNA_HASH})
endif()
update_deps_cache(GNA "${GNA}" "Path to GNA root folder") update_deps_cache(GNA "${GNA}" "Path to GNA root folder")
debug_message(STATUS "gna=" ${GNA}) debug_message(STATUS "gna=" ${GNA})
endif() endif()

View File

@ -258,6 +258,10 @@ function(ie_mark_target_as_cc TARGET_NAME)
set_source_files_properties(${sources} PROPERTIES OBJECT_DEPENDS ${GENERATED_HEADER}) set_source_files_properties(${sources} PROPERTIES OBJECT_DEPENDS ${GENERATED_HEADER})
endfunction() endfunction()
function(ov_mark_target_as_cc)
ie_mark_target_as_cc(${ARGN})
endfunction()
# check python package # check python package
function(ie_check_pip_package full_name message_type) function(ie_check_pip_package full_name message_type)

View File

@ -133,6 +133,10 @@ function(addIeTarget)
endif() endif()
endfunction() endfunction()
function(ov_add_target)
addIeTarget(${ARGV})
endfunction()
#[[ #[[
Wrapper function over addIeTarget, that also adds a test with the same name. Wrapper function over addIeTarget, that also adds a test with the same name.
You could use You could use
@ -163,3 +167,7 @@ function(addIeTargetTest)
COMPONENT tests COMPONENT tests
EXCLUDE_FROM_ALL) EXCLUDE_FROM_ALL)
endfunction() endfunction()
function(ov_add_test_target)
addIeTargetTest(${ARGV})
endfunction()

View File

@ -79,8 +79,20 @@ function(_ie_add_api_validator_post_build_step)
_ie_add_api_validator_post_build_step_recursive(TARGET ${API_VALIDATOR_TARGET}) _ie_add_api_validator_post_build_step_recursive(TARGET ${API_VALIDATOR_TARGET})
# remove targets which were tested before # remove targets which were tested before
foreach(target IN LISTS API_VALIDATOR_TARGETS)
foreach(item IN LISTS VALIDATED_LIBRARIES) list(FIND VALIDATED_LIBRARIES ${target} index)
if (NOT index EQUAL -1)
list(APPEND VALIDATED_TARGETS ${target})
endif()
if(TARGET "${target}")
get_target_property(orig_target ${target} ALIASED_TARGET)
list(FIND VALIDATED_LIBRARIES ${orig_target} index)
if (NOT index EQUAL -1)
list(APPEND VALIDATED_TARGETS ${target})
endif()
endif()
endforeach()
foreach(item IN LISTS VALIDATED_TARGETS)
list(REMOVE_ITEM API_VALIDATOR_TARGETS ${item}) list(REMOVE_ITEM API_VALIDATOR_TARGETS ${item})
endforeach() endforeach()

View File

@ -193,6 +193,10 @@ macro(ie_add_compiler_flags)
endforeach() endforeach()
endmacro() endmacro()
function(ov_add_compiler_flags)
ie_add_compiler_flags(${ARGN})
endfunction()
# #
# Forced includes certain header file to all target source files # Forced includes certain header file to all target source files
# #

View File

@ -2,8 +2,9 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
set(FRONTEND_INSTALL_INCLUDE "include/ngraph/frontend") set(FRONTEND_INSTALL_INCLUDE "runtime/include/")
set(FRONTEND_NAME_SUFFIX "_ov_frontend") set(FRONTEND_NAME_PREFIX "ov_")
set(FRONTEND_NAME_SUFFIX "_frontend")
set(FRONTEND_NAMES "" CACHE INTERNAL "") set(FRONTEND_NAMES "" CACHE INTERNAL "")
@ -20,7 +21,7 @@ function(ov_target_link_frontends TARGET_NAME)
endif() endif()
foreach(name IN LISTS FRONTEND_NAMES) foreach(name IN LISTS FRONTEND_NAMES)
set(frontend_target_name "${name}${FRONTEND_NAME_SUFFIX}") set(frontend_target_name "${FRONTEND_NAME_PREFIX}${name}${FRONTEND_NAME_SUFFIX}")
target_link_libraries(${TARGET_NAME} PRIVATE ${frontend_target_name}) target_link_libraries(${TARGET_NAME} PRIVATE ${frontend_target_name})
endforeach() endforeach()
endfunction() endfunction()
@ -34,7 +35,7 @@ function(ov_generate_frontends_hpp)
endif() endif()
# add frontends to libraries including ov_frontends.hpp # add frontends to libraries including ov_frontends.hpp
ov_target_link_frontends(frontend_common) ov_target_link_frontends(ov_runtime)
set(ov_frontends_hpp "${CMAKE_BINARY_DIR}/src/frontends/common/src/ov_frontends.hpp") set(ov_frontends_hpp "${CMAKE_BINARY_DIR}/src/frontends/common/src/ov_frontends.hpp")
set(frontends_hpp_in "${IEDevScripts_DIR}/frontends/ov_frontends.hpp.in") set(frontends_hpp_in "${IEDevScripts_DIR}/frontends/ov_frontends.hpp.in")
@ -59,7 +60,7 @@ function(ov_generate_frontends_hpp)
add_dependencies(frontend_common _ov_frontends_hpp) add_dependencies(frontend_common _ov_frontends_hpp)
# add dependency for object files # add dependency for object files
get_target_property(sources frontend_common::static SOURCES) get_target_property(sources frontend_common_obj SOURCES)
foreach(source IN LISTS sources) foreach(source IN LISTS sources)
if("${source}" MATCHES "\\$\\<TARGET_OBJECTS\\:([A-Za-z0-9_]*)\\>") if("${source}" MATCHES "\\$\\<TARGET_OBJECTS\\:([A-Za-z0-9_]*)\\>")
# object library # object library
@ -81,10 +82,11 @@ unset(protobuf_installed CACHE)
# #
# ov_add_frontend(NAME <IR|ONNX|...> # ov_add_frontend(NAME <IR|ONNX|...>
# FILEDESCRIPTION <description> # FILEDESCRIPTION <description> # used on Windows to describe DLL file
# [LINKABLE_FRONTEND] # [LINKABLE_FRONTEND] # whether we can use FE API directly or via FEM only
# [SKIP_INSTALL] # [SKIP_INSTALL] # private frontend, not for end users
# [PROTOBUF_LITE] # [PROTOBUF_LITE] # requires only libprotobuf-lite
# [SKIP_NCC_STYLE] # use custom NCC rules
# [LINK_LIBRARIES <lib1 lib2 ...>]) # [LINK_LIBRARIES <lib1 lib2 ...>])
# #
macro(ov_add_frontend) macro(ov_add_frontend)
@ -99,7 +101,7 @@ macro(ov_add_frontend)
endif() endif()
endforeach() endforeach()
set(TARGET_NAME "${OV_FRONTEND_NAME}${FRONTEND_NAME_SUFFIX}") set(TARGET_NAME "${FRONTEND_NAME_PREFIX}${OV_FRONTEND_NAME}${FRONTEND_NAME_SUFFIX}")
list(APPEND FRONTEND_NAMES ${OV_FRONTEND_NAME}) list(APPEND FRONTEND_NAMES ${OV_FRONTEND_NAME})
set(FRONTEND_NAMES "${FRONTEND_NAMES}" CACHE INTERNAL "" FORCE) set(FRONTEND_NAMES "${FRONTEND_NAMES}" CACHE INTERNAL "" FORCE)
@ -178,9 +180,9 @@ macro(ov_add_frontend)
set_target_properties(${TARGET_NAME} PROPERTIES SOVERSION 2022.1.1) set_target_properties(${TARGET_NAME} PROPERTIES SOVERSION 2022.1.1)
target_link_libraries(${TARGET_NAME} PRIVATE frontend_common::static ${OV_FRONTEND_LINK_LIBRARIES}) target_link_libraries(${TARGET_NAME} PRIVATE openvino::runtime ${OV_FRONTEND_LINK_LIBRARIES})
# WA for TF frontends which always requires protobuf (not protobuf-lite) # WA for TF frontends which always require protobuf (not protobuf-lite)
# if TF FE is built in static mode, use protobuf for all other FEs # if TF FE is built in static mode, use protobuf for all other FEs
if(FORCE_FRONTENDS_USE_PROTOBUF) if(FORCE_FRONTENDS_USE_PROTOBUF)
set(OV_FRONTEND_PROTOBUF_LITE OFF) set(OV_FRONTEND_PROTOBUF_LITE OFF)
@ -228,8 +230,8 @@ macro(ov_add_frontend)
if(OV_FRONTEND_LINKABLE_FRONTEND) if(OV_FRONTEND_LINKABLE_FRONTEND)
# install -dev part # install -dev part
install(DIRECTORY ${${TARGET_NAME}_INCLUDE_DIR}/${OV_FRONTEND_NAME}_frontend install(DIRECTORY ${${TARGET_NAME}_INCLUDE_DIR}/openvino
DESTINATION ${FRONTEND_INSTALL_INCLUDE} DESTINATION ${FRONTEND_INSTALL_INCLUDE}/
COMPONENT core_dev COMPONENT core_dev
FILES_MATCHING PATTERN "*.hpp") FILES_MATCHING PATTERN "*.hpp")

View File

@ -4,7 +4,7 @@
#pragma once #pragma once
#include "common/frontend.hpp" #include "openvino/frontend/frontend.hpp"
@OV_FRONTEND_DECLARATIONS@ @OV_FRONTEND_DECLARATIONS@

View File

@ -82,11 +82,7 @@ function(ie_add_plugin)
ie_add_vs_version_file(NAME ${IE_PLUGIN_NAME} ie_add_vs_version_file(NAME ${IE_PLUGIN_NAME}
FILEDESCRIPTION "Inference Engine ${IE_PLUGIN_DEVICE_NAME} device plugin library") FILEDESCRIPTION "Inference Engine ${IE_PLUGIN_DEVICE_NAME} device plugin library")
if(TARGET IE::inference_engine_plugin_api) target_link_libraries(${IE_PLUGIN_NAME} PRIVATE openvino::runtime openvino::runtime::dev)
target_link_libraries(${IE_PLUGIN_NAME} PRIVATE IE::inference_engine IE::inference_engine_plugin_api)
else()
target_link_libraries(${IE_PLUGIN_NAME} PRIVATE inference_engine inference_engine_plugin_api)
endif()
if(WIN32) if(WIN32)
set_target_properties(${IE_PLUGIN_NAME} PROPERTIES COMPILE_PDB_NAME ${IE_PLUGIN_NAME}) set_target_properties(${IE_PLUGIN_NAME} PROPERTIES COMPILE_PDB_NAME ${IE_PLUGIN_NAME})
@ -119,20 +115,20 @@ function(ie_add_plugin)
# fake dependencies to build in the following order: # fake dependencies to build in the following order:
# IE -> IE readers -> IE inference plugins -> IE-based apps # IE -> IE readers -> IE inference plugins -> IE-based apps
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
if(TARGET ir_ov_frontend) if(TARGET ov_ir_frontend)
add_dependencies(${IE_PLUGIN_NAME} ir_ov_frontend) add_dependencies(${IE_PLUGIN_NAME} ov_ir_frontend)
endif() endif()
if(TARGET inference_engine_ir_v7_reader) if(TARGET inference_engine_ir_v7_reader)
add_dependencies(${IE_PLUGIN_NAME} inference_engine_ir_v7_reader) add_dependencies(${IE_PLUGIN_NAME} inference_engine_ir_v7_reader)
endif() endif()
if(TARGET onnx_ov_frontend) if(TARGET ov_onnx_frontend)
add_dependencies(${IE_PLUGIN_NAME} onnx_ov_frontend) add_dependencies(${IE_PLUGIN_NAME} ov_onnx_frontend)
endif() endif()
if(TARGET paddlepaddle_ov_frontend) if(TARGET ov_paddle_frontend)
add_dependencies(${IE_PLUGIN_NAME} paddlepaddle_ov_frontend) add_dependencies(${IE_PLUGIN_NAME} ov_paddle_frontend)
endif() endif()
if(TARGET tensorflow_ov_frontend) if(TARGET ov_tensorflow_frontend)
add_dependencies(${IE_PLUGIN_NAME} tensorflow_ov_frontend) add_dependencies(${IE_PLUGIN_NAME} ov_tensorflow_frontend)
endif() endif()
endif() endif()
@ -173,6 +169,10 @@ function(ie_add_plugin)
set(${IE_PLUGIN_DEVICE_NAME}_AS_EXTENSION "${IE_PLUGIN_AS_EXTENSION}" CACHE INTERNAL "" FORCE) set(${IE_PLUGIN_DEVICE_NAME}_AS_EXTENSION "${IE_PLUGIN_AS_EXTENSION}" CACHE INTERNAL "" FORCE)
endfunction() endfunction()
function(ov_add_plugin)
ie_add_plugin(${ARGN})
endfunction()
# #
# ie_register_plugins_dynamic(MAIN_TARGET <main target name> # ie_register_plugins_dynamic(MAIN_TARGET <main target name>
# POSSIBLE_PLUGINS <list of plugins which can be build by this repo>) # POSSIBLE_PLUGINS <list of plugins which can be build by this repo>)
@ -317,7 +317,7 @@ function(ie_generate_plugins_hpp)
endforeach() endforeach()
# add plugins to libraries including ie_plugins.hpp # add plugins to libraries including ie_plugins.hpp
ie_target_link_plugins(inference_engine) ie_target_link_plugins(ov_runtime)
if(TARGET inference_engine_s) if(TARGET inference_engine_s)
ie_target_link_plugins(inference_engine_s) ie_target_link_plugins(inference_engine_s)
endif() endif()
@ -347,7 +347,7 @@ function(ie_generate_plugins_hpp)
add_dependencies(inference_engine _ie_plugins_hpp) add_dependencies(inference_engine _ie_plugins_hpp)
# add dependency for object files # add dependency for object files
get_target_property(sources inference_engine SOURCES) get_target_property(sources inference_engine_obj SOURCES)
foreach(source IN LISTS sources) foreach(source IN LISTS sources)
if("${source}" MATCHES "\\$\\<TARGET_OBJECTS\\:([A-Za-z0-9_]*)\\>") if("${source}" MATCHES "\\$\\<TARGET_OBJECTS\\:([A-Za-z0-9_]*)\\>")
# object library # object library

View File

@ -26,6 +26,33 @@ function(ie_generate_dev_package_config)
@ONLY) @ONLY)
endfunction() endfunction()
function(ov_generate_dev_package_config)
# dummy check that OpenCV is here
find_package(OpenCV QUIET)
set(all_dev_targets gflags ov_runtime_libraries)
foreach(component IN LISTS openvino_export_components)
string(FIND "${component}" "_legacy" index)
if (index EQUAL -1)
# export all targets with prefix and use them during extra modules build
export(TARGETS ${${component}} NAMESPACE openvino::
APPEND FILE "${CMAKE_BINARY_DIR}/ov_${component}_dev_targets.cmake")
list(APPEND all_dev_targets ${${component}})
endif()
endforeach()
add_custom_target(ov_dev_targets DEPENDS ${all_dev_targets})
configure_package_config_file("${OpenVINO_SOURCE_DIR}/cmake/templates/OpenVINODeveloperPackageConfig.cmake.in"
"${CMAKE_BINARY_DIR}/OpenVINODeveloperPackageConfig.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/OpenVINOConfig-version.cmake.in"
"${CMAKE_BINARY_DIR}/OpenVINODeveloperPackageConfig-version.cmake"
@ONLY)
endfunction()
# #
# Add extra modules # Add extra modules
# #
@ -36,22 +63,32 @@ function(register_extra_modules)
openvino_developer_export_targets(COMPONENT core TARGETS ngraph) openvino_developer_export_targets(COMPONENT core TARGETS ngraph)
set(InferenceEngineDeveloperPackage_DIR "${CMAKE_CURRENT_BINARY_DIR}/runtime") set(InferenceEngineDeveloperPackage_DIR "${CMAKE_CURRENT_BINARY_DIR}/runtime")
set(OpenVINODeveloperPackage_DIR "${CMAKE_BINARY_DIR}/runtime")
function(generate_fake_dev_package) function(generate_fake_dev_package NS)
set(iedevconfig_file "${InferenceEngineDeveloperPackage_DIR}/InferenceEngineDeveloperPackageConfig.cmake") if (NS STREQUAL "openvino")
file(REMOVE "${iedevconfig_file}") set(devconfig_file "${OpenVINODeveloperPackage_DIR}/OpenVINODeveloperPackageConfig.cmake")
else()
set(devconfig_file "${InferenceEngineDeveloperPackage_DIR}/InferenceEngineDeveloperPackageConfig.cmake")
endif()
file(REMOVE "${devconfig_file}")
file(WRITE "${iedevconfig_file}" "\# !! AUTOGENERATED: DON'T EDIT !!\n\n") file(WRITE "${devconfig_file}" "\# !! AUTOGENERATED: DON'T EDIT !!\n\n")
file(APPEND "${iedevconfig_file}" "ie_deprecated_no_errors()\n") file(APPEND "${devconfig_file}" "ie_deprecated_no_errors()\n")
foreach(target IN LISTS ${openvino_export_components}) foreach(target IN LISTS ${openvino_export_components})
if(target) if(target)
file(APPEND "${iedevconfig_file}" "add_library(IE::${target} ALIAS ${target})\n") file(APPEND "${devconfig_file}" "add_library(${NS}::${target} ALIAS ${target})\n")
endif() endif()
endforeach() endforeach()
if ("${NS}" STREQUAL "openvino")
file(APPEND "${devconfig_file}" "add_library(${NS}::runtime ALIAS ov_runtime)\n")
file(APPEND "${devconfig_file}" "add_library(${NS}::runtime::dev ALIAS ov_runtime_dev)\n")
endif()
endfunction() endfunction()
generate_fake_dev_package() generate_fake_dev_package("openvino")
generate_fake_dev_package("IE")
# automatically import plugins from the 'runtime/plugins' folder # automatically import plugins from the 'runtime/plugins' folder
file(GLOB local_extra_modules "runtime/plugins/*") file(GLOB local_extra_modules "runtime/plugins/*")
@ -97,6 +134,7 @@ endfunction()
# during extra modules build since it's generated after modules # during extra modules build since it's generated after modules
# are configured # are configured
ie_generate_dev_package_config() ie_generate_dev_package_config()
ov_generate_dev_package_config()
# extra modules must be registered after inference_engine library # extra modules must be registered after inference_engine library
# and all other IE common libraries (ov_runtime_libraries) are creared # and all other IE common libraries (ov_runtime_libraries) are creared
@ -107,3 +145,6 @@ register_extra_modules()
# for static libraries case we need to generate final ie_plugins.hpp # for static libraries case we need to generate final ie_plugins.hpp
# with all the information about plugins # with all the information about plugins
ie_generate_plugins_hpp() ie_generate_plugins_hpp()
# used for static build
ov_generate_frontends_hpp()

View File

@ -6,7 +6,7 @@
# Common cmake options # Common cmake options
# #
ie_dependent_option (ENABLE_MKL_DNN "MKL-DNN plugin for inference engine" ON "X86_64" OFF) ie_dependent_option (ENABLE_INTEL_CPU "CPU plugin for inference engine" ON "X86_64" OFF)
ie_option (ENABLE_TESTS "unit, behavior and functional tests" OFF) ie_option (ENABLE_TESTS "unit, behavior and functional tests" OFF)
@ -87,22 +87,6 @@ ie_dependent_option (ENABLE_TBBBIND_2_5 "Enable TBBBind_2_5 static usage in Open
ie_dependent_option (ENABLE_INTEL_GNA "GNA support for inference engine" ON ie_dependent_option (ENABLE_INTEL_GNA "GNA support for inference engine" ON
"NOT APPLE;NOT ANDROID;X86_64;CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 5.4" OFF) "NOT APPLE;NOT ANDROID;X86_64;CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 5.4" OFF)
if (ENABLE_INTEL_GNA)
if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.4)
set (DEFAULT_GNA_LIB GNA1)
else()
set (DEFAULT_GNA_LIB GNA2)
endif()
set(GNA_LIBRARY_VERSION "${DEFAULT_GNA_LIB}" CACHE STRING "GNAVersion")
set_property(CACHE GNA_LIBRARY_VERSION PROPERTY STRINGS "GNA1" "GNA1_1401" "GNA2")
list (APPEND IE_OPTIONS GNA_LIBRARY_VERSION)
if (NOT GNA_LIBRARY_VERSION STREQUAL "GNA1" AND
NOT GNA_LIBRARY_VERSION STREQUAL "GNA1_1401" AND
NOT GNA_LIBRARY_VERSION STREQUAL "GNA2")
message(FATAL_ERROR "GNA_LIBRARY_VERSION should be set to GNA1, GNA1_1401 or GNA2. Default option is ${DEFAULT_GNA_LIB}")
endif()
endif()
if(ENABLE_TESTS OR BUILD_SHARED_LIBS) if(ENABLE_TESTS OR BUILD_SHARED_LIBS)
set(ENABLE_IR_V7_READER_DEFAULT ON) set(ENABLE_IR_V7_READER_DEFAULT ON)
else() else()
@ -116,6 +100,8 @@ ie_option (ENABLE_GAPI_PREPROCESSING "Enables G-API preprocessing" ON)
ie_option (ENABLE_MULTI "Enables MULTI Device Plugin" ON) ie_option (ENABLE_MULTI "Enables MULTI Device Plugin" ON)
ie_option (ENABLE_AUTO "Enables AUTO Device Plugin" ON) ie_option (ENABLE_AUTO "Enables AUTO Device Plugin" ON)
ie_option (ENABLE_AUTO_BATCH "Enables Auto-Batching Plugin" ON)
ie_option (ENABLE_HETERO "Enables Hetero Device Plugin" ON) ie_option (ENABLE_HETERO "Enables Hetero Device Plugin" ON)
ie_option (ENABLE_TEMPLATE "Enable template plugin" ON) ie_option (ENABLE_TEMPLATE "Enable template plugin" ON)
@ -163,11 +149,11 @@ else()
endif() endif()
ie_dependent_option(ENABLE_OV_ONNX_FRONTEND "Enable ONNX FrontEnd" ON "protoc_available" OFF) ie_dependent_option(ENABLE_OV_ONNX_FRONTEND "Enable ONNX FrontEnd" ON "protoc_available" OFF)
ie_dependent_option(ENABLE_OV_PDPD_FRONTEND "Enable PaddlePaddle FrontEnd" ON "protoc_available" OFF) ie_dependent_option(ENABLE_OV_PADDLE_FRONTEND "Enable PaddlePaddle FrontEnd" ON "protoc_available" OFF)
ie_option(ENABLE_OV_IR_FRONTEND "Enable IR FrontEnd" ON) ie_option(ENABLE_OV_IR_FRONTEND "Enable IR FrontEnd" ON)
ie_dependent_option(ENABLE_OV_TF_FRONTEND "Enable TensorFlow FrontEnd" ON "protoc_available" OFF) ie_dependent_option(ENABLE_OV_TF_FRONTEND "Enable TensorFlow FrontEnd" ON "protoc_available" OFF)
ie_dependent_option(ENABLE_SYSTEM_PROTOBUF "Use system protobuf" OFF ie_dependent_option(ENABLE_SYSTEM_PROTOBUF "Use system protobuf" OFF
"ENABLE_OV_ONNX_FRONTEND OR ENABLE_OV_PDPD_FRONTEND OR ENABLE_OV_TF_FRONTEND;BUILD_SHARED_LIBS" OFF) "ENABLE_OV_ONNX_FRONTEND OR ENABLE_OV_PADDLE_FRONTEND OR ENABLE_OV_TF_FRONTEND;BUILD_SHARED_LIBS" OFF)
ie_dependent_option(ENABLE_OV_CORE_UNIT_TESTS "Enables OpenVINO core unit tests" ON "ENABLE_TESTS;NOT ANDROID" OFF) ie_dependent_option(ENABLE_OV_CORE_UNIT_TESTS "Enables OpenVINO core unit tests" ON "ENABLE_TESTS;NOT ANDROID" OFF)
ie_dependent_option(ENABLE_OV_CORE_BACKEND_UNIT_TESTS "Control the building of unit tests using backends" ON ie_dependent_option(ENABLE_OV_CORE_BACKEND_UNIT_TESTS "Control the building of unit tests using backends" ON
"ENABLE_OV_CORE_UNIT_TESTS" OFF) "ENABLE_OV_CORE_UNIT_TESTS" OFF)
@ -207,17 +193,12 @@ if (ENABLE_INTEL_GPU)
add_definitions(-DENABLE_INTEL_GPU=1) add_definitions(-DENABLE_INTEL_GPU=1)
endif() endif()
if (ENABLE_MKL_DNN) if (ENABLE_INTEL_CPU)
add_definitions(-DENABLE_MKL_DNN=1) add_definitions(-DENABLE_INTEL_CPU=1)
endif() endif()
if (ENABLE_INTEL_GNA) if (ENABLE_INTEL_GNA)
add_definitions(-DENABLE_INTEL_GNA) add_definitions(-DENABLE_INTEL_GNA)
if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.4)
message(WARNING "${GNA_LIBRARY_VERSION} is not supported on GCC version ${CMAKE_CXX_COMPILER_VERSION}. Fallback to GNA1")
set(GNA_LIBRARY_VERSION GNA1)
endif()
endif() endif()
print_enabled_features() print_enabled_features()

View File

@ -49,12 +49,10 @@ find_dependency(ngraph
NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH) NO_DEFAULT_PATH)
# create targets with old names for compatibility find_dependency(OpenVINODeveloperPackage
if(TARGET openvino::core AND NOT TARGET IE::core) PATHS "${CMAKE_CURRENT_LIST_DIR}"
add_library(IE::core INTERFACE IMPORTED) NO_CMAKE_FIND_ROOT_PATH
set_target_properties(IE::core PROPERTIES NO_DEFAULT_PATH)
INTERFACE_LINK_LIBRARIES openvino::core)
endif()
if(TARGET openvino::runtime AND NOT TARGET IE::runtime) if(TARGET openvino::runtime AND NOT TARGET IE::runtime)
add_library(IE::runtime INTERFACE IMPORTED) add_library(IE::runtime INTERFACE IMPORTED)

View File

@ -11,7 +11,7 @@
# #
# * `Runtime`: OpenVINO C++ and C Core & Inference Runtime, frontend common # * `Runtime`: OpenVINO C++ and C Core & Inference Runtime, frontend common
# * `ONNX`: OpenVINO ONNX frontend # * `ONNX`: OpenVINO ONNX frontend
# * `PaddlePaddle`: OpenVINO PaddlePaddle frontend # * `Paddle`: OpenVINO Paddle frontend
# #
# If no components are specified, `Runtime` component is provided: # If no components are specified, `Runtime` component is provided:
# #
@ -32,19 +32,13 @@
# `openvino::runtime::c` # `openvino::runtime::c`
# The OpenVINO C Inference Runtime # The OpenVINO C Inference Runtime
# #
# `openvino::core`
# The OpenVINO C++ Core Runtime
#
# Frontend specific targets: # Frontend specific targets:
# #
# `openvino::frontend::common`
# OpenVINO frontend common
#
# `openvino::frontend::onnx` # `openvino::frontend::onnx`
# ONNX FrontEnd target (optional) # ONNX FrontEnd target (optional)
# #
# `openvino::frontend::paddlepaddle` # `openvino::frontend::paddle`
# PaddlePaddle FrontEnd target (optional) # Paddle FrontEnd target (optional)
# #
# `openvino::frontend::tensorflow` # `openvino::frontend::tensorflow`
# TensorFlow FrontEnd target (optional) # TensorFlow FrontEnd target (optional)
@ -63,8 +57,8 @@
# `OpenVINO_Frontend_ONNX_FOUND` # `OpenVINO_Frontend_ONNX_FOUND`
# OpenVINO ONNX frontend is available # OpenVINO ONNX frontend is available
# #
# `OpenVINO_Frontend_PaddlePaddle_FOUND` # `OpenVINO_Frontend_Paddle_FOUND`
# OpenVINO PaddlePaddle frontend is available # OpenVINO Paddle frontend is available
# #
# `OpenVINO_Frontend_TensorFlow_FOUND` # `OpenVINO_Frontend_TensorFlow_FOUND`
# OpenVINO TensorFlow frontend is available # OpenVINO TensorFlow frontend is available
@ -174,9 +168,17 @@ endif()
_ov_find_dependency(Threads) _ov_find_dependency(Threads)
if(NOT TARGET inference_engine) if(NOT TARGET ov_runtime)
set(_ov_as_external_package ON) set(_ov_as_external_package ON)
include("${CMAKE_CURRENT_LIST_DIR}/OpenVINOTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/OpenVINOTargets.cmake")
# WA for cmake version < 3.16 which does not export
# IMPORTED_LINK_DEPENDENT_LIBRARIES_** properties if no PUBLIC dependencies for the library
if((THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") AND TBB_FOUND)
foreach (type RELEASE DEBUG RELWITHDEBINFO MINSIZEREL)
set_property(TARGET openvino::runtime APPEND PROPERTY IMPORTED_LINK_DEPENDENT_LIBRARIES_${type} "TBB::tbb;TBB::tbbmalloc")
endforeach()
endif()
endif() endif()
# #
@ -186,12 +188,12 @@ endif()
set(${CMAKE_FIND_PACKAGE_NAME}_Runtime_FOUND ON) set(${CMAKE_FIND_PACKAGE_NAME}_Runtime_FOUND ON)
set(${CMAKE_FIND_PACKAGE_NAME}_ONNX_FOUND @ENABLE_OV_ONNX_FRONTEND@) set(${CMAKE_FIND_PACKAGE_NAME}_ONNX_FOUND @ENABLE_OV_ONNX_FRONTEND@)
set(${CMAKE_FIND_PACKAGE_NAME}_PaddlePaddle_FOUND @ENABLE_OV_PDPD_FRONTEND@) set(${CMAKE_FIND_PACKAGE_NAME}_Paddle_FOUND @ENABLE_OV_PADDLE_FRONTEND@)
set(${CMAKE_FIND_PACKAGE_NAME}_TensorFlow_FOUND @ENABLE_OV_TF_FRONTEND@) set(${CMAKE_FIND_PACKAGE_NAME}_TensorFlow_FOUND @ENABLE_OV_TF_FRONTEND@)
set(${CMAKE_FIND_PACKAGE_NAME}_IR_FOUND @ENABLE_OV_IR_FRONTEND@) set(${CMAKE_FIND_PACKAGE_NAME}_IR_FOUND @ENABLE_OV_IR_FRONTEND@)
set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_ONNX_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_ONNX_FOUND}) set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_ONNX_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_ONNX_FOUND})
set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_PaddlePaddle_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_PaddlePaddle_FOUND}) set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_Paddle_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_Paddle_FOUND})
set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_TensorFlow_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_TensorFlow_FOUND}) set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_TensorFlow_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_TensorFlow_FOUND})
set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_IR_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_IR_FOUND}) set(${CMAKE_FIND_PACKAGE_NAME}_Frontend_IR_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_IR_FOUND})
@ -204,9 +206,8 @@ endif()
# Apply common functions # Apply common functions
# #
foreach(target openvino::runtime openvino::runtime::c openvino::core foreach(target openvino::runtime openvino::runtime::c
openvino::frontend::common openvino::frontend::onnx openvino::frontend::onnx openvino::frontend::paddle openvino::frontend::tensorflow)
openvino::frontend::paddlepaddle openvino::frontend::tensorflow)
if(TARGET ${target} AND _ov_as_external_package) if(TARGET ${target} AND _ov_as_external_package)
_ov_target_no_deprecation_error(${target}) _ov_target_no_deprecation_error(${target})
endif() endif()
@ -224,6 +225,6 @@ if(_need_package_name_reset)
unset(_need_package_name_reset) unset(_need_package_name_reset)
endif() endif()
unset(${CMAKE_FIND_PACKAGE_NAME}_PaddlePaddle_FOUND) unset(${CMAKE_FIND_PACKAGE_NAME}_Paddle_FOUND)
unset(${CMAKE_FIND_PACKAGE_NAME}_ONNX_FOUND) unset(${CMAKE_FIND_PACKAGE_NAME}_ONNX_FOUND)
unset(${CMAKE_FIND_PACKAGE_NAME}_TensorFlow_FOUND) unset(${CMAKE_FIND_PACKAGE_NAME}_TensorFlow_FOUND)

View File

@ -0,0 +1,78 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
set_and_check(OpenVINO_SOURCE_DIR "@OpenVINO_SOURCE_DIR@")
# Variables to export in plugin's projects
set(ie_options "@IE_OPTIONS@;CMAKE_BUILD_TYPE;CMAKE_SKIP_RPATH")
list(APPEND ie_options CMAKE_CXX_COMPILER_LAUNCHER CMAKE_C_COMPILER_LAUNCHER)
file(TO_CMAKE_PATH "${CMAKE_CURRENT_LIST_DIR}" cache_path)
message(STATUS "The following CMake options are exported from OpenVINO Developer package")
message("")
foreach(option IN LISTS ie_options)
if(NOT DEFINED "${option}")
load_cache("${cache_path}" READ_WITH_PREFIX "" ${option})
endif()
message(" ${option}: ${${option}}")
endforeach()
message("")
# for samples in 3rd party projects
set_and_check(gflags_DIR "@gflags_BINARY_DIR@")
#
# Content
#
find_dependency(IEDevScripts
PATHS "${OpenVINO_SOURCE_DIR}/cmake/developer_package"
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH)
find_dependency(OpenVINO
PATHS "${CMAKE_CURRENT_LIST_DIR}"
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH)
foreach(component @openvino_export_components@)
string(FIND "${component}" "_legacy" index)
if (index EQUAL -1)
include("${CMAKE_CURRENT_LIST_DIR}/ov_${component}_dev_targets.cmake")
endif()
endforeach()
if(ENABLE_SYSTEM_PUGIXML)
find_dependency(PugiXML)
set_property(TARGET pugixml PROPERTY IMPORTED_GLOBAL TRUE)
add_library(IE::pugixml ALIAS pugixml)
endif()
# inherit OpenCV from main IE project if enabled
if ("@OpenCV_FOUND@")
load_cache("${cache_path}" READ_WITH_PREFIX "" OpenCV_DIR)
find_dependency(OpenCV)
endif()
#
# Extra Compile Flags
#
if(NOT MSVC)
ie_add_compiler_flags(-Wno-error=unused-variable)
if(CMAKE_COMPILER_IS_GNUCXX)
ie_add_compiler_flags(-Wno-error=unused-but-set-variable)
if(SUGGEST_OVERRIDE_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-suggest-override")
endif()
endif()
endif()
# Don't threat deprecated API warnings as errors in 3rd party apps
ie_deprecated_no_errors()

View File

@ -26,13 +26,11 @@
# #
# Frontends: # Frontends:
# #
# ngraph::common - nGraph frontend common # ngraph_ov_onnx_frontend_FOUND - True if the system has ov_onnx_frontend library
# ngraph::ov_onnx_frontend - ONNX FrontEnd target (optional)
# #
# ngraph_onnx_ov_frontend_FOUND - True if the system has onnx_ov_frontend library # ngraph_paddle_frontend_FOUND - True if the system has Paddle frontend
# ngraph::onnx_ov_frontend - ONNX FrontEnd target (optional) # ngraph::ov_paddle_frontend - nGraph Paddle frontend (optional)
#
# ngraph_paddlepaddle_frontend_FOUND - True if the system has PDPD frontend
# ngraph::paddlepaddle_ov_frontend - nGraph PDPD frontend (optional)
# #
@PACKAGE_INIT@ @PACKAGE_INIT@
@ -46,54 +44,48 @@ find_dependency(OpenVINO
NO_DEFAULT_PATH) NO_DEFAULT_PATH)
# create targets with old names for compatibility # create targets with old names for compatibility
if(TARGET openvino::core AND NOT TARGET ngraph::ngraph) if(TARGET openvino::runtime AND NOT TARGET ngraph::ngraph)
add_library(ngraph::ngraph INTERFACE IMPORTED) add_library(ngraph::ngraph INTERFACE IMPORTED)
set_target_properties(ngraph::ngraph PROPERTIES set_target_properties(ngraph::ngraph PROPERTIES
INTERFACE_LINK_LIBRARIES openvino::core) INTERFACE_LINK_LIBRARIES openvino::runtime)
endif() endif()
if(TARGET openvino::frontend::common AND NOT TARGET ngraph::frontend_common) if(TARGET openvino::frontend::onnx AND NOT TARGET ngraph::ov_onnx_frontend)
add_library(ngraph::frontend_common INTERFACE IMPORTED) add_library(ngraph::ov_onnx_frontend INTERFACE IMPORTED)
set_target_properties(ngraph::frontend_common PROPERTIES set_target_properties(ngraph::ov_onnx_frontend PROPERTIES
INTERFACE_LINK_LIBRARIES openvino::frontend::common)
endif()
if(TARGET openvino::frontend::onnx AND NOT TARGET ngraph::onnx_ov_frontend)
add_library(ngraph::onnx_ov_frontend INTERFACE IMPORTED)
set_target_properties(ngraph::onnx_ov_frontend PROPERTIES
INTERFACE_LINK_LIBRARIES openvino::frontend::onnx) INTERFACE_LINK_LIBRARIES openvino::frontend::onnx)
endif() endif()
if(TARGET openvino::frontend::paddlepaddle AND NOT TARGET ngraph::paddlepaddle_ov_frontend) if(TARGET openvino::frontend::paddle AND NOT TARGET ngraph::ov_paddle_frontend)
add_library(ngraph::paddlepaddle_ov_frontend INTERFACE IMPORTED) add_library(ngraph::ov_paddle_frontend INTERFACE IMPORTED)
set_target_properties(ngraph::paddlepaddle_ov_frontend PROPERTIES set_target_properties(ngraph::ov_paddle_frontend PROPERTIES
INTERFACE_LINK_LIBRARIES openvino::frontend::paddlepaddle) INTERFACE_LINK_LIBRARIES openvino::frontend::paddle)
endif() endif()
if(TARGET openvino::frontend::tensorflow AND NOT TARGET ngraph::tensorflow_ov_frontend) if(TARGET openvino::frontend::tensorflow AND NOT TARGET ngraph::ov_tensorflow_frontend)
add_library(ngraph::tensorflow_ov_frontend INTERFACE IMPORTED) add_library(ngraph::ov_tensorflow_frontend INTERFACE IMPORTED)
set_target_properties(ngraph::tensorflow_ov_frontend PROPERTIES set_target_properties(ngraph::ov_tensorflow_frontend PROPERTIES
INTERFACE_LINK_LIBRARIES openvino::frontend::tensorflow) INTERFACE_LINK_LIBRARIES openvino::frontend::tensorflow)
endif() endif()
set(ngraph_ngraph_FOUND ON) set(ngraph_ngraph_FOUND ON)
set(NGRAPH_LIBRARIES ngraph::ngraph) set(NGRAPH_LIBRARIES ngraph::ngraph)
set(ngraph_onnx_ov_frontend_FOUND ${OpenVINO_Frontend_ONNX_FOUND}) set(ngraph_ov_onnx_frontend_FOUND ${OpenVINO_Frontend_ONNX_FOUND})
set(ngraph_onnx_importer_FOUND ${OpenVINO_Frontend_ONNX_FOUND}) set(ngraph_onnx_importer_FOUND ${OpenVINO_Frontend_ONNX_FOUND})
if(ngraph_onnx_importer_FOUND) if(ngraph_onnx_importer_FOUND)
set(ONNX_IMPORTER_LIBRARIES ngraph::onnx_ov_frontend) set(ONNX_IMPORTER_LIBRARIES ngraph::ov_onnx_frontend)
# ngraph::onnx_importer target and variables are deprecated # ngraph::onnx_importer target and variables are deprecated
# but need to create a dummy target for BW compatibility # but need to create a dummy target for BW compatibility
if(NOT TARGET ngraph::onnx_importer) if(NOT TARGET ngraph::onnx_importer)
add_library(ngraph::onnx_importer INTERFACE IMPORTED) add_library(ngraph::onnx_importer INTERFACE IMPORTED)
set_target_properties(ngraph::onnx_importer PROPERTIES set_target_properties(ngraph::onnx_importer PROPERTIES
INTERFACE_LINK_LIBRARIES ngraph::onnx_ov_frontend) INTERFACE_LINK_LIBRARIES ngraph::ov_onnx_frontend)
endif() endif()
endif() endif()
set(ngraph_paddlepaddle_frontend_FOUND ${OpenVINO_Frontend_PaddlePaddle_FOUND}) set(ngraph_paddle_frontend_FOUND ${OpenVINO_Frontend_Paddle_FOUND})
set(ngraph_tensorflow_frontend_FOUND ${OpenVINO_Frontend_TensorFlow_FOUND}) set(ngraph_tensorflow_frontend_FOUND ${OpenVINO_Frontend_TensorFlow_FOUND})
set(ngraph_ir_frontend_FOUND ${OpenVINO_Frontend_IR_FOUND}) set(ngraph_ir_frontend_FOUND ${OpenVINO_Frontend_IR_FOUND})

View File

@ -136,8 +136,8 @@ if(ENABLE_TESTS)
add_dependencies(test_model_zoo test_pip_prerequsites) add_dependencies(test_model_zoo test_pip_prerequsites)
endif() endif()
if (ENABLE_OV_PDPD_FRONTEND AND ENABLE_OV_CORE_UNIT_TESTS) if (ENABLE_OV_PADDLE_FRONTEND AND ENABLE_OV_CORE_UNIT_TESTS)
add_dependencies(test_model_zoo paddlepaddle_test_models) add_dependencies(test_model_zoo paddle_test_models)
endif() endif()
install(DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_model_zoo" install(DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_model_zoo"

View File

@ -23,8 +23,8 @@ if(NOT ENABLE_DOCKER)
add_subdirectory(template_extension) add_subdirectory(template_extension)
set(all_docs_targets set(all_docs_targets
ie_docs_snippets templateFuncTests ie_docs_snippets ov_template_func_tests
template_extension template_ov_extension templatePlugin) template_extension ov_template_extension ov_template_plugin)
foreach(target_name IN LISTS all_docs_targets) foreach(target_name IN LISTS all_docs_targets)
if(TARGET ${target_name}) if(TARGET ${target_name})
set_target_properties(${target_name} PROPERTIES FOLDER docs) set_target_properties(${target_name} PROPERTIES FOLDER docs)
@ -36,7 +36,7 @@ if(NOT ENABLE_DOCKER)
# install # install
foreach(target templatePlugin template_extension template_ov_extension) foreach(target ov_template_plugin template_extension ov_template_extension)
if(TARGET ${target}) if(TARGET ${target})
install(TARGETS ${target} install(TARGETS ${target}
LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH} LIBRARY DESTINATION ${IE_CPACK_RUNTIME_PATH}
@ -46,335 +46,189 @@ if(NOT ENABLE_DOCKER)
endforeach() endforeach()
endif() endif()
set(OMZ_DOCS_DIR "" CACHE PATH "Path to open_model_zoo documentation") set(LINKCHECKER_PY "" CACHE FILEPATH "Path to linkchecker.py for documentation check dir.")
set(WORKBENCH_DOCS_DIR "" CACHE PATH "Path to workbench documentation") set(OMZ_DOCS_DIR "" CACHE PATH "Path to open_model_zoo documentation dir.")
set(POT_DOCS_DIR "" CACHE PATH "Path to post-training-compression-tool documentation") set(WORKBENCH_DOCS_DIR "" CACHE PATH "Path to workbench documentation dir.")
set(GST_DOCS_DIR "" CACHE PATH "Path to gst-video-analytics documentation") set(POT_DOCS_DIR "" CACHE PATH "Path to post-training-compression-tool documentation dir.")
set(OVMS_DOCS_DIR "" CACHE PATH "Path to model server documentation dir.")
set(GST_DOCS_DIR "" CACHE PATH "Path to gst-video-analytics documentation dir.")
set(GITHUB_API_TOKEN "" CACHE PATH "Path to file containing github api token.")
set(GRAPH_CSV_DIR "" CACHE PATH "Path to the folder containing csv data for rendering graphs.")
function(build_docs) function(build_docs)
find_package(Doxygen REQUIRED dot) find_package(Doxygen REQUIRED dot)
find_package(LATEX REQUIRED) find_package(LATEX REQUIRED)
ie_check_pip_package(lxml FATAL_ERROR) find_program(DOXYREST_EXECUTABLE NAMES doxyrest)
ie_check_pip_package(LinkChecker WARNING) if (NOT DOXYREST_EXECUTABLE)
message(FATAL_ERROR "No doxyrest found. Documentation output is not available")
find_host_program(LINKCHECKER_PY endif()
NAMES linkchecker
DOC "linkchecker tools for documentation check")
set(DOCS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}") set(DOCS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(DOXYGEN_DIR "${OpenVINO_SOURCE_DIR}/docs/doxygen") set(DOCS_SOURCE_DIR "${OpenVINO_SOURCE_DIR}/docs")
set(IE_SOURCE_DIR "${OpenVINO_SOURCE_DIR}/inference-engine") set(SCRIPTS_DIR "${DOCS_SOURCE_DIR}/scripts")
set(OV_INFERENCE_DIR "${OpenVINO_SOURCE_DIR}/src/inference")
set(PYTHON_API_IN "${IE_SOURCE_DIR}/ie_bridges/python/src/openvino/inference_engine/ie_api.pyx") # markdown docs
set(PYTHON_API_OUT "${DOCS_BUILD_DIR}/python_api/ie_api.pyx") set(MARKDOWN_INPUT "${DOCS_BUILD_DIR}")
set(C_API "${OpenVINO_SOURCE_DIR}/bindings/c/include")
set(PLUGIN_API_DIR "${DOCS_BUILD_DIR}/IE_PLUGIN_DG")
set(CORE_DIR "${OpenVINO_SOURCE_DIR}/src/core")
set(FRONTENDS_DIR "${OpenVINO_SOURCE_DIR}/src/frontends")
set(NGRAPH_PY_DIR "${OpenVINO_SOURCE_DIR}/src/bindings/python/src/compatibility/ngraph/")
# Preprocessing scripts # Preprocessing scripts
set(DOXY_MD_FILTER "${DOXYGEN_DIR}/doxy_md_filter.py") set(DOXY_MD_FILTER "${SCRIPTS_DIR}/doxy_md_filter.py")
set(DOXY_LAYOUT_SCRIPT "${DOXYGEN_DIR}/build_main_layout.py") set(PYNGRAPH_REF_SCRIPT "${SCRIPTS_DIR}/pyngraph_ref.py")
set(DOXY_LOG_SCRIPT "${DOXYGEN_DIR}/log.py") set(DOXY_LOG_SCRIPT "${SCRIPTS_DIR}/log.py")
set(PYX_FILTER "${DOXYGEN_DIR}/pyx_filter.py") set(PYX_FILTER "${SCRIPTS_DIR}/pyx_filter.py")
set(PREPARE_XML_SCRIPT "${SCRIPTS_DIR}/prepare_xml.py")
# assets dir set(REMOVE_XML_SCRIPT "${SCRIPTS_DIR}/remove_xml.py")
set(ASSETS_DIR "${DOXYGEN_DIR}/assets") set(COPY_IMAGES_SCRIPT "${SCRIPTS_DIR}/copy_images.py")
set(DOC_TEST_DIR "${SCRIPTS_DIR}/tests")
# header and footer set(DOXYGEN_MAPPING_SCRIPT "${SCRIPTS_DIR}/create_mapping.py")
set(HEADER_SOURCE "${DOXYGEN_DIR}/header.html.in") set(DOXYGEN_MAPPING_FILE "${DOCS_BUILD_DIR}/mapping.json")
set(FOOTER_SOURCE "${DOXYGEN_DIR}/footer.html.in")
set(HEADER_BUILD "${DOCS_BUILD_DIR}/header.html")
set(FOOTER_BUILD "${DOCS_BUILD_DIR}/footer.html")
configure_file(${HEADER_SOURCE} ${HEADER_BUILD} @ONLY)
configure_file(${FOOTER_SOURCE} ${FOOTER_BUILD} @ONLY)
file(GLOB_RECURSE doc_source_files
LIST_DIRECTORIES true RELATIVE ${OpenVINO_SOURCE_DIR}
"${OpenVINO_SOURCE_DIR}/docs/*.md"
"${OpenVINO_SOURCE_DIR}/docs/*.png"
"${OpenVINO_SOURCE_DIR}/docs/*.gif"
"${OpenVINO_SOURCE_DIR}/docs/*.jpg"
"${OpenVINO_SOURCE_DIR}/docs/*.svg"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.md"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.png"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.gif"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.jpg"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.svg")
configure_file(${PYTHON_API_IN} ${PYTHON_API_OUT} @ONLY)
set(NGRAPH_CPP_CONFIG_SOURCE "${DOXYGEN_DIR}/ngraph_cpp_api.config")
set(NGRAPH_PY_CONFIG_SOURCE "${DOXYGEN_DIR}/ngraph_py_api.config")
set(IE_CONFIG_SOURCE "${DOXYGEN_DIR}/ie_docs.config")
set(C_CONFIG_SOURCE "${DOXYGEN_DIR}/ie_c_api.config")
set(PY_CONFIG_SOURCE "${DOXYGEN_DIR}/ie_py_api.config")
set(PLUGIN_CONFIG_SOURCE "${DOXYGEN_DIR}/ie_plugin_api.config")
set(NGRAPH_CPP_CONFIG_BUILD "${DOCS_BUILD_DIR}/ngraph_cpp_api.config")
set(NGRAPH_PY_CONFIG_BUILD "${DOCS_BUILD_DIR}/ngraph_py_api.config")
set(IE_CONFIG_BUILD "${DOCS_BUILD_DIR}/ie_docs.config")
set(C_CONFIG_BUILD "${DOCS_BUILD_DIR}/ie_c_api.config")
set(PY_CONFIG_BUILD "${DOCS_BUILD_DIR}/ie_py_api.config")
set(PLUGIN_CONFIG_BUILD "${DOCS_BUILD_DIR}/ie_plugin_api.config")
set(NGRAPH_CPP_LAYOUT_SOURCE "${DOXYGEN_DIR}/ngraph_cpp_api.xml")
set(NGRAPH_PY_LAYOUT_SOURCE "${DOXYGEN_DIR}/ngraph_py_api.xml")
set(IE_LAYOUT_SOURCE "${DOXYGEN_DIR}/ie_docs.xml")
set(OPENVINO_LAYOUT_SOURCE "${DOXYGEN_DIR}/openvino_docs.xml")
set(C_LAYOUT_SOURCE "${DOXYGEN_DIR}/ie_c_api.xml")
set(PY_LAYOUT_SOURCE "${DOXYGEN_DIR}/ie_py_api.xml")
set(PLUGIN_LAYOUT_SOURCE "${DOXYGEN_DIR}/ie_plugin_api.xml")
set(NGRAPH_CPP_LAYOUT_BUILD "${DOCS_BUILD_DIR}/ngraph_cpp_api.xml")
set(NGRAPH_PY_LAYOUT_BUILD "${DOCS_BUILD_DIR}/ngraph_py_api.xml")
set(IE_LAYOUT_BUILD "${DOCS_BUILD_DIR}/ie_docs.xml")
set(OPENVINO_LAYOUT_BUILD "${DOCS_BUILD_DIR}/openvino_docs.xml")
set(C_LAYOUT_BUILD "${DOCS_BUILD_DIR}/ie_c_api.xml")
set(PY_LAYOUT_BUILD "${DOCS_BUILD_DIR}/ie_py_api.xml")
set(PLUGIN_LAYOUT_BUILD "${DOCS_BUILD_DIR}/ie_plugin_api.xml")
# out dirs # out dirs
set(OUTPUT_DIRECTORY "${DOCS_BUILD_DIR}/html") set(XML_OUTPUT "${DOCS_BUILD_DIR}/xml")
set(IE_OUTPUT "${OUTPUT_DIRECTORY}") set(RST_OUTPUT "${DOCS_BUILD_DIR}/rst")
set(C_OUTPUT "${OUTPUT_DIRECTORY}/ie_c_api") set(SPHINX_OUTPUT "${DOCS_BUILD_DIR}/_build")
set(PY_OUTPUT "${OUTPUT_DIRECTORY}/ie_python_api")
set(PLUGIN_OUTPUT "${OUTPUT_DIRECTORY}/ie_plugin_api")
set(NGRAPH_CPP_OUTPUT "${OUTPUT_DIRECTORY}/ngraph_cpp_api")
set(NGRAPH_PY_OUTPUT "${OUTPUT_DIRECTORY}/ngraph_python_api")
# Tables of contents # Sphinx folders, doxyrest templates and config
configure_file(${NGRAPH_CPP_LAYOUT_SOURCE} ${NGRAPH_CPP_LAYOUT_BUILD} @ONLY) set(SPHINX_CONF_IN "${DOCS_SOURCE_DIR}/conf.py")
configure_file(${NGRAPH_PY_LAYOUT_SOURCE} ${NGRAPH_PY_LAYOUT_BUILD} @ONLY) set(SPHINX_CONF_OUT "${RST_OUTPUT}/conf.py")
configure_file(${IE_LAYOUT_SOURCE} ${IE_LAYOUT_BUILD} @ONLY) set(SPHINX_STATIC_IN "${DOCS_SOURCE_DIR}/_static")
configure_file(${OPENVINO_LAYOUT_SOURCE} ${OPENVINO_LAYOUT_BUILD} @ONLY) set(SPHINX_STATIC_OUT "${RST_OUTPUT}/_static")
configure_file(${C_LAYOUT_SOURCE} ${C_LAYOUT_BUILD} @ONLY) set(SPHINX_INDEX_IN "${DOCS_SOURCE_DIR}/index.rst")
configure_file(${PY_LAYOUT_SOURCE} ${PY_LAYOUT_BUILD} @ONLY) set(SPHINX_INDEX_OUT "${RST_OUTPUT}/index.rst")
configure_file(${PLUGIN_LAYOUT_SOURCE} ${PLUGIN_LAYOUT_BUILD} @ONLY) set(API_DOCS_IN "${DOCS_SOURCE_DIR}/api")
set(API_DOCS_OUT "${RST_OUTPUT}/api")
set(DOXYREST_IN "${DOCS_SOURCE_DIR}/doxyrest")
set(DOXYREST_OUT "${DOCS_BUILD_DIR}/doxyrest")
set(DOXYREST_SPHINX_IN "${DOCS_SOURCE_DIR}/doxyrest-sphinx")
set(DOXYREST_SPHINX_OUT "${RST_OUTPUT}/doxyrest-sphinx")
set(DOXYREST_CONFIG_IN "${DOCS_SOURCE_DIR}/doxyrest-config.lua")
set(DOXYREST_CONFIG_OUT "${DOCS_BUILD_DIR}/doxyrest-config.lua")
configure_file(${DOXYREST_CONFIG_IN} ${DOXYREST_CONFIG_OUT} @ONLY)
configure_file(${SPHINX_CONF_IN} ${SPHINX_CONF_OUT} @ONLY)
# Doxygen config files # Doxygen config
configure_file(${NGRAPH_CPP_CONFIG_SOURCE} ${NGRAPH_CPP_CONFIG_BUILD} @ONLY) set(DOXYFILE_SOURCE "${DOCS_SOURCE_DIR}/Doxyfile.config")
configure_file(${NGRAPH_PY_CONFIG_SOURCE} ${NGRAPH_PY_CONFIG_BUILD} @ONLY) set(DOXYFILE_BUILD "${DOCS_BUILD_DIR}/Doxyfile.config")
configure_file(${IE_CONFIG_SOURCE} ${IE_CONFIG_BUILD} @ONLY) configure_file(${DOXYFILE_SOURCE} ${DOXYFILE_BUILD} @ONLY)
configure_file(${C_CONFIG_SOURCE} ${C_CONFIG_BUILD} @ONLY)
configure_file(${PY_CONFIG_SOURCE} ${PY_CONFIG_BUILD} @ONLY)
configure_file(${PLUGIN_CONFIG_SOURCE} ${PLUGIN_CONFIG_BUILD} @ONLY)
# Preprocessing scripts list(APPEND commands COMMAND ${PYTHON_EXECUTABLE} ${DOXY_MD_FILTER}
set(DOXY_MD_FILTER "${DOXYGEN_DIR}/doxy_md_filter.py") --input_dir=${OpenVINO_SOURCE_DIR}
set(PYX_FILTER "${DOXYGEN_DIR}/pyx_filter.py") --output_dir=${DOCS_BUILD_DIR}/openvino
--exclude_dir=${DOCS_BUILD_DIR})
# nGraph C++ API # include additional repositories
add_custom_target(ngraph_cpp_api # openvino notebooks dir
COMMAND ${CMAKE_COMMAND} -E copy_directory ${ASSETS_DIR} ${NGRAPH_CPP_OUTPUT}/assets if(GITHUB_API_TOKEN)
COMMAND ${DOXYGEN_EXECUTABLE} ${NGRAPH_CPP_CONFIG_BUILD} set(NBDOC_SCRIPT "${DOCS_SOURCE_DIR}/nbdoc/nbdoc.py")
WORKING_DIRECTORY ${DOCS_BUILD_DIR} list(APPEND commands
VERBATIM) COMMAND ${PYTHON_EXECUTABLE} "${NBDOC_SCRIPT}" "${GITHUB_API_TOKEN}" "${RST_OUTPUT}/notebooks"
)
endif()
# nGraph Python API if(GRAPH_CSV_DIR)
set(GRAPH_CSV_DIR_OUT "${RST_OUTPUT}/csv")
add_custom_target(ngraph_py_api list(APPEND commands
COMMAND ${CMAKE_COMMAND} -E copy_directory ${ASSETS_DIR} ${NGRAPH_PY_OUTPUT}/assets COMMAND ${CMAKE_COMMAND} -E copy_directory "${GRAPH_CSV_DIR}" "${GRAPH_CSV_DIR_OUT}"
COMMAND ${DOXYGEN_EXECUTABLE} ${NGRAPH_PY_CONFIG_BUILD} )
WORKING_DIRECTORY ${DOCS_BUILD_DIR} endif()
VERBATIM)
# C API
add_custom_target(c_api
COMMAND ${CMAKE_COMMAND} -E copy_directory ${ASSETS_DIR} ${C_OUTPUT}/assets
COMMAND ${DOXYGEN_EXECUTABLE} ${C_CONFIG_BUILD}
WORKING_DIRECTORY ${DOCS_BUILD_DIR}
COMMENT "Generating C API Reference"
VERBATIM)
# Python API
add_custom_target(py_api
COMMAND ${CMAKE_COMMAND} -E copy_directory ${ASSETS_DIR} ${PY_OUTPUT}/assets
COMMAND ${DOXYGEN_EXECUTABLE} ${PY_CONFIG_BUILD}
WORKING_DIRECTORY ${DOCS_BUILD_DIR}
COMMENT "Generating Python API Reference"
VERBATIM)
add_custom_command(TARGET py_api
PRE_BUILD
COMMAND ${PYTHON_EXECUTABLE} ${PYX_FILTER} ${PYTHON_API_OUT}
COMMENT "Pre-process Python API")
# Preprocess docs
add_custom_target(preprocess_docs
COMMENT "Pre-process docs"
VERBATIM)
# ovino doc files
file(GLOB_RECURSE ovino_doc_files
LIST_DIRECTORIES true RELATIVE ${OpenVINO_SOURCE_DIR}
"${OpenVINO_SOURCE_DIR}/docs/*.md"
"${OpenVINO_SOURCE_DIR}/docs/*.png"
"${OpenVINO_SOURCE_DIR}/docs/*.gif"
"${OpenVINO_SOURCE_DIR}/docs/*.jpg"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.md"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.png"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.gif"
"${OpenVINO_SOURCE_DIR}/inference-engine/*.jpg"
"${OpenVINO_SOURCE_DIR}/src/*.md"
"${OpenVINO_SOURCE_DIR}/src/*.png"
"${OpenVINO_SOURCE_DIR}/src/*.gif"
"${OpenVINO_SOURCE_DIR}/src/*.jpg"
"${OpenVINO_SOURCE_DIR}/samples/*.md"
"${OpenVINO_SOURCE_DIR}/samples/*.png"
"${OpenVINO_SOURCE_DIR}/samples/*.gif"
"${OpenVINO_SOURCE_DIR}/samples/*.jpg"
"${OpenVINO_SOURCE_DIR}/tools/*.md"
"${OpenVINO_SOURCE_DIR}/tools/*.png"
"${OpenVINO_SOURCE_DIR}/tools/*.gif"
"${OpenVINO_SOURCE_DIR}/tools/*.jpg")
foreach(source_file ${ovino_doc_files})
list(APPEND commands COMMAND ${CMAKE_COMMAND} -E copy
"${OpenVINO_SOURCE_DIR}/${source_file}" "${DOCS_BUILD_DIR}/openvino/${source_file}")
endforeach()
# omz doc files # omz doc files
if(EXISTS "${OMZ_DOCS_DIR}") if(EXISTS "${OMZ_DOCS_DIR}")
get_filename_component(OMZ_DOCS_DIR "${OMZ_DOCS_DIR}" ABSOLUTE) get_filename_component(OMZ_DOCS_DIR "${OMZ_DOCS_DIR}" ABSOLUTE)
list(APPEND commands
file(GLOB_RECURSE omz_doc_files COMMAND ${PYTHON_EXECUTABLE} ${OMZ_DOCS_DIR}/ci/prepare-documentation.py ${CMAKE_BINARY_DIR}/open_model_zoo)
LIST_DIRECTORIES true RELATIVE ${OMZ_DOCS_DIR} list(APPEND commands COMMAND ${PYTHON_EXECUTABLE} ${DOXY_MD_FILTER}
"${OMZ_DOCS_DIR}/*.md" --input_dir=${CMAKE_BINARY_DIR}/open_model_zoo
"${OMZ_DOCS_DIR}/*.png" --output_dir=${DOCS_BUILD_DIR}/open_model_zoo)
"${OMZ_DOCS_DIR}/*.gif"
"${OMZ_DOCS_DIR}/*.jpg")
foreach(source_file ${omz_doc_files})
list(APPEND commands COMMAND ${CMAKE_COMMAND} -E copy
"${OMZ_DOCS_DIR}/${source_file}" "${DOCS_BUILD_DIR}/omz/${source_file}")
endforeach()
configure_file("${OMZ_DOCS_DIR}/omz_docs.xml" "${DOCS_BUILD_DIR}/omz_docs.xml" @ONLY)
endif() endif()
# workbench doc files # workbench doc files
if(EXISTS "${WORKBENCH_DOCS_DIR}") if(EXISTS "${WORKBENCH_DOCS_DIR}")
get_filename_component(WORKBENCH_DOCS_DIR "${WORKBENCH_DOCS_DIR}" ABSOLUTE) get_filename_component(WORKBENCH_DOCS_DIR "${WORKBENCH_DOCS_DIR}" ABSOLUTE)
file(GLOB_RECURSE workbench_doc_files list(APPEND commands COMMAND ${PYTHON_EXECUTABLE} ${DOXY_MD_FILTER}
LIST_DIRECTORIES true RELATIVE ${WORKBENCH_DOCS_DIR} --input_dir=${WORKBENCH_DOCS_DIR}
"${WORKBENCH_DOCS_DIR}/*.md" --output_dir=${DOCS_BUILD_DIR}/workbench)
"${WORKBENCH_DOCS_DIR}/*.png"
"${WORKBENCH_DOCS_DIR}/*.gif"
"${WORKBENCH_DOCS_DIR}/*.jpg")
foreach(source_file ${workbench_doc_files})
list(APPEND commands COMMAND ${CMAKE_COMMAND} -E copy
"${WORKBENCH_DOCS_DIR}/${source_file}" "${DOCS_BUILD_DIR}/workbench/${source_file}")
endforeach()
configure_file("${WORKBENCH_DOCS_DIR}/docs/Workbench_DG/workbench_docs.xml" "${DOCS_BUILD_DIR}/workbench_docs.xml" @ONLY)
endif() endif()
# pot doc files # pot doc files
if(EXISTS "${POT_DOCS_DIR}") if(EXISTS "${POT_DOCS_DIR}")
get_filename_component(POT_DOCS_DIR "${POT_DOCS_DIR}" ABSOLUTE) get_filename_component(POT_DOCS_DIR "${POT_DOCS_DIR}" ABSOLUTE)
file(GLOB_RECURSE pot_doc_files list(APPEND commands COMMAND ${PYTHON_EXECUTABLE} ${DOXY_MD_FILTER}
LIST_DIRECTORIES true RELATIVE ${POT_DOCS_DIR} --input_dir=${POT_DOCS_DIR}
"${POT_DOCS_DIR}/*.md" --output_dir=${DOCS_BUILD_DIR}/pot)
"${POT_DOCS_DIR}/*.png" endif()
"${POT_DOCS_DIR}/*.gif"
"${POT_DOCS_DIR}/*.jpg")
foreach(source_file ${pot_doc_files}) # ovms doc files
list(APPEND commands COMMAND ${CMAKE_COMMAND} -E copy if(EXISTS "${OVMS_DOCS_DIR}")
"${POT_DOCS_DIR}/${source_file}" "${DOCS_BUILD_DIR}/pot/${source_file}") get_filename_component(OVMS_DOCS_DIR "${OVMS_DOCS_DIR}" ABSOLUTE)
endforeach()
configure_file("${POT_DOCS_DIR}/docs/pot_docs.xml" "${DOCS_BUILD_DIR}/pot_docs.xml" @ONLY) list(APPEND commands COMMAND ${PYTHON_EXECUTABLE} ${DOXY_MD_FILTER}
--input_dir=${OVMS_DOCS_DIR}
--output_dir=${DOCS_BUILD_DIR}/ovms)
endif() endif()
# gst doc files # gst doc files
if(EXISTS "${GST_DOCS_DIR}") if(EXISTS "${GST_DOCS_DIR}")
get_filename_component(GST_DOCS_DIR "${GST_DOCS_DIR}" ABSOLUTE) get_filename_component(GST_DOCS_DIR "${GST_DOCS_DIR}" ABSOLUTE)
list(APPEND commands COMMAND ${PYTHON_EXECUTABLE} ${DOXY_MD_FILTER}
file(GLOB_RECURSE gst_doc_files --input_dir=${GST_DOCS_DIR}
LIST_DIRECTORIES true RELATIVE ${GST_DOCS_DIR} --output_dir=${DOCS_BUILD_DIR}/gst)
"${GST_DOCS_DIR}/*.md"
"${GST_DOCS_DIR}/*.png"
"${GST_DOCS_DIR}/*.gif"
"${GST_DOCS_DIR}/*.jpg")
foreach(source_file ${gst_doc_files})
list(APPEND commands COMMAND ${CMAKE_COMMAND} -E copy
"${GST_DOCS_DIR}/${source_file}" "${DOCS_BUILD_DIR}/gst/${source_file}")
endforeach()
endif() endif()
add_custom_target(preprocess_docs
COMMENT "Preprocess documentation"
VERBATIM)
# Preprocess docs
add_custom_command(TARGET preprocess_docs add_custom_command(TARGET preprocess_docs
PRE_BUILD
${commands}
COMMAND ${PYTHON_EXECUTABLE} ${DOXY_LAYOUT_SCRIPT} --openvino ${OPENVINO_LAYOUT_BUILD}
COMMAND ${PYTHON_EXECUTABLE} ${DOXY_MD_FILTER} ${DOCS_BUILD_DIR}
COMMENT "Pre-process markdown and image links")
# IE dev guide and C++ API
add_custom_target(ie_docs
DEPENDS ngraph_cpp_api preprocess_docs
COMMAND ${CMAKE_COMMAND} -E copy_directory ${ASSETS_DIR} ${IE_OUTPUT}/assets
COMMAND ${DOXYGEN_EXECUTABLE} ${IE_CONFIG_BUILD}
WORKING_DIRECTORY ${DOCS_BUILD_DIR}
VERBATIM)
# Plugin API
add_custom_target(plugin_api
DEPENDS ngraph_cpp_api ie_docs
COMMAND ${CMAKE_COMMAND} -E copy_directory ${ASSETS_DIR} ${PLUGIN_OUTPUT}/assets
COMMAND ${DOXYGEN_EXECUTABLE} ${PLUGIN_CONFIG_BUILD}
WORKING_DIRECTORY ${DOCS_BUILD_DIR}
COMMENT "Generating Plugin API Reference"
VERBATIM)
# Umbrella OpenVINO target
add_custom_target(openvino_docs
DEPENDS ngraph_cpp_api ngraph_py_api c_api py_api ie_docs plugin_api
COMMENT "Generating OpenVINO documentation"
VERBATIM)
set_target_properties(openvino_docs ie_docs c_api py_api preprocess_docs plugin_api
ngraph_py_api ngraph_cpp_api
PROPERTIES FOLDER docs)
add_custom_command(TARGET openvino_docs
POST_BUILD POST_BUILD
COMMAND ${PYTHON_EXECUTABLE} ${DOXY_LOG_SCRIPT} --log "${DOCS_BUILD_DIR}/ie_docs.log" ${commands}
--include_omz $<BOOL:${OMZ_DOCS_DIR}> WORKING_DIRECTORY ${DOCS_BUILD_DIR}
--include_wb $<BOOL:${WORKBENCH_DOCS_DIR}> COMMENT "Preprocess documentation"
--include_pot $<BOOL:${POT_DOCS_DIR}>
--include_gst $<BOOL:${GST_DOCS_DIR}>
COMMENT "Parse doxygen log to find errors."
VERBATIM) VERBATIM)
# added linkcheker add_custom_target(doxygen_xml
DEPENDS preprocess_docs
COMMAND ${PYTHON_EXECUTABLE} ${REMOVE_XML_SCRIPT} ${XML_OUTPUT}
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_BUILD}
WORKING_DIRECTORY ${DOCS_BUILD_DIR}
COMMENT "Generate doxygen XML output"
VERBATIM)
# Post-process docs
add_custom_command(TARGET doxygen_xml
POST_BUILD
COMMAND ${PYTHON_EXECUTABLE} ${PREPARE_XML_SCRIPT} ${XML_OUTPUT}
COMMAND ${CMAKE_COMMAND} -E copy_directory ${DOXYREST_IN} ${DOXYREST_OUT}
COMMAND ${DOXYREST_EXECUTABLE} -c ${DOXYREST_CONFIG_OUT}
COMMAND ${PYTHON_EXECUTABLE} ${COPY_IMAGES_SCRIPT} ${XML_OUTPUT} ${RST_OUTPUT}
COMMAND ${PYTHON_EXECUTABLE} ${DOXYGEN_MAPPING_SCRIPT} ${XML_OUTPUT} ${DOCS_BUILD_DIR} ${OpenVINO_SOURCE_DIR}/../
COMMAND ${CMAKE_COMMAND} -E copy ${SPHINX_INDEX_IN} ${SPHINX_INDEX_OUT}
COMMAND ${CMAKE_COMMAND} -E copy_directory ${API_DOCS_IN} ${API_DOCS_OUT}
COMMAND ${CMAKE_COMMAND} -E copy_directory ${DOXYREST_IN} ${DOXYREST_OUT}
COMMAND ${CMAKE_COMMAND} -E copy_directory ${DOXYREST_SPHINX_IN} ${DOXYREST_SPHINX_OUT}
COMMAND ${CMAKE_COMMAND} -E copy_directory ${SPHINX_STATIC_IN} ${SPHINX_STATIC_OUT}
COMMENT "Prepare xml"
VERBATIM)
add_custom_target(sphinx_docs
DEPENDS doxygen_xml
COMMAND sphinx-build -b html ${RST_OUTPUT} ${SPHINX_OUTPUT}
WORKING_DIRECTORY ${RST_OUTPUT}
VERBATIM)
set_target_properties(doxygen_xml sphinx_docs
PROPERTIES FOLDER docs)
if(EXISTS "${LINKCHECKER_PY}")
add_custom_target(docs_check
COMMAND "${LINKCHECKER_PY}" -v "${DOCS_BUILD_DIR}/html/"
COMMENT "Check links in generated documentation"
WORKING_DIRECTORY "${DOCS_BUILD_DIR}"
VERBATIM)
set_target_properties(docs_check PROPERTIES FOLDER docs)
endif()
find_program(browser NAMES xdg-open) find_program(browser NAMES xdg-open)
if(browser) if(browser)
add_custom_target(ie_docs_open add_custom_target(ie_docs_open
COMMAND ${browser} "${OpenVINO_SOURCE_DIR}/docs/html/index.html" COMMAND ${browser} "${SPHINX_OUTPUT}/index.html"
DEPENDS ie_docs DEPENDS sphinx_docs
COMMENT "Open OpenVINO documentation" COMMENT "Open OpenVINO documentation"
VERBATIM) VERBATIM)
set_target_properties(ie_docs_open PROPERTIES FOLDER docs) set_target_properties(ie_docs_open PROPERTIES FOLDER docs)

View File

@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If # entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used. # left blank the current directory will be used.
OUTPUT_DIRECTORY = "@OUTPUT_DIRECTORY@" OUTPUT_DIRECTORY = "@DOCS_BUILD_DIR@"
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and # directories (in 2 levels) under the output directory of each output format and
@ -262,6 +262,8 @@ TAB_SIZE = 4
# a double escape (\\{ and \\}) # a double escape (\\{ and \\})
ALIASES = "ref_ie{1}=@ref InferenceEngine::\1 \"\1\"" ALIASES = "ref_ie{1}=@ref InferenceEngine::\1 \"\1\""
ALIASES += sphinxdirective="\n\xmlonly<sphinxdirective>"
ALIASES += endsphinxdirective="</sphinxdirective>\endxmlonly"
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For # only. Doxygen will then generate output that is more tailored for C. For
@ -317,7 +319,7 @@ OPTIMIZE_OUTPUT_SLICE = NO
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen. # the files are not read by doxygen.
EXTENSION_MAPPING = EXTENSION_MAPPING = pyx=Python
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable # according to the Markdown format, which allows for more readable
@ -461,7 +463,7 @@ LOOKUP_CACHE_SIZE = 0
# normally produced when WARNINGS is set to YES. # normally produced when WARNINGS is set to YES.
# The default value is: NO. # The default value is: NO.
EXTRACT_ALL = NO EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation. # be included in the documentation.
@ -556,7 +558,7 @@ INTERNAL_DOCS = NO
# (including Cygwin) ands Mac users are advised to set this option to NO. # (including Cygwin) ands Mac users are advised to set this option to NO.
# The default value is: system dependent. # The default value is: system dependent.
CASE_SENSE_NAMES = YES CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the # their full class and namespace scopes in the documentation. If set to YES, the
@ -811,7 +813,7 @@ WARN_FORMAT = "$file:$line: $text"
# messages should be written. If left blank the output is written to standard # messages should be written. If left blank the output is written to standard
# error (stderr). # error (stderr).
WARN_LOGFILE = "@DOCS_BUILD_DIR@/ie_docs.log" WARN_LOGFILE = "@DOCS_BUILD_DIR@/doxygen.log"
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# Configuration options related to the input files # Configuration options related to the input files
@ -823,8 +825,27 @@ WARN_LOGFILE = "@DOCS_BUILD_DIR@/ie_docs.log"
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = "@DOCS_BUILD_DIR@" \ INPUT = "@MARKDOWN_INPUT@" \
"@OV_INFERENCE_DIR@/include" "@OpenVINO_SOURCE_DIR@/src/frontends/common/include" \
"@OpenVINO_SOURCE_DIR@/src/common/conditional_compilation/include" \
"@OpenVINO_SOURCE_DIR@/src/common/itt/include" \
"@OpenVINO_SOURCE_DIR@/src/common/legacy/include" \
"@OpenVINO_SOURCE_DIR@/src/common/legacy/include" \
"@OpenVINO_SOURCE_DIR@/src/common/low_precision_transformations/include" \
"@OpenVINO_SOURCE_DIR@/src/common/low_precision_transformations/include" \
"@OpenVINO_SOURCE_DIR@/src/common/offline_transformations/include" \
"@OpenVINO_SOURCE_DIR@/src/common/preprocessing/include" \
"@OpenVINO_SOURCE_DIR@/src/common/snippets/include" \
"@OpenVINO_SOURCE_DIR@/src/common/transformations/include" \
"@OpenVINO_SOURCE_DIR@/src/common/util/include" \
"@OpenVINO_SOURCE_DIR@/src/core/include" \
"@OpenVINO_SOURCE_DIR@/src/core/builder/include" \
"@OpenVINO_SOURCE_DIR@/src/core/reference/include" \
"@OpenVINO_SOURCE_DIR@/src/core/shape_inference/include" \
"@OpenVINO_SOURCE_DIR@/src/frontends/common/include" \
"@OpenVINO_SOURCE_DIR@/src/inference/dev_api" \
"@OpenVINO_SOURCE_DIR@/src/inference/include"
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@ -855,7 +876,8 @@ FILE_PATTERNS = *.md \
*.cpp \ *.cpp \
*.c \ *.c \
*.hpp \ *.hpp \
*.h *.h \
*.c++ \
# The RECURSIVE tag can be used to specify whether or not subdirectories should # The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well. # be searched for input files as well.
@ -891,7 +913,11 @@ EXCLUDE_PATTERNS = */temp/* \
*/tests/* \ */tests/* \
*/openvx/* \ */openvx/* \
*/thirdparty/* \ */thirdparty/* \
*/IE_PLUGIN_DG/* "@DOXYREST_OUT@" \
"@XML_OUTPUT@" \
"@RST_OUTPUT@" \
"@SPHINX_OUTPUT@" \
*/build/open_model_zoo/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the # (namespaces, classes, functions, etc.) that should be excluded from the
@ -953,20 +979,61 @@ EXCLUDE_SYMBOLS = InferenceEngine::details \
TBB_PREVIEW_NUMA_SUPPORT \ TBB_PREVIEW_NUMA_SUPPORT \
TBB_PREVIEW_TASK_ARENA_CONSTRAINTS_EXTENSION \ TBB_PREVIEW_TASK_ARENA_CONSTRAINTS_EXTENSION \
_TBB_REDUCE_FUNC \ _TBB_REDUCE_FUNC \
IE_THREAD_* IE_THREAD_* \
INFERENCE_ENGINE_C_API_EXTERN \
INFERENCE_ENGINE_C_API \
INFERENCE_ENGINE_C_API_CALLBACK \
IE_NODISCARD \
InferenceEngine::details \
ie_api::BlobBuffer \
*impl* \
*device_name* \
*num_requests* \
*exec_net* \
*c_config* \
*ie_core_impl* \
*plugin_impl* \
*extension_str* \
*buffer* \
*__cinit__* \
ngraph::utils \
ie_core_version \
ie_core_versions \
ie_available_devices \
ie_core_versions \
input_shapes \
colorformat_e \
layout_e \
dimensions \
ie_param_config \
struct_desc \
ie_param \
ie_complete_call_back \
IEStatusCode \
input_shape \
struct_desc
# The EXAMPLE_PATH tag can be used to specify one or more files or directories # The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include # that contain example code fragments that are included (see the \include
# command). # command).
EXAMPLE_PATH = "@CMAKE_CURRENT_SOURCE_DIR@" EXAMPLE_PATH = "@CMAKE_CURRENT_SOURCE_DIR@" \
"@CMAKE_CURRENT_SOURCE_DIR@/template_plugin/src" \
"@CMAKE_CURRENT_SOURCE_DIR@/template_plugin/include" \
"@CMAKE_CURRENT_SOURCE_DIR@/template_plugin/src/CMakeLists.txt" \
"@CMAKE_CURRENT_SOURCE_DIR@/template_plugin/tests/functional/CMakeLists.txt" \
"@CMAKE_CURRENT_SOURCE_DIR@/template_plugin/tests/functional/transformations" \
"@CMAKE_CURRENT_SOURCE_DIR@/template_plugin/tests/functional/shared_tests_instances/" \
"@CMAKE_CURRENT_SOURCE_DIR@/snippets"
"@IE_SOURCE_DIR@/tests/functional/plugin/shared/include"
# If the value of the EXAMPLE_PATH tag contains directories, you can use the # If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all # *.h) to filter out the source-files in the directories. If left blank all
# files are included. # files are included.
EXAMPLE_PATTERNS = EXAMPLE_PATTERNS = *.cpp \
*.hpp
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands # searched for input files to be used with the \include or \dontinclude commands
@ -979,7 +1046,7 @@ EXAMPLE_RECURSIVE = YES
# that contain images that are to be included in the documentation (see the # that contain images that are to be included in the documentation (see the
# \image command). # \image command).
IMAGE_PATH = . IMAGE_PATH = "@DOCS_BUILD_DIR@"
# The INPUT_FILTER tag can be used to specify a program that doxygen should # The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program # invoke to filter for each input file. Doxygen will invoke the filter program
@ -1185,7 +1252,7 @@ IGNORE_PREFIX =
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES. # The default value is: YES.
GENERATE_HTML = YES GENERATE_HTML = NO
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@ -1193,7 +1260,7 @@ GENERATE_HTML = YES
# The default directory is: html. # The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = @OUTPUT_DIRECTORY@ HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp). # generated HTML page (for example: .htm, .php, .asp).
@ -1220,7 +1287,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation. # of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER = @HEADER_BUILD@ HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard # generated HTML page. If the tag is left blank doxygen will generate a standard
@ -1230,7 +1297,7 @@ HTML_HEADER = @HEADER_BUILD@
# that doxygen normally uses. # that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER = @FOOTER_BUILD@ HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of # sheet that is used by each HTML page. It can be used to fine-tune the look of
@ -2059,7 +2126,7 @@ MAN_LINKS = NO
# captures the structure of the code including all documentation. # captures the structure of the code including all documentation.
# The default value is: NO. # The default value is: NO.
GENERATE_XML = NO GENERATE_XML = YES
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@ -2067,7 +2134,7 @@ GENERATE_XML = NO
# The default directory is: xml. # The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES. # This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml XML_OUTPUT = "@XML_OUTPUT@"
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program # If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to # listings (including syntax highlighting and cross-referencing information) to
@ -2076,7 +2143,7 @@ XML_OUTPUT = xml
# The default value is: YES. # The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES. # This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES XML_PROGRAMLISTING = NO
# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include # If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
# namespace members in file scope as well, matching the HTML output. # namespace members in file scope as well, matching the HTML output.
@ -2235,7 +2302,45 @@ PREDEFINED = "INFERENCE_ENGINE_API_CLASS=" \
"OPENVINO_PLUGIN_API=" \ "OPENVINO_PLUGIN_API=" \
"IE_SUPPRESS_DEPRECATED_END=" \ "IE_SUPPRESS_DEPRECATED_END=" \
"_IE_SUPPRESS_DEPRECATED_START_GCC=" \ "_IE_SUPPRESS_DEPRECATED_START_GCC=" \
"_IE_SUPPRESS_DEPRECATED_END_GCC=" "_IE_SUPPRESS_DEPRECATED_END_GCC=" \
"INFERENCE_ENGINE_NN_BUILDER_API_CLASS=" \
"INFERENCE_ENGINE_NN_BUILDER_DEPRECATED(x)=" \
"INFERENCE_ENGINE_INTERNAL(x)=" \
"INFERENCE_ENGINE_INTERNAL_CNNLAYER_CLASS(x)=" \
"__attribute__(x)=" \
"__VA_ARGS__=" \
"INFERENCE_ENGINE_C_API_EXTERN=" \
"INFERENCE_ENGINE_C_API_CALLBACK=" \
"INFERENCE_ENGINE_C_API=" \
"IE_NODISCARD=" \
"__cdecl=" \
"__declspec(x)=" \
"_WIN32" \
"INFERENCE_ENGINE_API=" \
"INFERENCE_ENGINE_API_CPP=" \
"INFERENCE_ENGINE_API_CLASS=" \
"INFERENCE_ENGINE_DEPRECATED=" \
"IMPLEMENT_OPENVINO_API" \
"TRANSFORMATIONS_API=" \
"NGRAPH_HELPER_DLL_EXPORT=" \
"NGRAPH_HELPER_DLL_IMPORT=" \
"IE_SUPPRESS_DEPRECATED_START=" \
"IE_SUPPRESS_DEPRECATED_END=" \
"_IE_SUPPRESS_DEPRECATED_START_MSVC=" \
"_IE_SUPPRESS_DEPRECATED_END_MSVC=" \
"_IE_SUPPRESS_DEPRECATED_START_GCC=" \
"_IE_SUPPRESS_DEPRECATED_END_GCC=" \
"IE_THREAD=IE_THREAD_TBB" \
"NGRAPH_RTTI_DECLARATION=" \
"__attribute__(x)=" \
"__VA_ARGS__=" \
"INFERENCE_ENGINE_C_API_EXTERN=" \
"INFERENCE_ENGINE_C_API=" \
"IE_NODISCARD=" \
"__cdecl=" \
"__declspec(x)=" \
"__GNUC__=" \
"_WIN32"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The # tag can be used to specify a list of macro names that should be expanded. The

View File

@ -5,28 +5,22 @@ TensorFlow*, Caffe*, MXNet*, Kaldi* and ONNX* file format. The list of supported
each of the supported frameworks. To see the operations supported by your framework, refer to each of the supported frameworks. To see the operations supported by your framework, refer to
[Supported Framework Layers](../MO_DG/prepare_model/Supported_Frameworks_Layers.md). [Supported Framework Layers](../MO_DG/prepare_model/Supported_Frameworks_Layers.md).
Custom operations are operations that are not included in the list of known operations. If your model contains any Custom operations, that is those not included in the list, are not recognized by Model Optimizer out-of-the-box. Therefore, creating Intermediate Representation (IR) for a model using them requires additional steps. This guide illustrates the workflow for running inference on topologies featuring custom operations, allowing you to plug in your own implementation for existing or completely new operations.
operation that is not in the list of known operations, the Model Optimizer is not able to generate an Intermediate
Representation (IR) for this model.
This guide illustrates the workflow for running inference on topologies featuring custom operations, allowing you to > **NOTE**: *Layer* is a legacy term for *operation* which came from Caffe\* framework. Currently it is not used.
plug in your own implementation for existing or completely new operation.
> **NOTE:** *Layer* — The legacy term for an *operation* which came from Caffe\* framework. Currently it is not used.
> Refer to the [Deep Learning Network Intermediate Representation and Operation Sets in OpenVINO™](../MO_DG/IR_and_opsets.md) > Refer to the [Deep Learning Network Intermediate Representation and Operation Sets in OpenVINO™](../MO_DG/IR_and_opsets.md)
> for more information on the topic. > for more information on the topic.
## Terms Used in This Guide ## Terms Used in This Guide
- *Intermediate Representation (IR)* — Neural Network used only by the Inference Engine in OpenVINO abstracting the - *Intermediate Representation (IR)* — OpenVINO's Neural Network format used by Inference Engine. It abstracts different frameworks and describs model topology, operations parameters, and weights.
different frameworks and describing the model topology, operations parameters and weights.
- *Operation*The abstract concept of a math function that is selected for a specific purpose. Operations supported by - *Operation*an abstract concept of a math function selected for a specific purpose. Operations supported by
OpenVINO™ are listed in the supported operation set provided in the [Available Operations Sets](../ops/opset.md). OpenVINO™ are listed in the supported operation set provided in the [Available Operations Sets](../ops/opset.md).
Examples of the operations are: [ReLU](../ops/activation/ReLU_1.md), [Convolution](../ops/convolution/Convolution_1.md), Examples of the operations are: [ReLU](../ops/activation/ReLU_1.md), [Convolution](../ops/convolution/Convolution_1.md),
[Add](../ops/arithmetic/Add_1.md), etc. [Add](../ops/arithmetic/Add_1.md), etc.
- *Kernel* — The implementation of a operation function in the OpenVINO™ plugin, in this case, the math programmed (in - *Kernel* — The implementation of an operation function in the OpenVINO™ plugin, in this case, the math programmed (in
C++ and OpenCL) to perform the operation for a target hardware (CPU or GPU). C++ and OpenCL) to perform the operation for a target hardware (CPU or GPU).
- *Inference Engine Extension* — Device-specific module implementing custom operations (a set of kernels). - *Inference Engine Extension* — Device-specific module implementing custom operations (a set of kernels).
@ -44,7 +38,7 @@ plugins to support inference of this operation using a particular target hardwar
To see the operations that are supported by each device plugin for the Inference Engine, refer to the To see the operations that are supported by each device plugin for the Inference Engine, refer to the
[Supported Devices](../IE_DG/supported_plugins/Supported_Devices.md). [Supported Devices](../IE_DG/supported_plugins/Supported_Devices.md).
> **NOTE:** If a device doesn't support a particular operation, an alternative to creating a new operation is to target > **NOTE**: If a device doesn't support a particular operation, an alternative to creating a new operation is to target
> an additional device using the HETERO plugin. The [Heterogeneous Plugin](../IE_DG/supported_plugins/HETERO.md) may be > an additional device using the HETERO plugin. The [Heterogeneous Plugin](../IE_DG/supported_plugins/HETERO.md) may be
> used to run an inference model on multiple devices allowing the unsupported operations on one device to "fallback" to > used to run an inference model on multiple devices allowing the unsupported operations on one device to "fallback" to
> run on another device (e.g., CPU) that does support those operations. > run on another device (e.g., CPU) that does support those operations.
@ -56,18 +50,18 @@ Model Optimizer model conversion pipeline is described in detail in "Model Conve
Model Optimizer provides an extensions mechanism to support new operations and implement custom model transformations to generate optimized IR. This mechanism is described in the "Model Optimizer Extensions" section of Model Optimizer provides an extensions mechanism to support new operations and implement custom model transformations to generate optimized IR. This mechanism is described in the "Model Optimizer Extensions" section of
[Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md). [Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md).
Two types of the Model Optimizer extensions should be implemented to support custom operations, at a minimum: Two types of Model Optimizer extensions should be implemented to support custom operations, at a minimum:
1. Operation class for a new operation. This class stores information about the operation, its attributes, shape inference function, attributes to be saved to an IR and some others internally used attributes. Refer to the "Model Optimizer Operation" section of [Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md) for detailed instructions on how to implement it. 1. Operation class for a new operation. This class stores information about the operation, its attributes, shape inference function, attributes to be saved to an IR and some others internally used attributes. Refer to the "Model Optimizer Operation" section of [Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md) for detailed instructions on how to implement it.
2. Operation attributes extractor. The extractor is responsible for parsing framework-specific representation of the 2. Operation attributes extractor. The extractor is responsible for parsing framework-specific representation of the
operation and uses corresponding operation class to update graph node attributes with necessary attributes of the operation and uses corresponding operation class to update graph node attributes with necessary attributes of the
operation. Refer to the "Operation Extractor" section of operation. Refer to the "Operation Extractor" section of
[Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md) for detailed instructions on how to implement it. [Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md) for detailed instructions on how to implement it.
> **NOTE:** In some cases you may need to implement some transformation to support the operation. This topic is covered in the "Graph Transformation Extensions" section of [Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md). > **NOTE**: In some cases you may need to implement some transformation to support the operation. This topic is covered in the "Graph Transformation Extensions" section of [Model Optimizer Extensibility](../MO_DG/prepare_model/customize_model_optimizer/Customize_Model_Optimizer.md).
## Custom Operations Extensions for the Inference Engine ## Custom Operations Extensions for the Inference Engine
Inference Engine provides extensions mechanism to support new operations. This mechanism is described in [Inference Engine Extensibility Mechanism](../IE_DG/Extensibility_DG/Intro.md). Inference Engine provides an extension mechanism to support new operations. This mechanism is described in [Inference Engine Extensibility Mechanism](../IE_DG/Extensibility_DG/Intro.md).
Each device plugin includes a library of optimized implementations to execute known operations which must be extended to execute a custom operation. The custom operation extension is implemented according to the target device: Each device plugin includes a library of optimized implementations to execute known operations which must be extended to execute a custom operation. The custom operation extension is implemented according to the target device:
@ -127,19 +121,18 @@ As a result the TensorFlow\* frozen model file "wnet_20.pb" is generated.
### Convert the Frozen TensorFlow\* Model to Intermediate Representation ### Convert the Frozen TensorFlow\* Model to Intermediate Representation
Firstly, open the model in the TensorBoard or other TensorFlow* model visualization tool. The model supports dynamic Firstly, open the model in TensorBoard or other TensorFlow* model visualization tool. The model supports dynamic
batch dimension because the value for the batch dimension is not hardcoded in the model. Model Optimizer need to set all batch dimension because the value for the batch dimension is not hardcoded in the model. Model Optimizer need to set all
dynamic dimensions to some specific value to create the IR, therefore specify the command line parameter `-b 1` to set dynamic dimensions to some specific value to create the IR, therefore specify the command line parameter `-b 1` to set
the batch dimension equal to 1. The actual batch size dimension can be changed at runtime using the Inference Engine API the batch dimension equal to 1. The actual batch size dimension can be changed at runtime using the Inference Engine API
described in the [Using Shape Inference](../IE_DG/ShapeInference.md). Also refer to described in the [Using Shape Inference](../IE_DG/ShapeInference.md). Also refer to the General Conversion Parameters section in [Converting a Model to Intermediate Representation (IR)](../MO_DG/prepare_model/convert_model/Converting_Model.md) and [Convert Your TensorFlow* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_TensorFlow.md)
[Converting a Model Using General Conversion Parameters](../MO_DG/prepare_model/convert_model/Converting_Model_General.md)
and [Convert Your TensorFlow* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_TensorFlow.md)
for more details and command line parameters used for the model conversion. for more details and command line parameters used for the model conversion.
```bash ```sh
mo --input_model <PATH_TO_MODEL>/wnet_20.pb -b 1 mo --input_model <PATH_TO_MODEL>/wnet_20.pb -b 1
``` ```
> **NOTE:** This conversion guide is applicable for the 2021.3 release of OpenVINO and that starting from 2021.4
> **NOTE**: This conversion guide is applicable for the 2021.3 release of OpenVINO and that starting from 2021.4
> the OpenVINO supports this model out of the box. > the OpenVINO supports this model out of the box.
Model Optimizer produces the following error: Model Optimizer produces the following error:
@ -221,7 +214,7 @@ following snippet provides two extractors: one for "IFFT2D", another one for "FF
@snippet FFT_ext.py fft_ext:extractor @snippet FFT_ext.py fft_ext:extractor
> **NOTE:** The graph is in inconsistent state after extracting node attributes because according to original operation > **NOTE**: The graph is in inconsistent state after extracting node attributes because according to original operation
> "IFFT2D" semantic it should have an input consuming a tensor of complex numbers, but the extractor instantiated an > "IFFT2D" semantic it should have an input consuming a tensor of complex numbers, but the extractor instantiated an
> operation "FFT" which expects a real tensor with specific layout. But the inconsistency will be resolved during > operation "FFT" which expects a real tensor with specific layout. But the inconsistency will be resolved during
> applying front phase transformations discussed below. > applying front phase transformations discussed below.
@ -239,7 +232,7 @@ information on how this type of transformation works. The code snippet should be
@snippet Complex.py complex:transformation @snippet Complex.py complex:transformation
> **NOTE:** The graph is in inconsistent state because the "ComplexAbs" operation consumes complex value tensor but > **NOTE**: The graph is in inconsistent state because the "ComplexAbs" operation consumes complex value tensor but
> "FFT" produces real value tensor. > "FFT" produces real value tensor.
Now lets implement a transformation which replace a "ComplexAbs" operation with a sub-graph of primitive operations Now lets implement a transformation which replace a "ComplexAbs" operation with a sub-graph of primitive operations
@ -257,15 +250,17 @@ The implementation should be saved to the file `mo_extensions/front/tf/ComplexAb
@snippet ComplexAbs.py complex_abs:transformation @snippet ComplexAbs.py complex_abs:transformation
Now it is possible to convert the model using the following command line: Now it is possible to convert the model using the following command line:
```bash ```sh
mo --input_model <PATH_TO_MODEL>/wnet_20.pb -b 1 --extensions mo_extensions/ mo --input_model <PATH_TO_MODEL>/wnet_20.pb -b 1 --extensions mo_extensions/
``` ```
@endsphinxdirective
The sub-graph corresponding to the originally non-supported one is depicted in the image below: The sub-graph corresponding to the originally non-supported one is depicted in the image below:
![Converted sub-graph](img/converted_subgraph.png) ![Converted sub-graph](img/converted_subgraph.png)
> **NOTE:** Model Optimizer performed conversion of the model from NHWC to NCHW layout that is why the dimension with > **NOTE**: Model Optimizer performed conversion of the model from NHWC to NCHW layout that is why the dimension with
> the value 2 moved to another position. > the value 2 moved to another position.
### Inference Engine Extension Implementation ### Inference Engine Extension Implementation
@ -279,7 +274,7 @@ file is the following:
@snippet ../template_extension/CMakeLists.txt cmake:extension @snippet ../template_extension/CMakeLists.txt cmake:extension
The CPU FFT kernel implementation uses OpenCV to perform the FFT that is why the extension library is linked with The CPU FFT kernel implementation uses OpenCV to perform the FFT that is why the extension library is linked with
"opencv_core" which comes with the OpenVINO. `opencv_core` which comes with the OpenVINO.
#### Custom nGraph Operation "FFT" Implementation #### Custom nGraph Operation "FFT" Implementation
The next step is to create the nGraph operation FFT. The header file "fft_op.hpp" has the following content: The next step is to create the nGraph operation FFT. The header file "fft_op.hpp" has the following content:
@ -287,7 +282,7 @@ The next step is to create the nGraph operation FFT. The header file "fft_op.hpp
@snippet ../template_extension/fft_op.hpp fft_op:header @snippet ../template_extension/fft_op.hpp fft_op:header
The operation has just one boolean attribute `inverse`. Implementation of the necessary nGraph operation functions are The operation has just one boolean attribute `inverse`. Implementation of the necessary nGraph operation functions are
in the "fft_op.cpp" file with the following content: in the `fft_op.cpp` file with the following content:
@snippet ../template_extension/fft_op.cpp fft_op:implementation @snippet ../template_extension/fft_op.cpp fft_op:implementation
@ -350,7 +345,7 @@ python3 mri_reconstruction_demo.py \
## Converting Models: ## Converting Models:
- [Convert Your Caffe* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_Caffe.md) - [Convert Your Caffe* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_Caffe.md)
- [Convert Your Kaldi* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_Kaldi.md)
- [Convert Your TensorFlow* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_TensorFlow.md) - [Convert Your TensorFlow* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_TensorFlow.md)
- [Convert Your MXNet* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_MxNet.md) - [Convert Your MXNet* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_MxNet.md)
- [Convert Your Kaldi* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_Kaldi.md)
- [Convert Your ONNX* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_ONNX.md) - [Convert Your ONNX* Model](../MO_DG/prepare_model/convert_model/Convert_Model_From_ONNX.md)

View File

@ -2,12 +2,9 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
#! [complex:transformation] #! [complex:transformation]
import logging as log
import numpy as np from openvino.tools.mo.front.common.replacement import FrontReplacementSubgraph
from openvino.tools.mo.graph.graph import Graph
from mo.front.common.replacement import FrontReplacementSubgraph
from mo.graph.graph import Graph
class Complex(FrontReplacementSubgraph): class Complex(FrontReplacementSubgraph):
@ -41,4 +38,3 @@ class Complex(FrontReplacementSubgraph):
# change the connection so now all consumers of "complex_node" get data from input node of strided slice nodes # change the connection so now all consumers of "complex_node" get data from input node of strided slice nodes
complex_node.out_port(0).get_connection().set_source(input_node_output_port) complex_node.out_port(0).get_connection().set_source(input_node_output_port)
#! [complex:transformation] #! [complex:transformation]

View File

@ -4,11 +4,11 @@
#! [complex_abs:transformation] #! [complex_abs:transformation]
import numpy as np import numpy as np
from extensions.ops.elementwise import Pow from openvino.tools.mo.ops.elementwise import Pow
from extensions.ops.ReduceOps import ReduceSum from openvino.tools.mo.ops.ReduceOps import ReduceSum
from mo.front.common.replacement import FrontReplacementOp from openvino.tools.mo.front.common.replacement import FrontReplacementOp
from mo.graph.graph import Graph, Node from openvino.tools.mo.graph.graph import Graph, Node
from mo.ops.const import Const from openvino.tools.mo.ops.const import Const
class ComplexAbs(FrontReplacementOp): class ComplexAbs(FrontReplacementOp):

View File

@ -3,8 +3,7 @@
# ! [fft_ext:extractor] # ! [fft_ext:extractor]
from ...ops.FFT import FFT from ...ops.FFT import FFT
from mo.front.extractor import FrontExtractorOp from openvino.tools.mo.front.extractor import FrontExtractorOp
from mo.utils.error import Error
class FFT2DFrontExtractor(FrontExtractorOp): class FFT2DFrontExtractor(FrontExtractorOp):

View File

@ -2,9 +2,9 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
#! [fft:operation] #! [fft:operation]
from mo.front.common.partial_infer.elemental import copy_shape_infer from openvino.tools.mo.front.common.partial_infer.elemental import copy_shape_infer
from mo.graph.graph import Node, Graph from openvino.tools.mo.graph.graph import Graph
from mo.ops.op import Op from openvino.tools.mo.ops.op import Op
class FFT(Op): class FFT(Op):

View File

@ -1,50 +1,57 @@
# Bfloat16 Inference {#openvino_docs_IE_DG_Bfloat16Inference} # Bfloat16 Inference {#openvino_docs_IE_DG_Bfloat16Inference}
## Disclaimer ## Bfloat16 Inference Usage (C++)
Inference Engine with the bfloat16 inference implemented on CPU must support the native `avx512_bf16` instruction and therefore the bfloat16 data format. @sphinxdirective
It is possible to use bfloat16 inference in simulation mode on platforms with Intel® Advanced Vector Extensions 512 (Intel® AVX-512), but it leads to significant performance degradation in comparison with FP32 or native `avx512_bf16` instruction usage. .. raw:: html
## Introduction <div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
### Disclaimer
Inference Engine with the bfloat16 inference implemented on CPU must support the native *avx512_bf16* instruction and therefore the bfloat16 data format. It is possible to use bfloat16 inference in simulation mode on platforms with Intel® Advanced Vector Extensions 512 (Intel® AVX-512), but it leads to significant performance degradation in comparison with FP32 or native *avx512_bf16* instruction usage.
### Introduction
Bfloat16 computations (referred to as BF16) is the Brain Floating-Point format with 16 bits. This is a truncated 16-bit version of the 32-bit IEEE 754 single-precision floating-point format FP32. BF16 preserves 8 exponent bits as FP32 but reduces precision of the sign and mantissa from 24 bits to 8 bits. Bfloat16 computations (referred to as BF16) is the Brain Floating-Point format with 16 bits. This is a truncated 16-bit version of the 32-bit IEEE 754 single-precision floating-point format FP32. BF16 preserves 8 exponent bits as FP32 but reduces precision of the sign and mantissa from 24 bits to 8 bits.
![bf16_format] ![bf16_format]
Preserving the exponent bits keeps BF16 to the same range as the FP32 (~1e-38 to ~3e38). This simplifies conversion between two data types: you just need to skip or flush to zero 16 low bits. Preserving the exponent bits keeps BF16 to the same range as the FP32 (~1e-38 to ~3e38). This simplifies conversion between two data types: you just need to skip or flush to zero 16 low bits. Truncated mantissa leads to occasionally less precision, but according to [investigations](https://cloud.google.com/blog/products/ai-machine-learning/bfloat16-the-secret-to-high-performance-on-cloud-tpus), neural networks are more sensitive to the size of the exponent than the mantissa size. Also, in lots of models, precision is needed close to zero but not so much at the maximum range. Another useful feature of BF16 is possibility to encode INT8 in BF16 without loss of accuracy, because INT8 range completely fits in BF16 mantissa field. It reduces data flow in conversion from INT8 input image data to BF16 directly without intermediate representation in FP32, or in combination of [INT8 inference](Int8Inference.md) and BF16 layers.
Truncated mantissa leads to occasionally less precision, but according to [investigations](https://cloud.google.com/blog/products/ai-machine-learning/bfloat16-the-secret-to-high-performance-on-cloud-tpus), neural networks are more sensitive to the size of the exponent than the mantissa size. Also, in lots of models, precision is needed close to zero but not so much at the maximum range.
Another useful feature of BF16 is possibility to encode INT8 in BF16 without loss of accuracy, because INT8 range completely fits in BF16 mantissa field. It reduces data flow in conversion from INT8 input image data to BF16 directly without intermediate representation in FP32, or in combination of [INT8 inference](Int8Inference.md) and BF16 layers.
See the ["BFLOAT16 Hardware Numerics Definition" white paper"](https://software.intel.com/sites/default/files/managed/40/8b/bf16-hardware-numerics-definition-white-paper.pdf) for more bfloat16 format details. See the [BFLOAT16 Hardware Numerics Definition white paper](https://software.intel.com/content/dam/develop/external/us/en/documents/bf16-hardware-numerics-definition-white-paper.pdf) for more bfloat16 format details.
There are two ways to check if CPU device can support bfloat16 computations for models: There are two ways to check if CPU device can support bfloat16 computations for models:
1. Query the instruction set via system `lscpu | grep avx512_bf16` or `cat /proc/cpuinfo | grep avx512_bf16`.
2. Use [Query API](InferenceEngine_QueryAPI.md) with `METRIC_KEY(OPTIMIZATION_CAPABILITIES)`, which should return `BF16` in the list of CPU optimization options: 1. Query the instruction set using one of these system commands:
* `lscpu | grep avx512_bf16`
* `cat /proc/cpuinfo | grep avx512_bf16`
2. Use the [Query API](InferenceEngine_QueryAPI.md) with `METRIC_KEY(OPTIMIZATION_CAPABILITIES)`, which should return `BF16` in the list of CPU optimization options:
@snippet snippets/Bfloat16Inference0.cpp part0 @snippet snippets/Bfloat16Inference0.cpp part0
Current Inference Engine solution for bfloat16 inference uses Intel® Math Kernel Library for Deep Neural Networks (Intel® MKL-DNN) and supports inference of the significant number of layers in BF16 computation mode. The current Inference Engine solution for bfloat16 inference uses the Intel® Math Kernel Library for Deep Neural Networks (Intel® MKL-DNN) and supports inference of the significant number of layers in BF16 computation mode.
## Lowering Inference Precision ### Lowering Inference Precision
Lowering precision to increase performance is [widely used](https://software.intel.com/content/www/us/en/develop/articles/lower-numerical-precision-deep-learning-inference-and-training.html) for optimization of inference. The bfloat16 data type usage on CPU for the first time opens the possibility of default optimization approach. Lowering precision to increase performance is [widely used](https://software.intel.com/content/www/us/en/develop/articles/lower-numerical-precision-deep-learning-inference-and-training.html) for optimization of inference. The bfloat16 data type usage on CPU for the first time opens the possibility of default optimization approach. The embodiment of this approach is to use the optimization capabilities of the current platform to achieve maximum performance while maintaining the accuracy of calculations within the acceptable range.
The embodiment of this approach is to use the optimization capabilities of the current platform to achieve maximum performance while maintaining the accuracy of calculations within the acceptable range.
Using Bfloat16 precision provides the following performance benefits:
Bfloat16 data usage provides the following benefits that increase performance:
1. Faster multiplication of two BF16 numbers because of shorter mantissa of bfloat16 data. 1. Faster multiplication of two BF16 numbers because of shorter mantissa of bfloat16 data.
2. No need to support denormals and handling exceptions as this is a performance optimization. 2. No need to support denormals and handling exceptions as this is a performance optimization.
3. Fast conversion of float32 to bfloat16 and vice versa. 3. Fast conversion of float32 to bfloat16 and vice versa.
4. Reduced size of data in memory, as a result, larger models fit in the same memory bounds. 4. Reduced size of data in memory, as a result, larger models fit in the same memory bounds.
5. Reduced amount of data that must be transferred, as a result, reduced data transition time. 5. Reduced amount of data that must be transferred, as a result, reduced data transition time.
For default optimization on CPU, source model is converted from FP32 or FP16 to BF16 and executed internally on platforms with native BF16 support. In this case, `KEY_ENFORCE_BF16` is set to `YES`. For default optimization on CPU, the source model is converted from FP32 or FP16 to BF16 and executed internally on platforms with native BF16 support. In this case, `KEY_ENFORCE_BF16` is set to `YES` in the `PluginConfigParams` for `GetConfig()`. The code below demonstrates how to check if the key is set:
The code below demonstrates how to check if the key is set:
@snippet snippets/Bfloat16Inference1.cpp part1 @snippet snippets/Bfloat16Inference1.cpp part1
To disable BF16 internal transformations, set the `KEY_ENFORCE_BF16` to `NO`. In this case, the model infers as is without modifications with precisions that were set on each layer edge. To disable BF16 internal transformations in C++ API, set the `KEY_ENFORCE_BF16` to `NO`. In this case, the model infers as is without modifications with precisions that were set on each layer edge.
@snippet snippets/Bfloat16Inference2.cpp part2 @snippet snippets/Bfloat16Inference2.cpp part2
To disable BF16 in C API: To disable BF16 in C API:
``` ```
@ -52,15 +59,16 @@ ie_config_t config = { "ENFORCE_BF16", "NO", NULL};
ie_core_load_network(core, network, device_name, &config, &exe_network); ie_core_load_network(core, network, device_name, &config, &exe_network);
``` ```
An exception with message `Platform doesn't support BF16 format` is formed in case of setting `KEY_ENFORCE_BF16` to `YES` on CPU without native BF16 support or BF16 simulation mode. An exception with the message `Platform doesn't support BF16 format` is formed in case of setting `KEY_ENFORCE_BF16` to `YES` on CPU without native BF16 support or BF16 simulation mode.
Low-Precision 8-bit integer models cannot be converted to BF16, even if bfloat16 optimization is set by default. Low-Precision 8-bit integer models cannot be converted to BF16, even if bfloat16 optimization is set by default.
## Bfloat16 Simulation Mode ### Bfloat16 Simulation Mode
Bfloat16 simulation mode is available on CPU and Intel® AVX-512 platforms that do not support the native `avx512_bf16` instruction. The simulator does not guarantee an adequate performance. Bfloat16 simulation mode is available on CPU and Intel® AVX-512 platforms that do not support the native `avx512_bf16` instruction. The simulator does not guarantee good performance. Note that the CPU must still support the AVX-512 extensions.
To enable Bfloat16 simulator:
* In [Benchmark App](../../samples/cpp/benchmark_app/README.md), add the `-enforcebf16=true` option To enable the simulation of Bfloat16:
* In the [Benchmark App](../../samples/cpp/benchmark_app/README.md), add the `-enforcebf16=true` option
* In C++ API, set `KEY_ENFORCE_BF16` to `YES` * In C++ API, set `KEY_ENFORCE_BF16` to `YES`
* In C API: * In C API:
``` ```
@ -68,25 +76,139 @@ ie_config_t config = { "ENFORCE_BF16", "YES", NULL};
ie_core_load_network(core, network, device_name, &config, &exe_network); ie_core_load_network(core, network, device_name, &config, &exe_network);
``` ```
## Performance Counters ### Performance Counters
Information about layer precision is stored in the performance counters that are available from the Inference Engine API. The layers have the following marks:
Information about layer precision is stored in the performance counters that are
available from the Inference Engine API. The layers have the following marks:
* Suffix `BF16` for layers that had bfloat16 data type input and were computed in BF16 precision * Suffix `BF16` for layers that had bfloat16 data type input and were computed in BF16 precision
* Suffix `FP32` for layers computed in 32-bit precision * Suffix `FP32` for layers computed in 32-bit precision
For example, the performance counters table for the Inception model can look as follows: For example, the performance counters table for the Inception model can look as follows:
``` ```
pool5 EXECUTED layerType: Pooling realTime: 143 cpu: 143 execType: jit_avx512_BF16 pool5 EXECUTED layerType: Pooling realTime: 143 cpu: 143 execType: jit_avx512_BF16
fc6 EXECUTED layerType: FullyConnected realTime: 47723 cpu: 47723 execType: jit_gemm_BF16 fc6 EXECUTED layerType: FullyConnected realTime: 47723 cpu: 47723 execType: jit_gemm_BF16
relu6 NOT_RUN layerType: ReLU realTime: 0 cpu: 0 execType: undef relu6 NOT_RUN layerType: ReLU realTime: 0 cpu: 0 execType: undef
fc7 EXECUTED layerType: FullyConnected realTime: 7558 cpu: 7558 execType: jit_gemm_BF16 fc7 EXECUTED layerType: FullyConnected realTime: 7558 cpu: 7558 execType: jit_gemm_BF16
relu7 NOT_RUN layerType: ReLU realTime: 0 cpu: 0 execType: undef relu7 NOT_RUN layerType: ReLU realTime: 0 cpu: 0 execType: undef
fc8 EXECUTED layerType: FullyConnected realTime: 2193 cpu: 2193 execType: jit_gemm_BF16 fc8 EXECUTED layerType: FullyConnected realTime: 2193 cpu: 2193 execType: jit_gemm_BF16
prob EXECUTED layerType: SoftMax realTime: 68 cpu: 68 execType: jit_avx512_FP32 prob EXECUTED layerType: SoftMax realTime: 68 cpu: 68 execType: jit_avx512_FP32
``` ```
The `execType` column of the table includes inference primitives with specific suffixes. The **execType** column of the table includes inference primitives with specific suffixes.
## Bfloat16 Inference Usage (Python)
@sphinxdirective
.. raw:: html
<div id="switcher-python" class="switcher-anchor">Python</div>
@endsphinxdirective
### Disclaimer
Inference Engine with the bfloat16 inference implemented on CPU must support the native *avx512_bf16* instruction and therefore the bfloat16 data format. It is possible to use bfloat16 inference in simulation mode on platforms with Intel® Advanced Vector Extensions 512 (Intel® AVX-512), but it leads to significant performance degradation in comparison with FP32 or native *avx512_bf16* instruction usage.
### Introduction
Bfloat16 computations (referred to as BF16) is the Brain Floating-Point format with 16 bits. This is a truncated 16-bit version of the 32-bit IEEE 754 single-precision floating-point format FP32. BF16 preserves 8 exponent bits as FP32 but reduces precision of the sign and mantissa from 24 bits to 8 bits.
![bf16_format]
Preserving the exponent bits keeps BF16 to the same range as the FP32 (~1e-38 to ~3e38). This simplifies conversion between two data types: you just need to skip or flush to zero 16 low bits. Truncated mantissa leads to occasionally less precision, but according to investigations, neural networks are more sensitive to the size of the exponent than the mantissa size. Also, in lots of models, precision is needed close to zero but not so much at the maximum range. Another useful feature of BF16 is possibility to encode INT8 in BF16 without loss of accuracy, because INT8 range completely fits in BF16 mantissa field. It reduces data flow in conversion from INT8 input image data to BF16 directly without intermediate representation in FP32, or in combination of [INT8 inference](Int8Inference.md) and BF16 layers.
See the [BFLOAT16 Hardware Numerics Definition white paper](https://software.intel.com/content/dam/develop/external/us/en/documents/bf16-hardware-numerics-definition-white-paper.pdf) for more bfloat16 format details.
There are two ways to check if CPU device can support bfloat16 computations for models:
1. Query the instruction set using one of these system commands:
* `lscpu | grep avx512_bf16`
* `cat /proc/cpuinfo | grep avx512_bf16`
2. Use the Query API with METRIC_KEY(OPTIMIZATION_CAPABILITIES), which should return BF16 in the list of CPU optimization options:
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(path_to_xml_file)
cpu_caps = ie.get_metric(metric_name="OPTIMIZATION_CAPABILITIES", device_name="CPU")
```
The current Inference Engine solution for bfloat16 inference uses the Intel® Math Kernel Library for Deep Neural Networks (Intel® MKL-DNN) and supports inference of the significant number of layers in BF16 computation mode.
### Lowering Inference Precision
Lowering precision to increase performance is widely used for optimization of inference. The bfloat16 data type usage on CPU for the first time opens the possibility of default optimization approach. The embodiment of this approach is to use the optimization capabilities of the current platform to achieve maximum performance while maintaining the accuracy of calculations within the acceptable range.
Using Bfloat16 precision provides the following performance benefits:
1. Faster multiplication of two BF16 numbers because of shorter mantissa of bfloat16 data.
2. No need to support denormals and handling exceptions as this is a performance optimization.
3. Fast conversion of float32 to bfloat16 and vice versa.
4. Reduced size of data in memory, as a result, larger models fit in the same memory bounds.
5. Reduced amount of data that must be transferred, as a result, reduced data transition time.
For default optimization on CPU, the source model is converted from FP32 or FP16 to BF16 and executed internally on platforms with native BF16 support. In this case, ENFORCE_BF16 is set to YES. The code below demonstrates how to check if the key is set:
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(path_to_xml_file)
exec_net = ie.load_network(network=net, device_name="CPU")
exec_net.get_config("ENFORCE_BF16")
```
To enable BF16 internal transformations, set the key "ENFORCE_BF16" to "YES" in the ExecutableNetwork configuration.
```python
bf16_config = {"ENFORCE_BF16" : "YES"}
exec_net = ie.load_network(network=net, device_name="CPU", config = bf16_config)
```
To disable BF16 internal transformations, set the key "ENFORCE_BF16" to "NO". In this case, the model infers as is without modifications with precisions that were set on each layer edge.
An exception with the message `Platform doesn't support BF16 format` is formed in case of setting "ENFORCE_BF16" to "YES"on CPU without native BF16 support or BF16 simulation mode.
Low-Precision 8-bit integer models cannot be converted to BF16, even if bfloat16 optimization is set by default.
### Bfloat16 Simulation Mode
Bfloat16 simulation mode is available on CPU and Intel® AVX-512 platforms that do not support the native avx512_bf16 instruction. The simulator does not guarantee good performance. Note that the CPU must still support the AVX-512 extensions.
#### To Enable the simulation of Bfloat16:
* In the Benchmark App, add the -enforcebf16=true option
* In Python, use the following code as an example:
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(path_to_xml_file)
bf16_config = {"ENFORCE_BF16" : "YES"}
exec_net = ie.load_network(network=net, device_name="CPU", config=bf16_config)
```
### Performance Counters
Information about layer precision is stored in the performance counters that are available from the Inference Engine API. The layers have the following marks:
* Suffix *BF16* for layers that had bfloat16 data type input and were computed in BF16 precision
* Suffix *FP32* for layers computed in 32-bit precision
For example, the performance counters table for the Inception model can look as follows:
```
pool5 EXECUTED layerType: Pooling realTime: 143 cpu: 143 execType: jit_avx512_BF16
fc6 EXECUTED layerType: FullyConnected realTime: 47723 cpu: 47723 execType: jit_gemm_BF16
relu6 NOT_RUN layerType: ReLU realTime: 0 cpu: 0 execType: undef
fc7 EXECUTED layerType: FullyConnected realTime: 7558 cpu: 7558 execType: jit_gemm_BF16
relu7 NOT_RUN layerType: ReLU realTime: 0 cpu: 0 execType: undef
fc8 EXECUTED layerType: FullyConnected realTime: 2193 cpu: 2193 execType: jit_gemm_BF16
prob EXECUTED layerType: SoftMax realTime: 68 cpu: 68 execType: jit_avx512_FP32
```
The **execType** column of the table includes inference primitives with specific suffixes.
[bf16_format]: img/bf16_format.png [bf16_format]: img/bf16_format.png

View File

@ -72,7 +72,7 @@ InferenceEngine:
API version ............ 1.0 API version ............ 1.0
Build .................. lnx_20180510 Build .................. lnx_20180510
Description ....... MKLDNNPlugin Description ....... ov_intel_cpu_plugin
API version ............ 0.1 API version ............ 0.1
Build .................. ci-main-03659 Build .................. ci-main-03659
@ -135,7 +135,7 @@ InferenceEngine:
API version ............ 1.0 API version ............ 1.0
Build .................. ### Build .................. ###
Description ....... MKLDNNPlugin Description ....... ov_intel_cpu_plugin
[ INFO ] Inputs detected: <list_of_input_layers> [ INFO ] Inputs detected: <list_of_input_layers>
[ INFO ] Statistics will be dumped for 1 layers: <output_layer_name(s)> [ INFO ] Statistics will be dumped for 1 layers: <output_layer_name(s)>

View File

@ -1,120 +1,52 @@
# Inference Engine Developer Guide {#openvino_docs_IE_DG_Deep_Learning_Inference_Engine_DevGuide} # Inference Engine Developer Guide {#openvino_docs_IE_DG_Deep_Learning_Inference_Engine_DevGuide}
This Guide provides an overview of the Inference Engine describing the typical workflow for performing inference of a pre-trained and optimized deep learning model and a set of sample applications. @sphinxdirective
> **NOTE:** Before you perform inference with the Inference Engine, your models should be converted to the Inference Engine format using the Model Optimizer or built directly in runtime using nGraph API. To learn about how to use Model Optimizer, refer to the [Model Optimizer Developer Guide](../MO_DG/Deep_Learning_Model_Optimizer_DevGuide.md). To learn about the pre-trained and optimized models delivered with the OpenVINO™ toolkit, refer to [Pre-Trained Models](@ref omz_models_group_intel). .. toctree::
:maxdepth: 1
:hidden:
openvino_docs_IE_DG_Integrate_with_customer_application_new_API
openvino_docs_deployment_optimization_guide_dldt_optimization_guide
openvino_docs_IE_DG_Device_Plugins
Direct ONNX Format Support <openvino_docs_IE_DG_ONNX_Support>
openvino_docs_IE_DG_Int8Inference
openvino_docs_IE_DG_Bfloat16Inference
openvino_docs_IE_DG_DynamicBatching
openvino_docs_IE_DG_ShapeInference
openvino_docs_IE_DG_Model_caching_overview
openvino_docs_IE_DG_Extensibility_DG_Intro
openvino_docs_IE_DG_Memory_primitives
openvino_docs_IE_DG_network_state_intro
openvino_docs_IE_DG_API_Changes
openvino_docs_IE_DG_Known_Issues_Limitations
openvino_docs_IE_DG_Glossary
@endsphinxdirective
After you have used the Model Optimizer to create an Intermediate Representation (IR), use the Inference Engine to infer the result for a given input data. ## Introduction
Inference Engine is a set of C++ libraries with C and Python bindings providing a common API to deliver inference solutions on the platform of your choice. Use the Inference Engine API to read the Intermediate Representation (IR), ONNX and execute the model on devices.
Inference Engine is a set of C++ libraries providing a common API to deliver inference solutions on the platform of your choice: CPU, GPU, or VPU. Use the Inference Engine API to read the Intermediate Representation, set the input and output formats, and execute the model on devices. While the C++ libraries is the primary implementation, C libraries and Python bindings are also available. Inference Engine uses a plugin architecture. Inference Engine plugin is a software component that contains complete implementation for inference on a certain Intel® hardware device: CPU, GPU, VPU, etc. Each plugin implements the unified API and provides additional hardware-specific APIs.
The scheme below illustrates the typical workflow for deploying a trained deep learning model:
For Intel® Distribution of OpenVINO™ toolkit, Inference Engine binaries are delivered within release packages. ![](img/BASIC_FLOW_IE_C.svg)
The open source version is available in the [OpenVINO™ toolkit GitHub repository](https://github.com/openvinotoolkit/openvino) and can be built for supported platforms using the <a href="https://github.com/openvinotoolkit/openvino/wiki/BuildingCode">Inference Engine Build Instructions</a>. \\* _nGraph_ is the internal graph representation in the OpenVINO™ toolkit. Use it to [build a model from source code](https://docs.openvinotoolkit.org/latest/openvino_docs_nGraph_DG_build_function.html).
To learn about how to use the Inference Engine API for your application, see the [Integrating Inference Engine in Your Application](Integrate_with_customer_application_new_API.md) documentation.
For complete API Reference, see the [Inference Engine API References](./api_references.html) section. ## Video
Inference Engine uses a plugin architecture. Inference Engine plugin is a software component that contains complete implementation for inference on a certain Intel&reg; hardware device: CPU, GPU, VPU, etc. Each plugin implements the unified API and provides additional hardware-specific APIs. @sphinxdirective
## Modules in the Inference Engine component .. list-table::
### Core Inference Engine Libraries
Your application must link to the core Inference Engine libraries: * - .. raw:: html
* Linux* OS:
- `libinference_engine.so`, which depends on `libinference_engine_transformations.so`, `libtbb.so`, `libtbbmalloc.so` and `libngraph.so`
* Windows* OS:
- `inference_engine.dll`, which depends on `inference_engine_transformations.dll`, `tbb.dll`, `tbbmalloc.dll` and `ngraph.dll`
* macOS*:
- `libinference_engine.dylib`, which depends on `libinference_engine_transformations.dylib`, `libtbb.dylib`, `libtbbmalloc.dylib` and `libngraph.dylib`
The required C++ header files are located in the `include` directory. <iframe allowfullscreen mozallowfullscreen msallowfullscreen oallowfullscreen webkitallowfullscreen height="315" width="100%"
src="https://www.youtube.com/embed/e6R13V8nbak">
This library contains the classes to: </iframe>
* Create Inference Engine Core object to work with devices and read network (InferenceEngine::Core) * - **Inference Engine Concept**. Duration: 3:43
* Manipulate network information (InferenceEngine::CNNNetwork)
* Execute and pass inputs and outputs (InferenceEngine::ExecutableNetwork and InferenceEngine::InferRequest) @endsphinxdirective
### Plugin Libraries to Read a Network Object
Starting from 2022.1 release, OpenVINO Runtime introduced a concept of frontend plugins. Such plugins can be automatically dynamically loaded by OpenVINO Runtime dynamically depending on file format:
* Linux* OS:
- `libir_ov_frontend.so` to read a network from IR
- `libpaddlepaddle_ov_frontend.so` to read a network from PaddlePaddle model format
- `libonnx_ov_frontend.so` to read a network from ONNX model format
* Windows* OS:
- `ir_ov_frontend.dll` to read a network from IR
- `paddlepaddle_ov_frontend.dll` to read a network from PaddlePaddle model format
- `onnx_ov_frontend.dll` to read a network from ONNX model format
### Device-Specific Plugin Libraries
For each supported target device, Inference Engine provides a plugin — a DLL/shared library that contains complete implementation for inference on this particular device. The following plugins are available:
| Plugin | Device Type |
| ------- | ----------------------------- |
|CPU | Intel® Xeon® with Intel® AVX2 and AVX512, Intel® Core™ Processors with Intel® AVX2, Intel® Atom® Processors with Intel® SSE |
|GPU | Intel® Processor Graphics, including Intel® HD Graphics and Intel® Iris® Graphics |
|MYRIAD | Intel® Neural Compute Stick 2 powered by the Intel® Movidius™ Myriad™ X |
|GNA | Intel&reg; Speech Enabling Developer Kit, Amazon Alexa* Premium Far-Field Developer Kit, Intel&reg; Pentium&reg; Silver J5005 Processor, Intel&reg; Pentium&reg; Silver N5000 Processor, Intel&reg; Celeron&reg; J4005 Processor, Intel&reg; Celeron&reg; J4105 Processor, Intel&reg; Celeron&reg; Processor N4100, Intel&reg; Celeron&reg; Processor N4000, Intel&reg; Core&trade; i3-8121U Processor, Intel&reg; Core&trade; i7-1065G7 Processor, Intel&reg; Core&trade; i7-1060G7 Processor, Intel&reg; Core&trade; i5-1035G4 Processor, Intel&reg; Core&trade; i5-1035G7 Processor, Intel&reg; Core&trade; i5-1035G1 Processor, Intel&reg; Core&trade; i5-1030G7 Processor, Intel&reg; Core&trade; i5-1030G4 Processor, Intel&reg; Core&trade; i3-1005G1 Processor, Intel&reg; Core&trade; i3-1000G1 Processor, Intel&reg; Core&trade; i3-1000G4 Processor |
|HETERO | Automatic splitting of a network inference between several devices (for example if a device doesn't support certain layers|
|MULTI | Simultaneous inference of the same network on several devices in parallel|
The table below shows the plugin libraries and additional dependencies for Linux, Windows and macOS platforms.
| Plugin | Library name for Linux | Dependency libraries for Linux | Library name for Windows | Dependency libraries for Windows | Library name for macOS | Dependency libraries for macOS |
|--------|-----------------------------|-------------------------------------------------------------|--------------------------|--------------------------------------------------------------------------------------------------------|------------------------------|---------------------------------------------|
| CPU | `libMKLDNNPlugin.so` | `libinference_engine_lp_transformations.so` | `MKLDNNPlugin.dll` | `inference_engine_lp_transformations.dll` | `libMKLDNNPlugin.so` | `inference_engine_lp_transformations.dylib` |
| GPU | `libov_intel_gpu_plugin.so` | `libinference_engine_lp_transformations.so`, `libOpenCL.so` | `ov_intel_gpu_plugin.dll` | `OpenCL.dll`, `inference_engine_lp_transformations.dll` | Is not supported | - |
| MYRIAD | `libmyriadPlugin.so` | `libusb.so`, | `myriadPlugin.dll` | `usb.dll` | `libmyriadPlugin.so` | `libusb.dylib` |
| HDDL | `libHDDLPlugin.so` | `libbsl.so`, `libhddlapi.so`, `libmvnc-hddl.so` | `HDDLPlugin.dll` | `bsl.dll`, `hddlapi.dll`, `json-c.dll`, `libcrypto-1_1-x64.dll`, `libssl-1_1-x64.dll`, `mvnc-hddl.dll` | Is not supported | - |
| GNA | `libov_intel_gna_plugin.so` | `libgna.so`, | `ov_intel_gna_plugin.dll` | `gna.dll` | Is not supported | - |
| HETERO | `libov_hetero_plugin.so` | Same as for selected plugins | `ov_hetero_plugin.dll` | Same as for selected plugins | `libov_hetero_plugin.so` | Same as for selected plugins |
| MULTI | `libov_auto_plugin.so` | Same as for selected plugins | `ov_auto_plugin.dll` | Same as for selected plugins | `libov_auto_plugin.so` | Same as for selected plugins |
| AUTO | `libov_auto_plugin.so` | Same as for selected plugins | `ov_auto_plugin.dll` | Same as for selected plugins | `libov_auto_plugin.so` | Same as for selected plugins |
> **NOTE**: All plugin libraries also depend on core Inference Engine libraries.
Make sure those libraries are in your computer's path or in the place you pointed to in the plugin loader. Make sure each plugin's related dependencies are in the:
* Linux: `LD_LIBRARY_PATH`
* Windows: `PATH`
* macOS: `DYLD_LIBRARY_PATH`
On Linux and macOS, use the script `setupvars.sh` to set the environment variables.
On Windows, run the `setupvars.bat` batch file to set the environment variables.
To learn more about supported devices and corresponding plugins, see the [Supported Devices](supported_plugins/Supported_Devices.md) chapter.
## Common Workflow for Using the Inference Engine API
The common workflow contains the following steps:
1. **Create Inference Engine Core object** - Create an `InferenceEngine::Core` object to work with different devices, all device plugins are managed internally by the `Core` object. Register extensions with custom nGraph operations (`InferenceEngine::Core::AddExtension`).
2. **Read the Intermediate Representation** - Using the `InferenceEngine::Core` class, read an Intermediate Representation file into an object of the `InferenceEngine::CNNNetwork` class. This class represents the network in the host memory.
3. **Prepare inputs and outputs format** - After loading the network, specify input and output precision and the layout on the network. For these specification, use the `InferenceEngine::CNNNetwork::getInputsInfo()` and `InferenceEngine::CNNNetwork::getOutputsInfo()`.
4. Pass per device loading configurations specific to this device (`InferenceEngine::Core::SetConfig`), and register extensions to this device (`InferenceEngine::Core::AddExtension`).
5. **Compile and Load Network to device** - Use the `InferenceEngine::Core::LoadNetwork()` method with specific device (e.g. `CPU`, `GPU`, etc.) to compile and load the network on the device. Pass in the per-target load configuration for this compilation and load operation.
6. **Set input data** - With the network loaded, you have an `InferenceEngine::ExecutableNetwork` object. Use this object to create an `InferenceEngine::InferRequest` in which you signal the input buffers to use for input and output. Specify a device-allocated memory and copy it into the device memory directly, or tell the device to use your application memory to save a copy.
7. **Execute** - With the input and output memory now defined, choose your execution mode:
* Synchronously - `InferenceEngine::InferRequest::Infer()` method. Blocks until inference is completed.
* Asynchronously - `InferenceEngine::InferRequest::StartAsync()` method. Check status with the `InferenceEngine::InferRequest::Wait()` method (0 timeout), wait, or specify a completion callback.
8. **Get the output** - After inference is completed, get the output memory or read the memory you provided earlier. Do this with the `InferenceEngine::IInferRequest::GetBlob()` method.
## Video: Inference Engine Concept
<iframe width="560" height="315" src="https://www.youtube.com/embed/e6R13V8nbak" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## Further Reading
For more details on the Inference Engine API, refer to the [Integrating Inference Engine in Your Application](Integrate_with_customer_application_new_API.md) documentation.

View File

@ -1,52 +1,106 @@
Using Dynamic Batching {#openvino_docs_IE_DG_DynamicBatching} # Using Dynamic Batching {#openvino_docs_IE_DG_DynamicBatching}
======================
Dynamic Batching feature allows you to dynamically change batch size for inference calls ## Using Dynamic Batching (C++)
within preset batch size limit.
This feature might be useful when batch size is unknown beforehand, and using extra large batch size is @sphinxdirective
undesired or impossible due to resource limitations. .. raw:: html
For example, face detection with person age, gender, or mood recognition is a typical usage scenario.
<div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
The Dynamic Batching feature allows you to dynamically change batch size for inference calls
within a preset batch size limit. This feature might be useful when batch size is unknown beforehand and using an extra-large batch size is undesirable or impossible due to resource limitations. For example, applying face detection and then mood labeling to a video, you won't know in advance how many frames will contain a face when you pass inferencing results to a secondary model.
## Usage You can activate Dynamic Batching by setting `KEY_DYN_BATCH_ENABLED` flag to `YES` in a configuration map that is
You can activate Dynamic Batching by setting <code>KEY_DYN_BATCH_ENABLED</code> flag to <code>YES</code> in a configuration map that is
passed to the plugin while loading a network. passed to the plugin while loading a network.
This configuration creates an <code>ExecutableNetwork</code> object that will allow setting batch size This configuration creates an `ExecutableNetwork` object that will allow setting batch size
dynamically in all of its infer requests using <code>SetBatch()</code> method. dynamically in all of its infer requests using `SetBatch()` method.
The batch size that was set in passed <code>CNNNetwork</code> object will be used as a maximum batch size limit. The batch size that was set in the passed `CNNNetwork` object will be used as a maximum batch size limit.
Here is a code example: Here is a code example:
@snippet snippets/DynamicBatching.cpp part0 @snippet snippets/DynamicBatching.cpp part0
## Limitations ### Limitations
Currently, certain limitations for using Dynamic Batching exist: Currently, there are certain limitations for the use of Dynamic Batching exist:
* Use Dynamic Batching with CPU and GPU plugins only. * Use Dynamic Batching with CPU and GPU plugins only.
* Use Dynamic Batching on topologies that consist of certain layers only: * Use Dynamic Batching on topologies that consist of certain layers only:
* Convolution
* Deconvolution
* Activation
* LRN
* Pooling
* FullyConnected
* SoftMax
* Split
* Concatenation
* Power
* Eltwise
* Crop
* BatchNormalization
* Copy
* Convolution The following types of layers are not supported:
* Deconvolution
* Activation
* LRN
* Pooling
* FullyConnected
* SoftMax
* Split
* Concatenation
* Power
* Eltwise
* Crop
* BatchNormalization
* Copy
Do not use layers that might arbitrary change tensor shape (such as Flatten, Permute, Reshape),
layers specific to object detection topologies (ROIPooling, ProirBox, DetectionOutput), and
custom layers.
Topology analysis is performed during the process of loading a network into plugin, and if topology is
not applicable, an exception is generated.
* Layers that might arbitrary change tensor shape (such as Flatten, Permute, Reshape)
* Layers specific to object detection topologies (ROIPooling, ProirBox, DetectionOutput)
* Custom layers
Topology analysis is performed during the process of loading a network into plugin, and if the topology is not supported, an exception is generated.
## Using Dynamic Batching (Python)
@sphinxdirective
.. raw:: html
<div id="switcher-python" class="switcher-anchor">Python</div>
@endsphinxdirective
Dynamic Batching is a feature that allows you to dynamically change batch size for inference calls within a preset batch size limit. This feature might be useful when batch size is unknown beforehand, and using extra large batch size is not desired or impossible due to resource limitations. For example, face detection with person age, gender, or mood recognition is a typical usage scenario.
You can activate Dynamic Batching by setting the "DYN_BATCH_ENABLED" flag to "YES" in a configuration map that is passed to the plugin while loading a network. This configuration creates an `ExecutableNetwork` object that will allow setting batch size dynamically in all of its infer requests using the [ie_api.batch_size](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.batch_size) method. The batch size that was set in the passed CNNNetwork object will be used as a maximum batch size limit.
```python
from openvino.inference_engine import IECore
ie = IECore()
dyn_config = {"DYN_BATCH_ENABLED": "YES"}
ie.set_config(config=dyn_config, device_name=device)
# Read a network in IR or ONNX format
net = ie.read_network(path_to_model)
net.batch_size = 32 # set the maximum batch size to 32
exec_net = ie.load_network(network=net, device_name=device)
```
### Limitations
Currently, certain limitations for the use of Dynamic Batching exist:
* Use Dynamic Batching with CPU and GPU plugins only.
* Use Dynamic Batching on topologies that consist of certain layers only:
* Convolution
* Deconvolution
* Activation
* LRN
* Pooling
* FullyConnected
* SoftMax
* Split
* Concatenation
* Power
* Eltwise
* Crop
* BatchNormalization
* Copy
The following types of layers are not supported:
* Layers that might arbitrary change tensor shape (such as Flatten, Permute, Reshape)
* Layers specific to object detection topologies (ROIPooling, ProirBox, DetectionOutput)
* Custom layers
Topology analysis is performed during the process of loading a network into plugin, and if the topology is not supported, an exception is generated.

View File

@ -1,6 +1,8 @@
# Custom nGraph Operation {#openvino_docs_IE_DG_Extensibility_DG_AddingNGraphOps} # Custom nGraph Operations {#openvino_docs_IE_DG_Extensibility_DG_AddingNGraphOps}
The Inference Engine Extension API allows you to register operation sets (opsets) with custom nGraph operations to support models with operations that OpenVINO™ does not support out-of-the-box. Inference Engine Extension API allows you to register operation sets (opsets) with custom nGraph operations to support models with operations which OpenVINO™ does not support out-of-the-box.
Besides creating custom nGraph operations, to [support custom operations](../../HOWTO/Custom_Layers_Guide.md) in your model you must also create a Model Optimizer extension for the custom operations and an Inference Engine device plugin extension for the device you will use for inference.
## Operation Class ## Operation Class
@ -26,8 +28,8 @@ Based on that, declaration of an operation class can look as follows:
The provided implementation has several fields: The provided implementation has several fields:
* `add` of type `int64_t` is an attribute of a custom operation. * `add` of type `int64_t` is an attribute of a custom operation
* `type_info` of type `ngraph::NodeTypeInfo` defines the type and version of an operation. * `type_info` of type `ngraph::NodeTypeInfo` defines type and version of an operation
### Operation Constructors ### Operation Constructors
@ -67,14 +69,13 @@ To add custom operations to the [Extension](Extension.md) class, create an opera
@snippet template_extension/old/extension.cpp extension:getOpSets @snippet template_extension/old/extension.cpp extension:getOpSets
This method returns a map of opsets that exist in the extension library. This method returns a map of opsets that exist in the [extension library](Extension.md).
nGraph provides an opset mechanism to group operations into clusters. Different opsets distinguish between different versions of one operation.
nGraph provides an opset mechanism to group operations into clusters. S. Different opsets distinguish between different versions of one operation.
When specifying opset names, follow the rules below: When specifying opset names, follow the rules below:
* Use unique opset names. * Use unique opset names.
* Do not use the following built-in opset names: `extension`, `experimental`, `opset1`, `opset2`, `opset3`, ... , `opsetN`. * Do not use the following built-in opset names: `extension`, `experimental`, `opset1`, `opset2`, `opset3`, ... , `opsetN`.
* Make sure that the Model Optimizer and your extension use the same opset names. * [Make sure that the Model Optimizer](../../HOWTO/Custom_Layers_Guide.md) and your extension use the same opset names.
* IR v10 operations have the mandatory `version` attribute specifying the opset. * IR v10 operations have the mandatory `version` attribute specifying the opset.
Operations from the default opset cannot be redefined. Operations from the default opset cannot be redefined.

View File

@ -2,13 +2,13 @@
Inference Engine build infrastructure provides the Inference Engine Package for application development. Inference Engine build infrastructure provides the Inference Engine Package for application development.
To build an extension library, use the following CMake script: To configure the build of your extension library, use the following CMake script:
@snippet template_extension/old/CMakeLists.txt cmake:extension @snippet template_extension/old/CMakeLists.txt cmake:extension
This CMake script finds the Inference Engine and nGraph using the `find_package` CMake command. This CMake script finds the Inference Engine and nGraph using the `find_package` CMake command.
To build an extension library, run the commands below: To build the extension library, run the commands below:
```sh ```sh
$ cd template_extension/old $ cd template_extension/old

View File

@ -1,6 +1,8 @@
# How to Implement Custom CPU Operations {#openvino_docs_IE_DG_Extensibility_DG_CPU_Kernel} # CPU Kernel Custom Operations {#openvino_docs_IE_DG_Extensibility_DG_CPU_Kernel}
The primary means of the performance of the CPU codepath in the Inference Engine is the Intel® Math Kernel Library for Deep Neural Networks (Intel® MKL-DNN), and new CPU kernels extend the Inference Engine plugin for the Intel MKL-DNN. Implementing the InferenceEngine::ILayerExecImpl defines a general CPU-side extension. There are no Intel MKL-DNN specifics in the way you need to implement a kernel. To enable operations not supported by OpenVINO™ out of the box, you need a custom extension for Model Optimizer, a custom nGraph operation set, and a custom kernel for the device you will target. This page describes custom kernel support for the CPU device.
The primary means of the performance of the CPU codepath in the Inference Engine is the Intel® Math Kernel Library for Deep Neural Networks (Intel® MKL-DNN), and new CPU kernels extend the Inference Engine plugin for the Intel MKL-DNN. Implementing the InferenceEngine::ILayerExecImpl API call defines a general CPU-side extension. There are no Intel MKL-DNN specifics in the way you need to implement a kernel.
## Implementation Class ## Implementation Class
@ -20,31 +22,32 @@ The provided implementation has several fields:
### Constructor of Implementation ### Constructor of Implementation
An implementation constructor checks parameters of an nGraph operation, stores required attributes, and stores an error message in the case of an error. An implementation constructor checks parameters of an nGraph operation, stores required attributes, and stores an error message in case of an error.
@snippet template_extension/old/cpu_kernel.cpp cpu_implementation:ctor @snippet template_extension/old/cpu_kernel.cpp cpu_implementation:ctor
### `getSupportedConfigurations` ### `getSupportedConfigurations`
InferenceEngine::ILayerExecImpl::getSupportedConfigurations method returns all supported configuration formats (input/output tensor layouts) for your implementation. To specify formats of data, use InferenceEngine::TensorDesc. Refer to the [Memory Primitives](../Memory_primitives.md) section for instructions. The InferenceEngine::ILayerExecImpl::getSupportedConfigurations method returns all supported configuration formats (input/output tensor layouts) for your implementation. To specify formats of data, use InferenceEngine::TensorDesc. Refer to the [Memory Primitives](../Memory_primitives.md) section for instructions.
@snippet template_extension/old/cpu_kernel.cpp cpu_implementation:getSupportedConfigurations @snippet template_extension/old/cpu_kernel.cpp cpu_implementation:getSupportedConfigurations
### `init` ### `init`
InferenceEngine::ILayerExecImpl::init method gets a runtime-selected configuration from a vector that is populated from the `getSupportedConfigurations` method and checks the parameters: The InferenceEngine::ILayerExecImpl::init method gets a runtime-selected configuration from a vector that is populated from the `getSupportedConfigurations` method and checks the parameters:
@snippet template_extension/old/cpu_kernel.cpp cpu_implementation:init @snippet template_extension/old/cpu_kernel.cpp cpu_implementation:init
### `execute` ### `execute`
InferenceEngine::ILayerExecImpl::execute method accepts and processes the actual tenors as input/output blobs: The InferenceEngine::ILayerExecImpl::execute method accepts and processes the actual tensors as input/output blobs:
@snippet template_extension/old/cpu_kernel.cpp cpu_implementation:execute @snippet template_extension/old/cpu_kernel.cpp cpu_implementation:execute
## Register Implementation in `Extension` Class ## Register Implementation in `Extension` Class
To register custom kernel implementation in the [Extension](Extension.md) class, implement the following methods: To register custom kernel implementation in the [Extension](Extension.md) class, implement the following methods:
* <a href="#getImpTypes">getImplTypes</a> * <a href="#getImpTypes">getImplTypes</a>
* <a href="#getImplementation">getImplementation</a> * <a href="#getImplementation">getImplementation</a>
@ -66,4 +69,3 @@ InferenceEngine::IExtension::getImplementation returns the kernel implementation
Use the `AddExtension` method of the general plugin interface to load your primitives: Use the `AddExtension` method of the general plugin interface to load your primitives:
@snippet snippets/CPU_Kernel.cpp part0 @snippet snippets/CPU_Kernel.cpp part0

View File

@ -1,7 +1,7 @@
# Custom ONNX* Operators {#openvino_docs_IE_DG_Extensibility_DG_Custom_ONNX_Ops} # Custom ONNX* Operators {#openvino_docs_IE_DG_Extensibility_DG_Custom_ONNX_Ops}
The ONNX\* importer provides a mechanism to register custom ONNX operators based on predefined or custom nGraph operations. The ONNX\* importer provides a mechanism to register custom ONNX operators based on predefined or custom nGraph operations.
The function responsible for registering a new operator is called `ngraph::onnx_import::register_operator` and is defined in `onnx_import/onnx_utils.hpp`. The function responsible for registering a new operator is called `ngraph::onnx_import::register_operator` and defined in the `onnx_import/onnx_utils.hpp` file.
## Register Custom ONNX Operator Based on Predefined nGraph Operations ## Register Custom ONNX Operator Based on Predefined nGraph Operations
@ -14,19 +14,25 @@ x < 0 => f(x) = x * beta
where `alpha` and `beta` are float constants. where `alpha` and `beta` are float constants.
1. Include headers: 1. Include headers:
@snippet onnx_custom_op/onnx_custom_op.cpp onnx_custom_op:headers @snippet onnx_custom_op/onnx_custom_op.cpp onnx_custom_op:headers
2. Register the CustomRelu operator in the ONNX importer: 2. Register the CustomRelu operator in the ONNX importer:
@snippet onnx_custom_op/onnx_custom_op.cpp onnx_custom_op:register_operator @snippet onnx_custom_op/onnx_custom_op.cpp onnx_custom_op:register_operator
The `register_operator` function takes four arguments: op_type, opset version, domain, and a function object. The `register_operator` function takes four arguments: op_type, opset version, domain, and a function object.
The function object is a user-defined function that takes `ngraph::onnx_import::Node` as an input and based on that, returns a graph with nGraph operations. The function object is a user-defined function that takes `ngraph::onnx_import::Node` as an input and based on that, returns a graph with nGraph operations.
The `ngraph::onnx_import::Node` class represents a node in an ONNX model. It provides functions to fetch input node(s) using `get_ng_inputs`, attribute value using `get_attribute_value`, and many more. See `onnx_import/core/node.hpp` for full class declaration. The `ngraph::onnx_import::Node` class represents a node in an ONNX model. It provides functions to fetch input node(s) using `get_ng_inputs`, attribute value using `get_attribute_value`, and many more. See the `onnx_import/core/node.hpp` file for the full class declaration.
New operator registration must happen before an ONNX model is read. For example, if an model uses the `CustomRelu` operator, call `register_operator("CustomRelu", ...)` before InferenceEngine::Core::ReadNetwork. New operator registration must happen before an ONNX model is read. For example, if an model uses the `CustomRelu` operator, call `register_operator("CustomRelu", ...)` before InferenceEngine::Core::ReadNetwork.
Reregistering ONNX operators within the same process is supported. If you register an existing operator, you get a warning. 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: The example below demonstrates an exemplary model that requires a previously created `CustomRelu` operator:
```
@include onnx_custom_op/custom_relu_model.prototxt @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: This model is in text format, so before it can be passed to Inference Engine, it has to be converted to binary using:
```py ```py
from google.protobuf import text_format from google.protobuf import text_format
@ -44,12 +50,14 @@ To create a graph with nGraph operations, visit [Custom nGraph Operations](Addin
For a complete list of predefined nGraph operators, visit [Available Operations Sets](../../ops/opset.md). For a complete list of predefined nGraph operators, visit [Available Operations Sets](../../ops/opset.md).
If you do not need an operator anymore, unregister it by calling `unregister_operator`. The function takes three arguments: `op_type`, `version`, and `domain`. If you do not need an operator anymore, unregister it by calling `unregister_operator`. The function takes three arguments: `op_type`, `version`, and `domain`.
@snippet onnx_custom_op/onnx_custom_op.cpp onnx_custom_op:unregister_operator @snippet onnx_custom_op/onnx_custom_op.cpp onnx_custom_op:unregister_operator
## Register Custom ONNX Operator Based on Custom nGraph Operations ## Register Custom ONNX Operator Based on Custom nGraph Operations
The same principles apply when registering a custom ONNX operator based on custom nGraph operations. The same principles apply when registering a custom ONNX operator based on custom nGraph operations.
This example shows how to register a custom ONNX operator based on `Operation` presented in [this tutorial](AddingNGraphOps.md), which is used in [TemplateExtension](Extension.md). This example shows how to register a custom ONNX operator based on `Operation` presented in [this tutorial](AddingNGraphOps.md), which is used in [TemplateExtension](Extension.md):
@snippet template_extension/old/extension.cpp extension:ctor @snippet template_extension/old/extension.cpp extension:ctor
Here, the `register_operator` function is called in the constructor of Extension. The constructor makes sure that the function is called before InferenceEngine::Core::ReadNetwork, because InferenceEngine::Core::AddExtension must be called before a model with a custom operator is read. Here, the `register_operator` function is called in the constructor of Extension. The constructor makes sure that the function is called before InferenceEngine::Core::ReadNetwork, because InferenceEngine::Core::AddExtension must be called before a model with a custom operator is read.
@ -62,8 +70,9 @@ The example below demonstrates how to unregister an operator from the destructor
## Requirements for Building with CMake ## Requirements for Building with CMake
A program that uses the `register_operator` functionality requires `openvino::core` and `openvino::frontend::onnx` libraries in addition to the OpenVINO Inference Runtime. A program that uses the `register_operator` functionality requires `openvino::core` and `openvino::frontend::onnx` libraries in addition to the OpenVINO Inference Runtime.
The `onnx_ov_frontend` is a component of the `OpenVINO` package , so `find_package(OpenVINO REQUIRED COMPONENTS ONNX)` can find both. The `ov_onnx_frontend` is a component of the `OpenVINO` package , so `find_package(OpenVINO REQUIRED COMPONENTS ONNX)` can find both.
Those libraries need to be passed to the `target_link_libraries` command in the CMakeLists.txt file. Those libraries need to be passed to the `target_link_libraries` command in the CMakeLists.txt file.
See CMakeLists.txt below for reference: See CMakeLists.txt below for reference:
@snippet onnx_custom_op/CMakeLists.txt cmake:onnx_custom_op @snippet onnx_custom_op/CMakeLists.txt cmake:onnx_custom_op

View File

@ -25,6 +25,5 @@ Also, an `Extension` object should implement the following methods:
Implement the InferenceEngine::IExtension::getOpSets method if the extension contains custom layers. Implement the InferenceEngine::IExtension::getOpSets method if the extension contains custom layers.
Read [Custom nGraph Operation](AddingNGraphOps.md) for more information. Read [Custom nGraph Operation](AddingNGraphOps.md) for more information.
To understand how to integrate execution kernels to the extension library, read the [documentation about development of custom CPU kernels](CPU_Kernel.md). To integrate execution kernels to the extension library, read [How to Implement Custom CPU Operations](CPU_Kernel.md).
To register a custom ONNX\* operator to the extension library, read [Custom ONNX Operators](Custom_ONNX_Ops.md).
To understand how to register custom ONNX operator to the extension library, read the [documentation about custom ONNX operators](Custom_ONNX_Ops.md).

View File

@ -1,15 +1,17 @@
# How to Implement Custom GPU Operations {#openvino_docs_IE_DG_Extensibility_DG_GPU_Kernel} # How to Implement Custom GPU Operations {#openvino_docs_IE_DG_Extensibility_DG_GPU_Kernel}
The GPU codepath abstracts many details about OpenCL\*. You need to provide the kernel code in OpenCL C and the configuration file that connects the kernel and its parameters to the parameters of the operation. To enable operations not supported by OpenVINO™ out of the box, you need a custom extension for Model Optimizer, a custom nGraph operation set, and a custom kernel for the device you will target. This page describes custom kernel support for the GPU device.
There are two options of using the custom operation configuration file: The GPU codepath abstracts many details about OpenCL\*. You need to provide the kernel code in OpenCL C and an XML configuration file that connects the kernel and its parameters to the parameters of the operation.
There are two options for using the custom operation configuration file:
* Include a section with your kernels into the global automatically-loaded `cldnn_global_custom_kernels/cldnn_global_custom_kernels.xml` file, which is hosted in the `<INSTALL_DIR>/runtime/bin` folder * Include a section with your kernels into the global automatically-loaded `cldnn_global_custom_kernels/cldnn_global_custom_kernels.xml` file, which is hosted in the `<INSTALL_DIR>/runtime/bin` folder
* Call the `InferenceEngine::Core::SetConfig()` method from your application with the `InferenceEngine::PluginConfigParams::KEY_CONFIG_FILE` key and the configuration file name as a value before loading the network that uses custom operations to the plugin: * Call the `InferenceEngine::Core::SetConfig()` method from your application with the `InferenceEngine::PluginConfigParams::KEY_CONFIG_FILE` key and the configuration file name as a value before loading the network that uses custom operations to the plugin:
@snippet snippets/GPU_Kernel.cpp part0 @snippet snippets/GPU_Kernel.cpp part0
All Inference Engine samples, except the trivial `hello_classification`, All Inference Engine samples, except the trivial `hello_classification`, and most Open Model Zoo demos
feature a dedicated command-line option `-c` to load custom kernels. For example, to load custom operations for the classification sample, run the command below: feature a dedicated command-line option `-c` to load custom kernels. For example, to load custom operations for the classification sample, run the command below:
```sh ```sh
$ ./classification_sample -m <path_to_model>/bvlc_alexnet_fp16.xml -i ./validation_set/daily/227x227/apron.bmp -d GPU $ ./classification_sample -m <path_to_model>/bvlc_alexnet_fp16.xml -i ./validation_set/daily/227x227/apron.bmp -d GPU
@ -132,8 +134,8 @@ queuing an OpenCL program for execution.
## Example Configuration File ## Example Configuration File
The following code sample provides an example configuration file in the The following code sample provides an example configuration file in XML
`.xml` format. For information on the configuration file structure, see format. For information on the configuration file structure, see
[Configuration File Format](#config-file-format). [Configuration File Format](#config-file-format).
```xml ```xml
<CustomLayer name="ReLU" type="SimpleGPU" version="1"> <CustomLayer name="ReLU" type="SimpleGPU" version="1">
@ -208,12 +210,12 @@ __kernel void example_relu_kernel(
} }
``` ```
> **NOTE:** As described in the previous section, all things like > **NOTE**: As described in the previous section, all items like
> `INPUT0_TYPE` are actually defined as OpenCL (pre-)compiler inputs by > `INPUT0_TYPE` are actually defined as OpenCL (pre-)compiler inputs by
> the Inference Engine for efficiency reasons. See [Debugging > the Inference Engine for efficiency reasons. See [Debugging
> Tips](#debugging-tips) for information on debugging the results. > Tips](#debugging-tips) for information on debugging the results.
> **NOTE**: Several GPU-targeted kernels are also added to the binaries upon samples compilation > **NOTE**: Several GPU-targeted kernels are also added to the binaries upon compilation of samples
> so that the sample application can easy load them. > so that the sample application can easy load them.
> Refer to the `cldnn_global_custom_kernels` folder in the GPU plugin installation directory. > Refer to the `cldnn_global_custom_kernels` folder in the GPU plugin installation directory.
@ -221,10 +223,11 @@ __kernel void example_relu_kernel(
* **Using `printf` in the OpenCL™ Kernels**. * **Using `printf` in the OpenCL™ Kernels**.
To debug the specific values, you can use `printf` in your kernels. To debug the specific values, you can use `printf` in your kernels.
However, be careful: for instance, do not output excessively However, be careful not to output excessively, which
as it would generate too much data. The `printf` output is typical, so could generate too much data. The `printf` output is typical, so
your output can be truncated to fit the buffer. Also, because of your output can be truncated to fit the buffer. Also, because of
buffering, you actually get an entire buffer of output when the buffering, you actually get an entire buffer of output when the
execution ends.<br> execution ends.<br>
For more information, refer to the [printf For more information, refer to the [printf
Function](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/printfFunction.html). Function](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/printfFunction.html).

View File

@ -1,27 +1,39 @@
# Inference Engine Extensibility Mechanism {#openvino_docs_IE_DG_Extensibility_DG_Intro} # Inference Engine Extensibility Mechanism {#openvino_docs_IE_DG_Extensibility_DG_Intro}
Inference Engine Extensibility API enables you to add support of custom operations to the Inference Engine. @sphinxdirective
Extension should contain operation sets with custom operations and execution kernels for custom operations.
Physically, an extension library can be represented as a dynamic library exporting the single function
that creates a new extension instance.
To load the Extensibility library to the `InferenceEngine::Core` object, use the .. toctree::
`InferenceEngine::Core::AddExtension` method. :maxdepth: 1
:hidden:
openvino_docs_IE_DG_Extensibility_DG_AddingNGraphOps
openvino_docs_IE_DG_Extensibility_DG_Custom_ONNX_Ops
CPU Kernels Extensibility <openvino_docs_IE_DG_Extensibility_DG_CPU_Kernel>
GPU Kernels Extensibility <openvino_docs_IE_DG_Extensibility_DG_GPU_Kernel>
VPU Kernels Extensibility <openvino_docs_IE_DG_Extensibility_DG_VPU_Kernel>
openvino_docs_IE_DG_Extensibility_DG_Extension
openvino_docs_IE_DG_Extensibility_DG_Building
@endsphinxdirective
If your model contains operations not normally supported by OpenVINO, the Inference Engine Extensibility API lets you add support for those custom operations in a library containing custom nGraph operation sets, corresponding extensions to the Model Optimizer, and a device plugin extension. See the overview in the [Custom Operations Guide](../../HOWTO/Custom_Layers_Guide.md) to learn how these work together.
To load the Extensibility library to the `InferenceEngine::Core` object, use the `InferenceEngine::Core::AddExtension` method.
## Inference Engine Extension Library ## Inference Engine Extension Library
Inference Engine Extension dynamic library contains the following components: An Inference Engine Extension dynamic library contains the following components:
* [Extension Library](Extension.md): * [Extension Library](Extension.md):
- Contains custom operation sets. - Contains custom operation sets
- Provides CPU implementations for custom operations. - Provides CPU implementations for custom operations
* [Custom nGraph Operation](AddingNGraphOps.md): * [Custom nGraph Operation](AddingNGraphOps.md):
- Enables the use of `InferenceEngine::Core::ReadNetwork` to read Intermediate Representation (IR) with unsupported - Enables the use of `InferenceEngine::Core::ReadNetwork` to read Intermediate Representation (IR) with unsupported
operations. operations
- Enables the creation of `ngraph::Function` with unsupported operations. - Enables the creation of `ngraph::Function` with unsupported operations
- Provides a shape inference mechanism for custom operations. - Provides a shape inference mechanism for custom operations
> **NOTE**: This documentation is written based on the `Template extension`, which demonstrates extension development details. Find the complete code of the `Template extension`, which is fully compilable and up-to-date, at `<dldt source tree>/docs/template_extension`. > **NOTE**: This documentation is written based on the [Template extension](https://github.com/openvinotoolkit/openvino/tree/master/docs/template_extension), which demonstrates extension development details. You can review the complete code, which is fully compilable and up-to-date, to see how it works.
## Execution Kernels ## Execution Kernels

View File

@ -1,10 +1,12 @@
# How to Implement Custom Layers for VPU (Intel® Neural Compute Stick 2) {#openvino_docs_IE_DG_Extensibility_DG_VPU_Kernel} # How to Implement Custom Layers for VPU (Intel® Neural Compute Stick 2) {#openvino_docs_IE_DG_Extensibility_DG_VPU_Kernel}
To enable operations not supported by OpenVINO™ out of the box, you need a custom extension for Model Optimizer, a custom nGraph operation set, and a custom kernel for the device you will target. This page describes custom kernel support for one the VPU, the Intel® Neural Compute Stick 2 device, which uses the MYRIAD device plugin.
> **NOTES:** > **NOTES:**
> * OpenCL\* custom layer support is available in the preview mode. > * OpenCL\* custom layer support is available in the preview mode.
> * This section assumes you are familiar with developing kernels using OpenCL. > * This section assumes you are familiar with developing kernels using OpenCL.
To customize your topology with an OpenCL layer, follow the steps below: To customize your topology with an OpenCL layer, carry out the tasks described on this page:
1. Write and compile your OpenCL code with the standalone offline OpenCL compiler (`clc`). 1. Write and compile your OpenCL code with the standalone offline OpenCL compiler (`clc`).
2. Write a configuration file to bind the OpenCL kernel to the topology file (`.xml`) of the model IR. 2. Write a configuration file to bind the OpenCL kernel to the topology file (`.xml`) of the model IR.
@ -12,12 +14,12 @@ To customize your topology with an OpenCL layer, follow the steps below:
## Compile OpenCL code for VPU (Intel® Neural Compute Stick 2) ## Compile OpenCL code for VPU (Intel® Neural Compute Stick 2)
> **NOTE:** OpenCL compiler, targeting Intel® Neural Compute Stick 2 for the SHAVE* processor only, is redistributed with OpenVINO. > **NOTE**: OpenCL compiler, targeting Intel® Neural Compute Stick 2 for the SHAVE* processor only, is redistributed with OpenVINO.
OpenCL support is provided by ComputeAorta*, and is distributed under a license agreement between Intel® and Codeplay* Software Ltd. OpenCL support is provided by ComputeAorta* and is distributed under a license agreement between Intel® and Codeplay* Software Ltd.
The OpenCL toolchain for the Intel® Neural Compute Stick 2 supports offline compilation only, so first compile OpenCL C code using the standalone `clc` compiler. You can find the compiler binary at `<INSTALL_DIR>/tools/cl_compiler`. The OpenCL toolchain for the Intel® Neural Compute Stick 2 supports offline compilation only, so first compile OpenCL C code using the standalone `clc` compiler. You can find the compiler binary at `<INSTALL_DIR>/tools/cl_compiler`.
> **NOTE:** By design, custom OpenCL layers support any OpenCL kernels written with 1.2 version assumed. It also supports half float extension and is optimized for this type, because it is a native type for Intel® Movidius™ VPUs. > **NOTE**: By design, custom OpenCL layers support any OpenCL kernels written assuming OpenCL version 1.2. It also supports half float extension and is optimized for this type, because it is a native type for Intel® Movidius™ VPUs.
1. Prior to running a compilation, make sure that the following variables are set: 1. Prior to running a compilation, make sure that the following variables are set:
* `SHAVE_MA2X8XLIBS_DIR=<INSTALL_DIR>/tools/cl_compiler/lib/` * `SHAVE_MA2X8XLIBS_DIR=<INSTALL_DIR>/tools/cl_compiler/lib/`
@ -25,19 +27,19 @@ The OpenCL toolchain for the Intel® Neural Compute Stick 2 supports offline com
* `SHAVE_MYRIAD_LD_DIR=<INSTALL_DIR>/tools/cl_compiler/bin/` * `SHAVE_MYRIAD_LD_DIR=<INSTALL_DIR>/tools/cl_compiler/bin/`
* `SHAVE_MOVIASM_DIR=<INSTALL_DIR>/tools/cl_compiler/bin/` * `SHAVE_MOVIASM_DIR=<INSTALL_DIR>/tools/cl_compiler/bin/`
2. Run the compilation with the command below. You should use `--strip-binary-header` to make an OpenCL runtime-agnostic binary runnable with the Inference Engine. 2. Run the compilation with the command below. You should use `--strip-binary-header` to make an OpenCL runtime-agnostic binary runnable with the Inference Engine.
```bash ```bash
cd <INSTALL_DIR>/tools/cl_compiler/bin cd <INSTALL_DIR>/tools/cl_compiler/bin
./clc --strip-binary-header custom_layer.cl -o custom_layer.bin ./clc --strip-binary-header custom_layer.cl -o custom_layer.bin
``` ```
## Write a Configuration File ## Write a Configuration File
To tie the topology IR for a layer you customize, prepare a configuration file, so that the Inference Engine can find parameters for your kernel and the execution work grid is described. To tie the topology IR for a layer you customize, prepare a configuration file, so that the Inference Engine can find parameters for your kernel and the execution work grid is described.
For example, given the following OpenCL kernel signature: For example, consider the following OpenCL kernel signature:
```cpp ```cpp
__kernel void reorg_nhwc(__global const half *src, __global half *out, int w, int h, int c, int stride); __kernel void reorg_nhwc(__global const half *src, __global half *out, int w, int h, int c, int stride);
``` ```
Configuration file for this kernel might be the following: A configuration file for this kernel might be the following:
```xml ```xml
<CustomLayer name="ReorgYolo" type="MVCL" version="1"> <CustomLayer name="ReorgYolo" type="MVCL" version="1">
<Kernel entry="reorg_nhwc"> <Kernel entry="reorg_nhwc">
@ -62,7 +64,7 @@ Each custom layer is described with the `CustomLayer` node. It has the following
- Sub-node `Kernel` must contain the following attributes: - Sub-node `Kernel` must contain the following attributes:
- `entry` The name of your kernel function as you defined it in a source file. In the example above, it is `reorg_nhwc`. - `entry` The name of your kernel function as you defined it in a source file. In the example above, it is `reorg_nhwc`.
- Node `Source` must contain the following attributes: - Node `Source` must contain the following attributes:
- `filename` The path to a compiled binary relative to the `.xml` binding file. - `filename` The path to a compiled binary relative to the XML configuration file.
- Sub-node `Parameters` Describes parameters bindings. For more information, see the description below. - Sub-node `Parameters` Describes parameters bindings. For more information, see the description below.
- Sub-node `WorkSizes` Describes local and global work group sizes and the source for dimension deduction as a pair `direction,port`. In the example above, the work group is described relatively to the dimension of the input tensor that comes through port 0 in the IR. `global` and `local` work group configurations support any simple math expressions with +,-,\*,/, and () from `B`(batch), `Y`(height), `X`(width) and `F`(channels). - Sub-node `WorkSizes` Describes local and global work group sizes and the source for dimension deduction as a pair `direction,port`. In the example above, the work group is described relatively to the dimension of the input tensor that comes through port 0 in the IR. `global` and `local` work group configurations support any simple math expressions with +,-,\*,/, and () from `B`(batch), `Y`(height), `X`(width) and `F`(channels).
- Sub-node `Where` Allows to customize bindings with the `key="value"` attribute. For example, to substitute only 3x3 convolutions, write `<Where kernel="3,3"/>` in the binding xml. - Sub-node `Where` Allows to customize bindings with the `key="value"` attribute. For example, to substitute only 3x3 convolutions, write `<Where kernel="3,3"/>` in the binding xml.
@ -70,8 +72,8 @@ Each custom layer is described with the `CustomLayer` node. It has the following
Parameter description supports `Tensor` of one of tensor types such as `input`, `output`, `input_buffer`, `output_buffer` or `data`, `Scalar`, or `Data` nodes and has the following format: Parameter description supports `Tensor` of one of tensor types such as `input`, `output`, `input_buffer`, `output_buffer` or `data`, `Scalar`, or `Data` nodes and has the following format:
- Each `Tensor` node of `input` or `output` type must contain the following attributes: - Each `Tensor` node of `input` or `output` type must contain the following attributes:
- `arg-name` The name of a kernel parameter in the kernel signature. - `arg-name` The name of a kernel parameter in the kernel signature.
- `type` Node type: `input` or `output` as in the IR. - `type` Node type: `input` or `output` as specified in the IR.
- `port-index` A number of input/output ports as in the IR. - `port-index` A number of input/output ports as specified in the IR.
- `format` The channel order in the tensor. Optional conversion layers are generated if the custom layer format is not compatible with formats of neighboring layers. `BFXY`, `BYXF`, and `ANY` formats are supported currently. - `format` The channel order in the tensor. Optional conversion layers are generated if the custom layer format is not compatible with formats of neighboring layers. `BFXY`, `BYXF`, and `ANY` formats are supported currently.
- Each `Tensor` node of `input_buffer` or `output_buffer` type must contain the following attributes: - Each `Tensor` node of `input_buffer` or `output_buffer` type must contain the following attributes:
- `arg-name` The name of a kernel parameter in the kernel signature. - `arg-name` The name of a kernel parameter in the kernel signature.
@ -417,7 +419,7 @@ This decreases the execution time up to 40% against the best performing vectoriz
stalls completely on memory access without any prefetch. The same recommendation is applicable for scalar load/store stalls completely on memory access without any prefetch. The same recommendation is applicable for scalar load/store
from/to a `__blobal` pointer since work-group copying could be done in a vector fashion. from/to a `__blobal` pointer since work-group copying could be done in a vector fashion.
10. Use a manual DMA extension. Local (on-chip) memory throughput is up to 24x higher than DDR throughput. Starting from OpenVINO™ 2020.1, VPU OpenCL features manual-DMA kernel extension to copy sub-tensor used by work group into local memory and performing compute without DDR evolved. Here is the simple GRN kernel implementation that runs over DDR. Local size is equal to (width of the input tensor, 1, 1) to define a large enough work group to get code automatically vectorized and unrolled, while global size is (width of the input tensor, height of the input tensor, 1): 10. Use a manual DMA extension. Local (on-chip) memory throughput is up to 24x higher than DDR throughput. Starting from OpenVINO™ 2020.1, VPU OpenCL features manual-DMA kernel extension to copy sub-tensor used by work group into local memory and performing compute without DDR evolved. Here is the simple GRN kernel implementation that runs over DDR. Local size is in the form (width of the input tensor, 1, 1) to define a large enough work group to get code automatically vectorized and unrolled, while global size is (width of the input tensor, height of the input tensor, 1):
```cpp ```cpp
__kernel void grn_NCHW( __kernel void grn_NCHW(
__global const half* restrict src_data, __global const half* restrict src_data,
@ -444,7 +446,9 @@ from/to a `__blobal` pointer since work-group copying could be done in a vector
} }
} }
``` ```
This kernel can be rewritten to introduce special data binding `__dma_preload` and `__dma_postwrite intrinsics`. This means that instead of one kernel, a group of three kernels should be implemented: `kernelName`, `__dma_preload_kernelName`, and `__dma_postwrite_kernelName`. `__dma_preload_kernelName` for a particular work group `n` is guaranteed to be executed before the `n`-th work group itself, while `__dma_postwrite_kernelName` is guaranteed to be executed after a corresponding work group. You can define one of those functions that are intended to be used to copy data from-to `__global` and `__local` memory. The syntactics requires exact functional signature match. The example below illustrates how to prepare your kernel for manual-DMA. This kernel can be rewritten to introduce special data binding `__dma_preload` and `__dma_postwrite intrinsics`. This means that instead of one kernel, a group of three kernels should be implemented: `kernelName`, `__dma_preload_kernelName`, and `__dma_postwrite_kernelName`. `__dma_preload_kernelName` for a particular work group `n` is guaranteed to be executed before the `n`-th work group itself, while `__dma_postwrite_kernelName` is guaranteed to be executed after a corresponding work group. You can define one of those functions that are intended to be used to copy data from-to `__global` and `__local` memory. The syntactics requires exact functional signature match. The example below illustrates how to prepare your kernel for manual-DMA.
```cpp ```cpp
__kernel void __dma_preload_grn_NCHW( __kernel void __dma_preload_grn_NCHW(
__global const half* restrict src, __global const half* restrict src,
@ -453,7 +457,7 @@ This kernel can be rewritten to introduce special data binding `__dma_preload` a
__local half* restrict local_dst, __local half* restrict local_dst,
int C, int C,
float bias) float bias)
{ {
// ToDO: copy required piece of src tensor into local_src // ToDO: copy required piece of src tensor into local_src
} }
@ -478,9 +482,9 @@ This kernel can be rewritten to introduce special data binding `__dma_preload` a
{ {
// same as the example above // same as the example above
} }
``` ```
GRN kernel operates on channel-major tensors to compute average over full channel range and then normalizes input elements to produce the output. The GRN kernel operates on channel-major tensors to compute average over full channel range and then normalizes input elements to produce the output.
As a part of manual DMA extension, a group of work group copy functions are introduced in addition to `async_work_group_copy`, which is also mapped to DMA call. As a part of the manual DMA extension, a group of work group copy functions are introduced in addition to `async_work_group_copy`, which is also mapped to a DMA call.
Here is the list of supported functions: Here is the list of supported functions:
```cpp ```cpp
@ -613,7 +617,7 @@ __kernel void grn_NCHW(
Note the `get_local_size` and `get_local_id` usage inside the kernel. 21x speedup is expected for a kernel on enet-curbs setup because it was completely limited by memory usage. Note the `get_local_size` and `get_local_id` usage inside the kernel. 21x speedup is expected for a kernel on enet-curbs setup because it was completely limited by memory usage.
An alternative method of using DMA is to use work item copy extension. Those functions are executed inside a kernel and requires work groups equal to single work item. An alternative method to using DMA is to use work item copy extension. Those functions are executed inside a kernel and requires work groups equal to single work item.
Here is the list of supported work item functions: Here is the list of supported work item functions:
```cpp ```cpp

View File

@ -1,55 +1,62 @@
Introduction to Inference Engine Device Query API {#openvino_docs_IE_DG_InferenceEngine_QueryAPI} # Introduction to Inference Engine Device Query API {#openvino_docs_IE_DG_InferenceEngine_QueryAPI}
===============================
This section provides a high-level description of the process of querying of different device properties and configuration values. ## Inference Engine Query API (C++)
Refer to the [Hello Query Device Sample](../../samples/cpp/hello_query_device/README.md) sources and [Multi-Device Plugin guide](supported_plugins/MULTI.md) for example of using the Inference Engine Query API in user applications.
## Using the Inference Engine Query API in Your Code @sphinxdirective
.. raw:: html
The Inference Engine `Core` class provides the following API to query device information, set or get different device configuration properties: <div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
* <code>InferenceEngine::Core::GetAvailableDevices</code> - Provides a list of available devices. If there are more than one instance of a specific device, the devices are enumerated with `.suffix` where `suffix` is a unique string identifier. The device name can be passed to all methods of the `InferenceEngine::Core` class that work with devices, for example `InferenceEngine::Core::LoadNetwork`. The OpenVINO™ toolkit supports inferencing with several types of devices (processors or accelerators).
* <code>InferenceEngine::Core::GetMetric</code> - Provides information about specific device. This section provides a high-level description of the process of querying of different device properties and configuration values at runtime. Refer to the [Hello Query Device С++ Sample](../../samples/cpp/hello_query_device/README.md) sources and the [Multi-Device Plugin documentation](supported_plugins/MULTI.md) for examples of using the Inference Engine Query API in user applications.
<code>InferenceEngine::Core::GetConfig</code> - Gets the current value of a specific configuration key.
* <code>InferenceEngine::Core::SetConfig</code> - Sets a new value for the configuration key. ### Using the Inference Engine Query API in Your Code
The `InferenceEngine::Core` class provides the following API to query device information, set or get different device configuration properties:
* `InferenceEngine::Core::GetAvailableDevices` - Provides a list of available devices. If there are more than one instance of a specific device, the devices are enumerated with `.suffix` where `suffix` is a unique string identifier. The device name can be passed to all methods of the `InferenceEngine::Core` class that work with devices, for example `InferenceEngine::Core::LoadNetwork`.
* `InferenceEngine::Core::GetMetric` - Provides information about specific device.
`InferenceEngine::Core::GetConfig` - Gets the current value of a specific configuration key.
* `InferenceEngine::Core::SetConfig` - Sets a new value for the configuration key.
The `InferenceEngine::ExecutableNetwork` class is also extended to support the Query API: The `InferenceEngine::ExecutableNetwork` class is also extended to support the Query API:
* <code>InferenceEngine::ExecutableNetwork::GetMetric</code> * `InferenceEngine::ExecutableNetwork::GetMetric`
* <code>InferenceEngine::ExecutableNetwork::GetConfig</code> * `InferenceEngine::ExecutableNetwork::GetConfig`
* <code>InferenceEngine::ExecutableNetwork::SetConfig</code> * `InferenceEngine::ExecutableNetwork::SetConfig`
## Query API in the Core Class ### Query API in the Core Class
### GetAvailableDevices #### GetAvailableDevices
@snippet snippets/InferenceEngine_QueryAPI0.cpp part0 @snippet snippets/InferenceEngine_QueryAPI0.cpp part0
The function returns list of available devices, for example: The function returns a list of available devices, for example:
``` ```
MYRIAD.1.2-ma2480 MYRIAD.1.2-ma2480
MYRIAD.1.4-ma2480 MYRIAD.1.4-ma2480
CPU CPU
GPU.0 GPU.0
GPU.1 GPU.1
...
``` ```
Each device name can then be passed to: Each device name can then be passed to:
* `InferenceEngine::Core::LoadNetwork` to load the network to a specific device. * `InferenceEngine::Core::LoadNetwork` to load the network to a specific device.
* `InferenceEngine::Core::GetMetric` to get common or device specific metrics. * `InferenceEngine::Core::GetMetric` to get common or device specific metrics.
* All other methods of the `Core` class that accept `deviceName`. * All other methods of the `InferenceEngine::Core` class that accept `deviceName`.
### GetConfig() #### GetConfig()
The code below demonstrates how to understand whether `HETERO` device dumps `.dot` files with split graphs during the split stage: The code below demonstrates how to understand whether the `HETERO` device dumps GraphViz `.dot` files with split graphs during the split stage:
@snippet snippets/InferenceEngine_QueryAPI1.cpp part1 @snippet snippets/InferenceEngine_QueryAPI1.cpp part1
For documentation about common configuration keys, refer to `ie_plugin_config.hpp`. Device specific configuration keys can be found in corresponding plugin folders. For documentation about common configuration keys, refer to `ie_plugin_config.hpp`. Device specific configuration keys can be found in corresponding plugin folders.
### GetMetric() #### GetMetric()
* To extract device properties such as available device, device name, supported configuration keys, and others, use the `InferenceEngine::Core::GetMetric` method: * To extract device properties such as available device, device name, supported configuration keys, and others, use the `InferenceEngine::Core::GetMetric` method:
@ -57,26 +64,172 @@ For documentation about common configuration keys, refer to `ie_plugin_config.hp
A returned value appears as follows: `Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz`. A returned value appears as follows: `Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz`.
> **NOTE**: All metrics have specific type, which is specified during metric instantiation. The list of common device-agnostic metrics can be found in `ie_plugin_config.hpp`. Device specific metrics (for example, for `HDDL`, `MYRIAD` devices) can be found in corresponding plugin folders. > **NOTE**: All metrics have a type, which is specified during metric instantiation. The list of common device-agnostic metrics can be found in `ie_plugin_config.hpp`. Device specific metrics (for example, for HDDL or MYRIAD devices) can be found in corresponding plugin folders.
## Query API in the ExecutableNetwork Class ### Query API in the ExecutableNetwork Class
### GetMetric() #### GetMetric()
The method is used to get executable network specific metric such as `METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS)`: The method is used to get an executable network specific metric such as `METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS)`:
@snippet snippets/InferenceEngine_QueryAPI3.cpp part3 @snippet snippets/InferenceEngine_QueryAPI3.cpp part3
Or the current temperature of `MYRIAD` device: Or the current temperature of the `MYRIAD` device:
@snippet snippets/InferenceEngine_QueryAPI4.cpp part4 @snippet snippets/InferenceEngine_QueryAPI4.cpp part4
### GetConfig() #### GetConfig()
The method is used to get information about configuration values the executable network has been created with: The method is used to get information about configuration values the executable network has been created with:
@snippet snippets/InferenceEngine_QueryAPI5.cpp part5 @snippet snippets/InferenceEngine_QueryAPI5.cpp part5
### SetConfig() #### SetConfig()
The only device that supports this method is [Multi-Device](supported_plugins/MULTI.md). The only device that supports this method is [Multi-Device](supported_plugins/MULTI.md).
## Inference Engine Query API (Python)
@sphinxdirective
.. raw:: html
<div id="switcher-python" class="switcher-anchor">Python</div>
@endsphinxdirective
This section provides a high-level description of the process of querying of different device properties and configuration values. Refer to the [Hello Query Device Python Sample](../../inference-engine/ie_bridges/python/sample/hello_query_device/README.md) sources and the [Multi-Device Plugin documentation](supported_plugins/MULTI.md) for examples of using the Inference Engine Query API in user applications.
### Using the Inference Engine Query API in Your Code
The Inference Engine [Core](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino-inference-engine-iecore) class provides the following API to query device information, set or get different device configuration properties:
* [ie_api.IECore.available_devices](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.available_devices) - Provides a list of available devices. If there are more than one instance of a specific device, the devices are enumerated with .suffix where suffix is a unique string identifier. The device name can be passed to all methods of the IECore class that work with devices, for example [ie_api.IECore.load_network](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.load_network).
* [ie_api.ieCore.get_metric](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.get_metric) - Provides information about specific device.
* [ie_api.IECore.get_config](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.get_config) - Gets the current value of a specific configuration key.
* [ie_api.IECore.set_config](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.set_config) - Sets a new value for the configuration key.
The [ie_api.ExecutableNetwork](api/ie_python_api/_autosummary/openvino.inference_engine.ExecutableNetwork.html) class is also extended to support the Query API:
* [ie_api.ExecutableNetwork.get_metric](api/ie_python_api/_autosummary/openvino.inference_engine.ExecutableNetwork.html#openvino.inference_engine.ExecutableNetwork.get_metric)
* [ie_api.ExecutableNetwork.get_config](latest/api/ie_python_api/_autosummary/openvino.inference_engine.ExecutableNetwork.html#openvino.inference_engine.ExecutableNetwork.get_config)
* There is no method to call for set_config, but the equivalent action is described below.
### Query API in the IECore Class
#### Get Available Devices
```python
from openvino.inference_engine import IECore
ie = IECore()
print(ie.available_devices)
```
This code prints a list of available devices, for example:
```
MYRIAD.1.2-ma2480
MYRIAD.1.4-ma2480
FPGA.0
FPGA.1
CPU
GPU.0
GPU.1
```
Each device name can then be passed to:
* `IECore.load_network` to load the network to a specific device.
* `IECore.get_metric` to get common or device specific metrics.
* All other methods of the `IECore` class that accept a device name.
#### Get Metric
To extract device properties such as available device, device name, supported configuration keys, and others, use the [IECore.get_metric](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.get_metric) method:
```python
from openvino.inference_engine import IECore
ie = IECore()
ie.get_metric(device_name="CPU", metric_name="FULL_DEVICE_NAME")
```
A returned value appears as follows: `Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz`.
To list all supported metrics for a device:
```python
from openvino.inference_engine import IECore
ie = IECore()
ie.get_metric(device_name="GPU", metric_name="SUPPORTED_METRICS")
```
#### Get Configuration
The code below uses the [IECore.get_config](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.get_config) method and demonstrates how to understand whether the HETERO device dumps .dot files with split graphs during the split stage:
```python
from openvino.inference_engine import IECore
ie = IECore()
ie.get_config(device_name="HETERO", config_name="HETERO_DUMP_GRAPH_DOT")
```
To list all supported configuration keys for a device:
```python
from openvino.inference_engine import IECore
ie = IECore()
ie.get_metric(device_name=device, metric_name="SUPPORTED_CONFIG_KEYS")
```
For documentation about common configuration keys, refer to `ie_plugin_config.hpp`. Device specific configuration keys can be found in corresponding plugin folders.
### Query API in the ExecutableNetwork Class
#### Get Metric
To get the name of the loaded network:
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(model=path_to_xml_file)
exec_net = ie.load_network(network=net, device_name=device)
exec_net.get_metric("NETWORK_NAME")
```
Use `exec_net.get_metric("SUPPORTED_METRICS")` to list all supported metrics for an ExecutableNetwork instance.
#### Get Configuration
The [IECore.get_config](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.get_config) method is used to get information about configuration values the executable network has been created with:
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(model=path_to_xml_file)
exec_net = ie.load_network(network=net, device_name="CPU")
exec_net.get_config("CPU_THREADS_NUM")
```
Or the current temperature of MYRIAD device:
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(model=path_to_xml_file)
exec_net = ie.load_network(network=net, device_name="MYRIAD")
exec_net.get_config("DEVICE_THERMAL")
```
Use `exec_net.get_metric("SUPPORTED_CONFIG_KEYS")` to list all supported configuration keys.
#### Set Configuration
The only device that supports this method in the ExecutableNetwork class is the [Multi-Device](supported_plugins/MULTI.md), where you can change the priorities of the devices for the Multi plugin in real time: `exec_net.set_config({{"MULTI_DEVICE_PRIORITIES", "GPU,CPU"}})`. See the Multi-Device documentation for more details.

View File

@ -1,6 +1,6 @@
# Low-Precision 8-bit Integer Inference {#openvino_docs_IE_DG_Int8Inference} # Low-Precision 8-bit Integer Inference {#openvino_docs_IE_DG_Int8Inference}
## Supported devices ## Disclaimer
Low-precision 8-bit inference is optimized for: Low-precision 8-bit inference is optimized for:
- Intel® architecture processors with the following instruction set architecture extensions: - Intel® architecture processors with the following instruction set architecture extensions:
@ -11,43 +11,57 @@ Low-precision 8-bit inference is optimized for:
- Intel® processor graphics: - Intel® processor graphics:
- Intel® Iris® Xe Graphics - Intel® Iris® Xe Graphics
- Intel® Iris® Xe MAX Graphics - Intel® Iris® Xe MAX Graphics
- A model must be quantized. You can use a quantized model from [OpenVINO™ Toolkit Intel's Pre-Trained Models](@ref omz_models_group_intel) or quantize a model yourself. For quantization, you can use the:
- [Post-Training Optimization Tool](@ref pot_docs_LowPrecisionOptimizationGuide) delivered with the Intel® Distribution of OpenVINO™ toolkit release package.
- [Neural Network Compression Framework](https://www.intel.com/content/www/us/en/artificial-intelligence/posts/openvino-nncf.html) available on GitHub: https://github.com/openvinotoolkit/nncf
## Low-Precision 8-bit Integer Inference Workflow ## Introduction
8-bit computations (referred to as `int8`) offer better performance compared to the results of inference in higher precision (for example, `fp32`), because they allow loading more data into a single processor instruction. Usually the cost for significant boost is reduced accuracy. However, it is proved that an accuracy drop can be negligible and depends on task requirements, so that the application engineer can set up the maximum accuracy drop that is acceptable. For 8-bit integer computation, a model must be quantized. You can use a quantized model from [OpenVINO™ Toolkit Intel's Pre-Trained Models](@ref omz_models_group_intel) or quantize a model yourself. For quantization, you can use the following:
- [Post-Training Optimization Tool](@ref pot_docs_LowPrecisionOptimizationGuide) delivered with the Intel® Distribution of OpenVINO™ toolkit release package
- [Neural Network Compression Framework](https://www.intel.com/content/www/us/en/artificial-intelligence/posts/openvino-nncf.html) available on GitHub: https://github.com/openvinotoolkit/nncf
For 8-bit integer computations, a model must be quantized. Quantized models can be downloaded from [Overview of OpenVINO™ Toolkit Intel's Pre-Trained Models](@ref omz_models_group_intel). If the model is not quantized, you can use the [Post-Training Optimization Tool](@ref pot_README) to quantize the model. The quantization process adds [FakeQuantize](../ops/quantization/FakeQuantize_1.md) layers on activations and weights for most layers. Read more about mathematical computations in the [Uniform Quantization with Fine-Tuning](https://github.com/openvinotoolkit/nncf/blob/develop/docs/compression_algorithms/Quantization.md). The quantization process adds [FakeQuantize](../ops/quantization/FakeQuantize_1.md) layers on activations and weights for most layers. Read more about mathematical computations in the [Uniform Quantization with Fine-Tuning](https://github.com/openvinotoolkit/nncf/blob/develop/docs/compression_algorithms/Quantization.md).
When you pass the quantized IR to the OpenVINO™ plugin, the plugin automatically recognizes it as a quantized model and performs 8-bit inference. Note, if you pass a quantized model to another plugin that does not support 8-bit inference but supports all operations from the model, the model is inferred in precision that this plugin supports. When you pass the quantized IR to the OpenVINO™ plugin, the plugin automatically recognizes it as a quantized model and performs 8-bit inference. Note that if you pass a quantized model to another plugin that does not support 8-bit inference but supports all operations from the model, the model is inferred in precision that this plugin supports.
In *Runtime stage*, the quantized model is loaded to the plugin. The plugin uses the `Low Precision Transformation` component to update the model to infer it in low precision: At runtime, the quantized model is loaded to the plugin. The plugin uses the `Low Precision Transformation` component to update the model to infer it in low precision:
- Update `FakeQuantize` layers to have quantized output tensors in a low precision range and add dequantization layers to compensate the update. Dequantization layers are pushed through as many layers as possible to have more layers in low precision. After that, most layers quantized input tensors in the low precision range and can be inferred in low precision. Ideally, dequantization layers should be fused in the next `FakeQuantize` layer. - Update `FakeQuantize` layers to have quantized output tensors in low-precision range and add dequantization layers to compensate for the update. Dequantization layers are pushed through as many layers as possible to have more layers in low precision. After that, most layers have quantized input tensors in low-precision range and can be inferred in low precision. Ideally, dequantization layers should be fused in the next `FakeQuantize` layer.
- Quantize weights and store them in `Constant` layers. - Weights are quantized and stored in `Constant` layers.
## Prerequisites ## Prerequisites
Let's explore the quantized [TensorFlow* implementation of ResNet-50](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/resnet-50-tf) model. Use the [Model Downloader](@ref omz_tools_downloader) tool to download the `fp16` model from [OpenVINO™ Toolkit - Open Model Zoo repository](https://github.com/openvinotoolkit/open_model_zoo): Let's explore quantized [TensorFlow* implementation of the ResNet-50](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/resnet-50-tf) model. Use [Model Downloader](@ref omz_tools_downloader) to download the `FP16` model from [OpenVINO™ Toolkit - Open Model Zoo repository](https://github.com/openvinotoolkit/open_model_zoo):
> **NOTE**: If you installed OpenVINO with pip, use `omz_downloader` and `omz_quantizer` instead of `download.py` and `quantize.py`. See [Open Model Zoo documentation](https://github.com/openvinotoolkit/open_model_zoo/tree/master/tools/model_tools#model-downloader-usage). Replace `./benchmark_app` with `benchmark_app`.
```sh ```sh
cd $INTEL_OPENVINO_DIR/deployment_tools/tools/model_downloader <omz_dir>/tools/downloader/downloader.py --name resnet-50-tf --precisions FP16-INT8
./downloader.py --name resnet-50-tf --precisions FP16-INT8 --output_dir <your_model_directory>
``` ```
After that, you should quantize the model by the [Model Quantizer](@ref omz_tools_downloader) tool. For the dataset, you can choose to download the ImageNet dataset from [here](https://www.image-net.org/download.php). After that you should quantize the model with the [Model Quantizer](@ref omz_tools_downloader) tool.
```sh ```sh
./quantizer.py --model_dir --name public/resnet-50-tf --dataset_dir <DATASET_DIR> --precisions=FP16-INT8 <omz_dir>/tools/downloader/quantizer.py --model_dir public/resnet-50-tf --dataset_dir <DATASET_DIR> --precisions=FP16-INT8
``` ```
## Inference The simplest way to infer the model and collect performance counters is the [Benchmark Application](../../samples/cpp/benchmark_app/README.md):
The simplest way to infer the model and collect performance counters is the [C++ Benchmark Application](../../samples/cpp/benchmark_app/README.md).
```sh ```sh
./benchmark_app -m resnet-50-tf.xml -d CPU -niter 1 -api sync -report_type average_counters -report_folder pc_report_dir ./benchmark_app -m resnet-50-tf.xml -d CPU -niter 1 -api sync -report_type average_counters -report_folder pc_report_dir
``` ```
If you infer the model with the Inference Engine CPU plugin and collect performance counters, all operations (except the last non-quantized SoftMax) are executed in INT8 precision. If you infer the model with the OpenVINO™ CPU plugin and collect performance counters, all operations (except the last non-quantized SoftMax) are executed in INT8 precision.
## Results analysis ## Low-Precision 8-bit Integer Inference Workflow
For 8-bit integer computations, a model must be quantized. Quantized models can be downloaded from [Overview of OpenVINO™ Toolkit Intel's Pre-Trained Models](@ref omz_models_group_intel). If the model is not quantized, you can use the [Post-Training Optimization Tool](@ref pot_README) to quantize the model. The quantization process adds [FakeQuantize](../ops/quantization/FakeQuantize_1.md) layers on activations and weights for most layers. Read more about mathematical computations in the [Uniform Quantization with Fine-Tuning](https://github.com/openvinotoolkit/nncf/blob/develop/docs/compression_algorithms/Quantization.md).
8-bit inference pipeline includes two stages (also refer to the figure below):
1. *Offline stage*, or *model quantization*. During this stage, [FakeQuantize](../ops/quantization/FakeQuantize_1.md) layers are added before most layers to have quantized tensors before layers in a way that low-precision accuracy drop for 8-bit integer inference satisfies the specified threshold. The output of this stage is a quantized model. Quantized model precision is not changed, quantized tensors are in original precision range (`fp32`). `FakeQuantize` layer has `levels` attribute which defines quants count. Quants count defines precision which is used during inference. For `int8` range `levels` attribute value has to be 255 or 256. To quantize the model, you can use the [Post-Training Optimization Tool](@ref pot_README) delivered with the Intel® Distribution of OpenVINO™ toolkit release package.
When you pass the quantized IR to the OpenVINO™ plugin, the plugin automatically recognizes it as a quantized model and performs 8-bit inference. Note, if you pass a quantized model to another plugin that does not support 8-bit inference but supports all operations from the model, the model is inferred in precision that this plugin supports.
2. *Runtime stage*. This stage is an internal procedure of the OpenVINO™ plugin. During this stage, the quantized model is loaded to the plugin. The plugin uses `Low Precision Transformation` component to update the model to infer it in low precision:
- Update `FakeQuantize` layers to have quantized output tensors in low precision range and add dequantization layers to compensate the update. Dequantization layers are pushed through as many layers as possible to have more layers in low precision. After that, most layers have quantized input tensors in low precision range and can be inferred in low precision. Ideally, dequantization layers should be fused in the next `FakeQuantize` layer.
- Weights are quantized and stored in `Constant` layers.
![int8_flow]
## Performance Counters
Information about layer precision is stored in the performance counters that are Information about layer precision is stored in the performance counters that are
available from the Inference Engine API. For example, the part of performance counters table for quantized [TensorFlow* implementation of ResNet-50](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/resnet-50-tf) model inference on [CPU Plugin](supported_plugins/CPU.md) looks as follows: available from the Inference Engine API. For example, the part of performance counters table for quantized [TensorFlow* implementation of ResNet-50](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/resnet-50-tf) model inference on [CPU Plugin](supported_plugins/CPU.md) looks as follows:
@ -65,12 +79,12 @@ available from the Inference Engine API. For example, the part of performance co
| resnet\_model/add\_5/fq\_input\_1 | NOT\_RUN | FakeQuantize | undef | 0 | 0 | | resnet\_model/add\_5/fq\_input\_1 | NOT\_RUN | FakeQuantize | undef | 0 | 0 |
> The `exeStatus` column of the table includes possible values: The `exeStatus` column of the table includes possible values:
> - `EXECUTED` - layer was executed by standalone primitive, - `EXECUTED` - layer was executed by standalone primitive,
> - `NOT_RUN` - layer was not executed by standalone primitive or was fused with another operation and executed in another layer primitive. - `NOT_RUN` - layer was not executed by standalone primitive or was fused with another operation and executed in another layer primitive.
>
> The `execType` column of the table includes inference primitives with specific suffixes. The layers have the following marks: The `execType` column of the table includes inference primitives with specific suffixes. The layers have the following marks:
> * Suffix `I8` for layers that had 8-bit data type input and were computed in 8-bit precision * Suffix `I8` for layers that had 8-bit data type input and were computed in 8-bit precision
> * Suffix `FP32` for layers computed in 32-bit precision * Suffix `FP32` for layers computed in 32-bit precision
All `Convolution` layers are executed in int8 precision. Rest layers are fused into Convolutions using post operations optimization technique, which is described in [Internal CPU Plugin Optimizations](supported_plugins/CPU.md). All `Convolution` layers are executed in int8 precision. Rest layers are fused into Convolutions using post operations optimization technique, which is described in [Internal CPU Plugin Optimizations](supported_plugins/CPU.md).

View File

@ -1,131 +1,252 @@
Integrate the Inference Engine with Your Application {#openvino_docs_IE_DG_Integrate_with_customer_application_new_API} # Integrate Inference Engine {#openvino_docs_IE_DG_Integrate_with_customer_application_new_API}
===============================
This section provides a high-level description of the process of integrating the Inference Engine into your application. ## Integrate Inference Engine with Your C++ Application
Refer to the [Hello Classification Sample](../../samples/cpp/hello_classification/README.md) sources
for example of using the Inference Engine in applications.
## Use the Inference Engine API in Your Code @sphinxdirective
.. raw:: html
The core `libinference_engine.so` library implements loading and parsing a model Intermediate Representation (IR), and triggers inference using a specified device. The core library has the following API: <div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
* `InferenceEngine::Core` The following diagram illustrates the typical Inference Engine С++ API workflow:
* `InferenceEngine::Blob`, `InferenceEngine::TBlob`,
`InferenceEngine::NV12Blob`
* `InferenceEngine::BlobMap`
* `InferenceEngine::InputsDataMap`, `InferenceEngine::InputInfo`,
* `InferenceEngine::OutputsDataMap`
C++ Inference Engine API wraps the capabilities of core library: ![ie_api_flow_cpp]
* `InferenceEngine::CNNNetwork` Read the sections below to learn about each item.
* `InferenceEngine::ExecutableNetwork`
* `InferenceEngine::InferRequest`
## Integration Steps > **NOTE**: Before start using Inference Engine, make sure you set all environment variables during the installation. If you did not, follow the instructions from the _Set the Environment Variables_ section in the installation guides:
> * [For Windows* 10](../install_guides/installing-openvino-windows.md)
> * [For Linux*](../install_guides/installing-openvino-linux.md)
> * [For macOS*](../install_guides/installing-openvino-macos.md)
> * To build an open source version, use the [Inference Engine Build Instructions](https://github.com/openvinotoolkit/openvino/wiki/BuildingCode).
Integration process includes the following steps: ### Link with Inference Library
![integration_process]
1) **Create Inference Engine Core** to manage available devices and read network objects: 1. **Create a structure** for the project:
``` sh
project/
├── CMakeLists.txt - CMake file to build
├── ... - Additional folders like includes/
└── src/ - source folder
└── main.cpp
build/ - build directory
...
```
2. **Include Inference Engine, nGraph and OpenCV libraries** in `project/CMakeLists.txt`
[OpenCV](https://docs.opencv.org/master/db/df5/tutorial_linux_gcc_cmake.html) integration is needed mostly for pre-processing input data and nGraph for more complex applications using [nGraph API](../nGraph_DG/nGraph_dg.md).
``` cmake
cmake_minimum_required(VERSION 3.0.0)
project(project_name)
find_package(ngraph REQUIRED)
find_package(InferenceEngine REQUIRED)
find_package(OpenCV REQUIRED)
add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE ${InferenceEngine_LIBRARIES} ${OpenCV_LIBS} ${NGRAPH_LIBRARIES})
```
### Use Inference Engine API to Implement Inference Pipeline
This section provides step-by-step instructions to implement a typical inference pipeline with the Inference Engine C++ API:
![ie_api_use_cpp]
#### Step 1. Create Inference Engine Core
Use the following code to create Inference Engine Core to manage available devices and read network objects:
@snippet snippets/Integrate_with_customer_application_new_API.cpp part0 @snippet snippets/Integrate_with_customer_application_new_API.cpp part0
2) **Read a model IR** created by the Model Optimizer (.xml is supported format): #### Step 2 (Optional). Configure Input and Output of the Model
@snippet snippets/Integrate_with_customer_application_new_API.cpp part1 @sphinxdirective
.. raw:: html
**Or read the model from ONNX format**. You can find more information about the ONNX format support in the document [ONNX format support in the OpenVINO™](./ONNX_Support.md). <div class="collapsible-section">
@endsphinxdirective
@snippet snippets/Integrate_with_customer_application_new_API.cpp part2 Optionally, configure input and output of the model using the steps below:
3) **Configure input and output**. Request input and output information using `InferenceEngine::CNNNetwork::getInputsInfo()`, and `InferenceEngine::CNNNetwork::getOutputsInfo()` 1. Load a model to a Core object:
methods: @sphinxdirective
.. tab:: IR
.. code-block:: c
auto network = core.ReadNetwork("model.xml");
@snippet snippets/Integrate_with_customer_application_new_API.cpp part3 .. tab:: ONNX
.. code-block:: c
auto network = core.ReadNetwork("model.onnx");
Optionally, set the number format (precision) and memory layout for inputs and outputs. Refer to the You can find more information about the ONNX format support in the document `ONNX format support in the OpenVINO™ <https://docs.openvinotoolkit.org/latest/openvino_docs_IE_DG_ONNX_Support.html>`_
[Supported configurations](supported_plugins/Supported_Devices.md) chapter to choose the relevant configuration.
.. tab:: nGraph
.. code-block:: c
std::shared_ptr<Function> createNetwork() {
// To construct a network, please follow
// https://docs.openvinotoolkit.org/latest/openvino_docs_nGraph_DG_build_function.html
}
auto network = CNNNetwork(createNetwork());
You can also allow input of any size. To do this, mark each input as resizable by setting a desired resize algorithm (e.g. `BILINEAR`) inside of the appropriate input info. @endsphinxdirective
Basic color format conversions are supported as well. By default, the Inference Engine assumes 2. Request input and output information using `InferenceEngine::CNNNetwork::getInputsInfo()`, and `InferenceEngine::CNNNetwork::getOutputsInfo()` methods:
that the input color format is `BGR` and color format conversions are disabled. The Inference ```cpp
Engine supports the following color format conversions: /** Take information about all topology inputs **/
* `RGB->BGR` InferenceEngine::InputsDataMap input_info = network.getInputsInfo();
* `RGBX->BGR` /** Iterate over all input info**/
* `BGRX->BGR` for (auto &item : input_info) {
* `NV12->BGR` auto input_data = item.second;
// Add your input configuration steps here
}
/** Take information about all topology outputs **/
InferenceEngine::OutputsDataMap output_info = network.getOutputsInfo();
/** Iterate over all output info**/
for (auto &item : output_info) {
auto output_data = item.second;
// Add your output configuration steps here
}
```
Configuring options:
1. **Set precision** (number format): FP16, FP32, INT8, etc. Refer to the Supported Configurations section on the [Supported Devices](supported_plugins/Supported_Devices.md) page to choose the relevant configuration.<br>
For input (*iterate over all input info*):
```cpp
input_data->setPrecision(InferenceEngine::Precision::U8);
```
For output (*iterate over all output info*):
```cpp
output_data->setPrecision(InferenceEngine::Precision::FP32);
```
**By default**, the input and output precision is set to `Precision::FP32`.
where `X` is a channel that will be ignored during inference. To enable the conversions, set a 2. **Set layout** (NCHW, ).<br>
desired color format (for example, `RGB`) for each input inside of the appropriate input info. For input (*iterate over all input info*):
```cpp
input_data->setLayout(InferenceEngine::Layout::NCHW);
```
**By default**, the input layout is set to `Layout::NCHW`.<br>
For output (*iterate over all output info*):
```cpp
output_data->setLayout(InferenceEngine::Layout::NC);
```
**By default**, the output layout depends on a number of its dimensions:<br>
|Number of dimensions | 5 | 4 | 3 | 2 | 1 |
|:--------------------|-------|------|-----|----|----|
|Layout | NCDHW | NCHW | CHW | NC | C |
3. **Set resize algorithm for inputs** (Bilinear). You can allow input of any size. To do this, mark each input as resizable by setting a desired resize algorithm (e.g. `BILINEAR`) inside of the appropriate input info (*Iterate over all input info*):
```cpp
input_data->getPreProcess().setResizeAlgorithm(InferenceEngine::RESIZE_BILINEAR);
```
**By default**, no resize algorithm is set for inputs.
If you want to run inference for multiple images at once, you can use the built-in batch 4. **Set color format** (BGR, RGB, NV12). Basic color format conversions are supported as well. **By default**, the Inference Engine assumes that the input color format is BGR and color format conversions are disabled. Set `ColorFormat::RAW` input color format if the input does not need color conversions. The Inference Engine supports the following color format conversions:
pre-processing functionality. * RGB->BGR
* RGBX->BGR
* BGRX->BGR
* NV12->BGR
where X is a channel that will be ignored during inference. To enable the conversions, set a desired color format (for example, RGB) for each input inside of the appropriate input info (*iterate over all input info*):
```cpp
input_data->getPreProcess().setColorFormat(InferenceEngine::ColorFormat::RGB);
```
> **NOTE**: NV12 input color format pre-processing differs from other color conversions. In case of NV12, Inference Engine expects two separate image planes (Y and UV). You must use a specific `InferenceEngine::NV12Blob` object instead of default blob object and set this blob to the Inference Engine Infer Request using `InferenceEngine::InferRequest::SetBlob()`. Refer to [Hello NV12 Input Classification C++ Sample](../../samples/cpp/hello_nv12_input_classification/README.md) for more details.
5. **Run on multiple images** with setting batch. If you want to run inference for multiple images at once, you can use the built-in batch pre-processing functionality.
**NOTE** : Batch pre-processing is not supported if input color format is set to `ColorFormat::NV12`.
> **NOTE**: Batch pre-processing is not supported if input color format is set to `ColorFormat::NV12`. @sphinxdirective
.. raw:: html
You can use the following code snippet to configure input and output: </div>
@endsphinxdirective
@snippet snippets/Integrate_with_customer_application_new_API.cpp part4 #### Step 3. Load the Model to the Device
> **NOTE**: NV12 input color format pre-processing differs from other color conversions. In case of NV12, Load the model to the device using `InferenceEngine::Core::LoadNetwork()`:
> Inference Engine expects two separate image planes (Y and UV). You must use a specific
> `InferenceEngine::NV12Blob` object instead of default blob object and set this blob to
> the Inference Engine Infer Request using `InferenceEngine::InferRequest::SetBlob()`.
> Refer to [Hello NV12 Input Classification C++ Sample](../../samples/cpp/hello_nv12_input_classification/README.md)
> for more details.
If you skip this step, the default values are set:
* no resize algorithm is set for inputs @sphinxdirective
* input color format - `ColorFormat::RAW` meaning that input does not need color
conversions .. tab:: IR
* input and output precision - `Precision::FP32`
* input layout - `Layout::NCHW`
* output layout depends on number of its dimensions:
|Number of dimensions | 5 | 4 | 3 | 2 | 1 | .. code-block:: c
|:--------------------|-------|------|-----|----|----|
|Layout | NCDHW | NCHW | CHW | NC | C |
4) **Load the model** to the device using `InferenceEngine::Core::LoadNetwork()`: executable_network = core.LoadNetwork("model.xml", "CPU");
@snippet snippets/Integrate_with_customer_application_new_API.cpp part5 .. tab:: ONNX
It creates an executable network from a network object. The executable network is associated with single hardware device. .. code-block:: c
It is possible to create as many networks as needed and to use them simultaneously (up to the limitation of the hardware resources).
Third parameter is a configuration for plugin. It is map of pairs: (parameter name, parameter value). Choose device from executable_network = core.LoadNetwork("model.onnx", "CPU");
[Supported devices](supported_plugins/Supported_Devices.md) page for more details about supported configuration parameters.
.. tab:: nGraph
.. code-block:: c
std::shared_ptr<Function> createNetwork() {
// To construct a network, please follow
// https://docs.openvinotoolkit.org/latest/openvino_docs_nGraph_DG_build_function.html
}
auto network = CNNNetwork(createNetwork());
executable_network = core.LoadNetwork(network, "CPU");
.. tab:: Model From Step 2
Follow this step only if you went through optional "Step 2 (Optional). Configure Input and Output of the Model", otherwise use another tab for your model type: IR (OpenVINO Intermediate Representation), ONNX or nGraph.
.. code-block:: c
executable_network = core.LoadNetwork(network, "CPU");
@endsphinxdirective
It creates an executable network from a network object. The executable network is associated with single hardware device.
It is possible to create as many networks as needed and to use them simultaneously (up to the limitation of the hardware resources).
Third parameter is a configuration for plugin. It is map of pairs: (parameter name, parameter value). Choose device from
[Supported devices](supported_plugins/Supported_Devices.md) page for more details about supported configuration parameters.
@snippet snippets/Integrate_with_customer_application_new_API.cpp part6 @snippet snippets/Integrate_with_customer_application_new_API.cpp part6
5) **Create an infer request**: #### Step 4. Create an Inference Request
Create an infer request using the following code:
@snippet snippets/Integrate_with_customer_application_new_API.cpp part7 @snippet snippets/Integrate_with_customer_application_new_API.cpp part7
6) **Prepare input**. You can use one of the following options to prepare input: #### Step 5. Prepare Input
* **Optimal way for a single network.** Get blobs allocated by an infer request using `InferenceEngine::InferRequest::GetBlob()` and feed an image and the input data to the blobs. In this case, input data must be aligned (resized manually) with a given blob size and have a correct color format.
@snippet snippets/Integrate_with_customer_application_new_API.cpp part8 You can use one of the following options to prepare input:
* **Optimal way for a cascade of networks (output of one network is input for another).** Get output blob from the first request using `InferenceEngine::InferRequest::GetBlob()` and set it as input for the second request using `InferenceEngine::InferRequest::SetBlob()`. * **Optimal way for a single network.** Get blobs allocated by an infer request using `InferenceEngine::InferRequest::GetBlob()` and feed an image and the input data to the blobs. In this case, input data must be aligned (resized manually) with a given blob size and have a correct color format.
@snippet snippets/Integrate_with_customer_application_new_API.cpp part9 @snippet snippets/Integrate_with_customer_application_new_API.cpp part8
* **Optimal way to handle ROI (a ROI object located inside of input of one network is input for another).** It is possible to re-use shared input by several networks. You do not need to allocate separate input blob for a network if it processes a ROI object located inside of already allocated input of a previous network. For instance, when first network detects objects on a video frame (stored as input blob) and second network accepts detected bounding boxes (ROI inside of the frame) as input. In this case, it is allowed to re-use pre-allocated input blob (used by first network) by second network and just crop ROI without allocation of new memory using `InferenceEngine::make_shared_blob()` with passing of `InferenceEngine::Blob::Ptr` and `InferenceEngine::ROI` as parameters. * **Optimal way for a cascade of networks (output of one network is input for another).** Get output blob from the first request using `InferenceEngine::InferRequest::GetBlob()` and set it as input for the second request using `InferenceEngine::InferRequest::SetBlob()`.
@snippet snippets/Integrate_with_customer_application_new_API.cpp part10 @snippet snippets/Integrate_with_customer_application_new_API.cpp part9
Make sure that shared input is kept valid during execution of each network. Otherwise, ROI blob may be corrupted if the original input blob (that ROI is cropped from) has already been rewritten. * **Optimal way to handle ROI (a ROI object located inside of input of one network is input for another).** It is possible to re-use shared input by several networks. You do not need to allocate separate input blob for a network if it processes a ROI object located inside of already allocated input of a previous network. For instance, when first network detects objects on a video frame (stored as input blob) and second network accepts detected bounding boxes (ROI inside of the frame) as input. In this case, it is allowed to re-use pre-allocated input blob (used by first network) by second network and just crop ROI without allocation of new memory using `InferenceEngine::make_shared_blob()` with passing of `InferenceEngine::Blob::Ptr` and `InferenceEngine::ROI` as parameters.
* Allocate input blobs of the appropriate types and sizes, feed an image and the input data to the blobs, and call `InferenceEngine::InferRequest::SetBlob()` to set these blobs for an infer request: @snippet snippets/Integrate_with_customer_application_new_API.cpp part10
@snippet snippets/Integrate_with_customer_application_new_API.cpp part11 Make sure that shared input is kept valid during execution of each network. Otherwise, ROI blob may be corrupted if the original input blob (that ROI is cropped from) has already been rewritten.
A blob can be filled before and after `SetBlob()`. * Allocate input blobs of the appropriate types and sizes, feed an image and the input data to the blobs, and call `InferenceEngine::InferRequest::SetBlob()` to set these blobs for an infer request:
> **NOTE:** @snippet snippets/Integrate_with_customer_application_new_API.cpp part11
A blob can be filled before and after `SetBlob()`.
> **NOTE**:
> >
> * The `SetBlob()` method compares precision and layout of an input blob with the ones defined in step 3 and > * The `SetBlob()` method compares precision and layout of an input blob with the ones defined in step 3 and
> throws an exception if they do not match. It also compares a size of the input blob with input > throws an exception if they do not match. It also compares a size of the input blob with input
@ -141,22 +262,28 @@ Make sure that shared input is kept valid during execution of each network. Othe
> corresponding values of the read network. No pre-processing will happen for this blob. If you > corresponding values of the read network. No pre-processing will happen for this blob. If you
> call `GetBlob()` after `SetBlob()`, you will get the blob you set in `SetBlob()`. > call `GetBlob()` after `SetBlob()`, you will get the blob you set in `SetBlob()`.
7) **Do inference** by calling the `InferenceEngine::InferRequest::StartAsync` and `InferenceEngine::InferRequest::Wait` methods for asynchronous request: #### Step 6. Start Inference
@snippet snippets/Integrate_with_customer_application_new_API.cpp part12 Start inference in asynchronous or synchronous mode. Async API usage can improve overall frame-rate of the application, because rather than wait for inference to complete, the app can continue doing things on the host, while accelerator is busy.
or by calling the `InferenceEngine::InferRequest::Infer` method for synchronous request: * For synchronous inference request:
```cpp
infer_request.Infer();
```
@snippet snippets/Integrate_with_customer_application_new_API.cpp part13 * For asynchronous inference request:
```cpp
infer_request.StartAsync();
infer_request.Wait(InferenceEngine::InferRequest::WaitMode::RESULT_READY);
```
`StartAsync` returns immediately and starts inference without blocking main thread, `Infer` blocks main thread and returns when inference is completed. Call `Wait` for waiting result to become available for asynchronous request.
`StartAsync` returns immediately and starts inference without blocking main thread, `Infer` blocks There are three ways to use it:
main thread and returns when inference is completed. Call `Wait` for waiting result to become available for asynchronous request. * specify maximum duration in milliseconds to block for. The method is blocked until the specified timeout has elapsed, or the result becomes available, whichever comes first.
* `InferenceEngine::InferRequest::WaitMode::RESULT_READY` - waits until inference result becomes available
There are three ways to use it: * `InferenceEngine::InferRequest::WaitMode::STATUS_ONLY` - immediately returns request status.It does not
* specify maximum duration in milliseconds to block for. The method is blocked until the specified timeout has elapsed, or the result becomes available, whichever comes first. block or interrupts current thread.
* `InferenceEngine::InferRequest::WaitMode::RESULT_READY` - waits until inference result becomes available
* `InferenceEngine::InferRequest::WaitMode::STATUS_ONLY` - immediately returns request status.It does not
block or interrupts current thread.
Both requests are thread-safe: can be called from different threads without fearing corruption and failures. Both requests are thread-safe: can be called from different threads without fearing corruption and failures.
@ -165,41 +292,21 @@ Multiple requests for single `ExecutableNetwork` are executed sequentially one b
While request is ongoing, all its methods except `InferenceEngine::InferRequest::Wait` would throw an While request is ongoing, all its methods except `InferenceEngine::InferRequest::Wait` would throw an
exception. exception.
8) Go over the output blobs and **process the results**. #### Step 7. Process the Inference Results
Note that casting `Blob` to `TBlob` via `std::dynamic_pointer_cast` is not the recommended way. It's better to access data via the `buffer()` and `as()` methods as follows:
Go over the output blobs and process the inference results. Note that casting `Blob` to `TBlob` via `std::dynamic_pointer_cast` is not the recommended way. It's better to access data via the `buffer()` and `as()` methods as follows:
@snippet snippets/Integrate_with_customer_application_new_API.cpp part14 @snippet snippets/Integrate_with_customer_application_new_API.cpp part14
## Build Your Application ### Build Your Application
For details about building your application, refer to the CMake files for the sample applications. For details about building your application, refer to the CMake files for the sample applications.
All samples source code is located in the `<INSTALL_DIR>/samples` directory, where `INSTALL_DIR` is the OpenVINO™ installation directory. All samples source code is located in the `<INSTALL_DIR>/samples` directory, where `INSTALL_DIR` is the OpenVINO™ installation directory.
### CMake project creation To build your project using CMake with the default build tools currently available on your machine, execute the following commands:
1. **Create a structure** for the project: > **NOTE**: Make sure you set environment variables first by running `<INSTALL_DIR>/setupvars.sh` (or `setupvars.bat` for Windows). Otherwise the `InferenceEngine_DIR` and `OpenCV_DIR` variables won't be configured properly to pass `find_package` calls.
``` sh
project/
├── CMakeLists.txt - CMake file to build
├── ... - Additional folders like includes/
└── src/ - source folder
└── main.cpp
build/ - build directory
...
```
2. **Include Inference Engine, nGraph and OpenCV libraries** in `project/CMakeLists.txt`
[OpenCV](https://docs.opencv.org/master/db/df5/tutorial_linux_gcc_cmake.html) integration is needed mostly for pre-processing input data and ngraph for more complex applications using [ngraph API](../nGraph_DG/nGraph_dg.md).
``` cmake
cmake_minimum_required(VERSION 3.0.0)
project(project_name)
find_package(OpenVINO REQUIRED)
find_package(OpenCV REQUIRED)
add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE openvino::runtime ${OpenCV_LIBS})
```
3. **To build your project** using CMake with the default build tools currently available on your machine, execute the following commands:
> **NOTE**: Make sure you set environment variables first by running `<INSTALL_DIR>/setupvars.sh` (or setupvars.bat for Windows)`. Otherwise the `InferenceEngine_DIR` and `OpenCV_DIR` variables won't be configured properly to pass `find_package` calls.
```sh ```sh
cd build/ cd build/
cmake ../project cmake ../project
@ -209,6 +316,179 @@ It's allowed to specify additional build options (e.g. to build CMake project on
### Run Your Application ### Run Your Application
Before running, make sure you completed **Set the Environment Variables** section in [OpenVINO Installation](../../samples/cpp/hello_nv12_input_classification/README.md) document so that the application can find the libraries. > **NOTE**: Before running, make sure you completed **Set the Environment Variables** section in [OpenVINO Installation](../../samples/cpp/hello_nv12_input_classification/README.md) document so that the application can find the libraries.
[integration_process]: img/integration_process.png To run compiled applications on Microsoft* Windows* OS, make sure that Microsoft* Visual C++ 2017
Redistributable and Intel® C++ Compiler 2017 Redistributable packages are installed and
`<INSTALL_DIR>/bin/intel64/Release/*.dll` files are placed to the
application folder or accessible via `%PATH%` environment variable.
## Integrate Inference Engine with Your Python Application
@sphinxdirective
.. raw:: html
<div id="switcher-python" class="switcher-anchor">Python</div>
@endsphinxdirective
This document explains how to integrate and use the Inference Engine API with your Python application.
The following diagram illustrates the typical Inference Engine Python API workflow:
![ie_api_flow_python]
Read the sections below to learn about each item.
### Import Inference Module
To make use of the Inference Engine functionality, import IECore to your application:
```py
from openvino.inference_engine import IECore
```
### Use Inference Engine API
This section provides step-by-step instructions to implement a typical inference pipeline with the Inference Engine API:
![ie_api_use_python]
#### Step 1. Create Inference Engine Core
Use the following code to create Inference Engine Core to manage available devices and read network objects:
```py
ie = IECore()
```
#### Step 2 (Optional). Read model. Configure Input and Output of the Model
@sphinxdirective
.. raw:: html
<div class="collapsible-section">
@endsphinxdirective
Optionally, configure input and output of the model using the steps below:
1. Read model
@sphinxdirective
.. tab:: IR
.. code-block:: python
net = ie.read_network(model="model.xml")
.. tab:: ONNX
.. code-block:: python
net = ie.read_network(model="model.onnx")
.. tab:: nGraph
.. code-block:: python
#Basic example of nGraph model creation
param = Parameter(Type.f32, Shape([1, 3, 22, 22]))
relu = ng.relu(param)
func = Function([relu], [param], 'test')
caps = Function.to_capsule(func)
net = IENetwork(caps)
@endsphinxdirective
2. Request input and output information using input_info, outputs
```py
inputs = net.input_info
input_name = next(iter(net.input_info))
outputs = net.outputs
output_name = next(iter(net.outputs))
```
Information for this input layer is stored ininput_info. The next cell prints the input layout, precision and shape.
```py
print("Inputs:")
for name, info in net.input_info.items():
print("\tname: {}".format(name))
print("\tshape: {}".format(info.tensor_desc.dims))
print("\tlayout: {}".format(info.layout))
print("\tprecision: {}\n".format(info.precision))
```
This cell output tells us that the model expects inputs with a shape of [1,3,224,224], and that this is in NCHW layout. This means that the model expects input data with a batch size (N) of 1, 3 channels (C), and images of a height (H) and width (W) of 224. The input data is expected to be of FP32 (floating point) precision.
Getting the output layout, precision and shape is similar to getting the input layout, precision and shape.
```py
print("Outputs:")
for name, info in net.outputs.items():
print("\tname: {}".format(name))
print("\tshape: {}".format(info.shape))
print("\tlayout: {}".format(info.layout))
print("\tprecision: {}\n".format(info.precision))
```
This cell output shows that the model returns outputs with a shape of [1, 1001], where 1 is the batch size (N) and 1001 the number of classes (C). The output is returned as 32-bit floating point.
@sphinxdirective
.. raw:: html
</div>
@endsphinxdirective
#### Step 3. Load model to the Device
Load the model to the device using `load_network()`:
@sphinxdirective
.. tab:: IR
.. code-block:: python
exec_net = ie.load_network(network= "model.xml", device_name="CPU")
.. tab:: ONNX
.. code-block:: python
exec_net = ie.load_network(network= "model.onnx", device_name="CPU")
.. tab:: Model from step 2
.. code-block:: python
exec_net = ie.load_network(network=net, device_name="CPU")
@endsphinxdirective
This example is designed for CPU device, refer to the [Supported Devices](../IE_DG/supported_plugins/Supported_Devices.md) page to read about more devices.
#### Step 4. Prepare input
```py
import cv2
import numpy as np
image = cv2.imread("image.png")
# Resize with OpenCV your image if needed to match with net input shape
# N, C, H, W = net.input_info[input_name].tensor_desc.dims
# image = cv2.resize(src=image, dsize=(W, H))
# Converting image to NCHW format with FP32 type
input_data = np.expand_dims(np.transpose(image, (2, 0, 1)), 0).astype(np.float32)
```
#### Step 5. Start Inference
```py
result = exec_net.infer({input_name: input_data})
```
#### Step 6. Process the Inference Results
```py
output = result[output_name]
```
### Run Your Application
Congratulations, you have made your first Python application with OpenVINO™ toolkit, now you may run it.
[ie_api_flow_cpp]: img/BASIC_IE_API_workflow_Cpp.svg
[ie_api_use_cpp]: img/IMPLEMENT_PIPELINE_with_API_C.svg
[ie_api_flow_python]: img/BASIC_IE_API_workflow_Python.svg
[ie_api_use_python]: img/IMPLEMENT_PIPELINE_with_API_Python.svg

View File

@ -1,4 +1,4 @@
# Introduction to the Performance Topics {#openvino_docs_IE_DG_Intro_to_Performance} # Runtime Optimization Guide {#openvino_docs_IE_DG_Intro_to_Performance}
This section is a shorter version of the This section is a shorter version of the
[Optimization Guide](../optimization_guide/dldt_optimization_guide.md) for the Intel® Distribution of OpenVINO™ Toolkit. [Optimization Guide](../optimization_guide/dldt_optimization_guide.md) for the Intel® Distribution of OpenVINO™ Toolkit.

View File

@ -72,8 +72,8 @@ For the list of supported models refer to the framework or format specific page:
* [Supported Caffe* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_Caffe.md) * [Supported Caffe* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_Caffe.md)
* [Supported TensorFlow* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_TensorFlow.md) * [Supported TensorFlow* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_TensorFlow.md)
* [Supported MXNet* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_MxNet.md) * [Supported MXNet* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_MxNet.md)
* [Supported ONNX* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_ONNX.md)
* [Supported Kaldi* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_Kaldi.md) * [Supported Kaldi* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_Kaldi.md)
* [Supported ONNX* models](../MO_DG/prepare_model/convert_model/Convert_Model_From_ONNX.md)
## Intermediate Representation ## Intermediate Representation

View File

@ -3,7 +3,8 @@
## Multiple OpenMP Loadings ## Multiple OpenMP Loadings
If the application uses the Inference Engine with third-party components that depend on Intel OpenMP, multiple loadings of the libiomp library may occur and cause OpenMP runtime initialization conflicts. This may happen, for example, if the application uses Intel® Math Kernel Library (Intel® MKL) through the “Single Dynamic Library” (<code>libmkl_rt.so</code>) mechanism and calls Intel MKL after loading the Inference Engine plugin. If the application uses the Inference Engine with third-party components that depend on Intel OpenMP, multiple loadings of the libiomp library may occur and cause OpenMP runtime initialization conflicts. This may happen, for example, if the application uses Intel® Math Kernel Library (Intel® MKL) through the “Single Dynamic Library” (<code>libmkl_rt.so</code>) mechanism and calls Intel MKL after loading the Inference Engine plugin.
The error log looks as follows: The error log looks like this:
```sh ```sh
OMP: Error #15: Initializing libiomp5.so, but found libiomp5.so already initialized. OMP: Error #15: Initializing libiomp5.so, but found libiomp5.so already initialized.
OMP: Hint: This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://www.intel.com/software/products/support/. OMP: Hint: This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://www.intel.com/software/products/support/.
@ -12,20 +13,20 @@ OMP: Hint: This means that multiple copies of the OpenMP runtime have been linke
Possible workarounds: Possible workarounds:
* Preload the OpenMP runtime using the <code>LD_PRELOAD</code> variable: * Preload the OpenMP runtime using the <code>LD_PRELOAD</code> variable:
```sh ```sh
LD_PRELOAD=<path_to_libiomp5.so> <path_to your_executable> LD_PRELOAD=<path_to_libiomp5.so> <path_to your_executable>
``` ```
This eliminates multiple loadings of libiomp, and makes all the components use this specific version of OpenMP. This eliminates multiple loadings of libiomp, and makes all the components use this specific version of OpenMP.
* Alternatively, you can set <code>KMP_DUPLICATE_LIB_OK=TRUE</code>. However, performance degradation or results incorrectness may occur in this case. * Alternatively, you can set <code>KMP_DUPLICATE_LIB_OK=TRUE</code>. However, performance degradation or incorrect results may occur in this case.
## Old proto compiler breaks protobuf library ## Old proto compiler breaks protobuf library
With python protobuf library version 3.5.1 the following incompatibility can happen. With python protobuf library version 3.5.1, the following incompatibility can happen.
The known case is for Cent OS 7.4 The known case is for Cent OS 7.4.
The error log looks as follows: The error log looks like this:
```sh ```sh
File "../lib64/python3.5/site-packages/google/protobuf/descriptor.py", line 829, in _new_ File "../lib64/python3.5/site-packages/google/protobuf/descriptor.py", line 829, in _new_
@ -33,25 +34,24 @@ return _message.default_pool.AddSerializedFile(serialized_pb)
TypeError: expected bytes, str found TypeError: expected bytes, str found
``` ```
Possible workaround is to upgrade default protobuf compiler (libprotoc 2.5.0) to newer version, for example A possible workaround is to upgrade default protobuf compiler (libprotoc 2.5.0) to newer version, for example libprotoc 2.6.1.
libprotoc 2.6.1.
[protobuf_issue]: https://github.com/google/protobuf/issues/4272 [protobuf_issue]: https://github.com/google/protobuf/issues/4272
## Dynamic batching ## Dynamic batching
Refer to the **Limitations** section of [Dynamic batching page](DynamicBatching.md) Refer to the **Limitations** section of the [Dynamic batching page](DynamicBatching.md).
## Static Shape Infer ## Static Shape Infer
Refer to the **Limitations** section of [Static Shape Infer page](ShapeInference.md) Refer to the **Limitations** section of the [Static Shape Infer page](ShapeInference.md).
## Image Pre-Processing Performance Optimization Issue ## Image Pre-Processing Performance Optimization Issue
As described in [documentation for new API](Integrate_with_customer_application_new_API.md), you can set an image blob of any size to an As described in [documentation for the new API](Integrate_with_customer_application_new_API.md), you can set an image blob of any size to an
infer request using resizable input. Resize is executed during inference using configured resize algorithm. infer request using resizable input. Resize is executed during inference using the configured resize algorithm.
But currently resize algorithms are not completely optimized. So expect performance degradation if resizable input is But currently, resize algorithms are not completely optimized. So expect performance degradation if resizable input is
specified and an input blob (to be resized) is set (`SetBlob()` is used). Required performance is met for specified and an input blob (to be resized) is set using `SetBlob()`. The best performance is for the
[CPU](supported_plugins/CPU.md) plugin only (because enabled openMP* provides parallelism). [CPU](supported_plugins/CPU.md) plugin only (because enabled openMP* provides parallelism).
Another limitation is that currently, resize algorithms support NCHW layout only. So if you set NHWC layout for an input Another limitation is that currently, resize algorithms support NCHW layout only. So if you set NHWC layout for an input

View File

@ -1,5 +1,12 @@
Inference Engine Memory primitives {#openvino_docs_IE_DG_Memory_primitives} # Inference Engine Memory Primitives {#openvino_docs_IE_DG_Memory_primitives}
=====================================================================
## Inference Memory Primitives (C++)
@sphinxdirective
.. raw:: html
<div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
## Blobs ## Blobs
@ -18,7 +25,7 @@ InferenceEngine::Blob::Ptr blob = InferenceEngine::make_shared_blob<float>(tdesc
This class allows to create planar layouts using the standard formats (like <code>InferenceEngine::Layout::NCDHW</code>, <code>InferenceEngine::Layout::NCHW</code>, <code>InferenceEngine::Layout::NC</code>, <code>InferenceEngine::Layout::C</code> and etc) and also non-planar layouts using <code>InferenceEngine::BlockingDesc</code>. This class allows to create planar layouts using the standard formats (like <code>InferenceEngine::Layout::NCDHW</code>, <code>InferenceEngine::Layout::NCHW</code>, <code>InferenceEngine::Layout::NC</code>, <code>InferenceEngine::Layout::C</code> and etc) and also non-planar layouts using <code>InferenceEngine::BlockingDesc</code>.
In order to create a complex layout you should use <code>InferenceEngine::BlockingDesc</code> which allows to define the blocked memory with offsets and strides. In order to create a complex layout you should use <code>InferenceEngine::BlockingDesc</code>, which allows you to define the blocked memory with offsets and strides.
## Examples ## Examples
@ -27,13 +34,12 @@ In order to create a complex layout you should use <code>InferenceEngine::Blocki
InferenceEngine::BlockingDesc({1, 20, 20, 25}, {0, 2, 3, 1}); // or InferenceEngine::BlockingDesc({1, 20, 20, 25}, {0, 2, 3, 1}); // or
InferenceEngine::BlockingDesc({1, 20, 20, 25}, InferenceEngine::Layout::NHWC); InferenceEngine::BlockingDesc({1, 20, 20, 25}, InferenceEngine::Layout::NHWC);
</pre> </pre>
2. If you have a memory with real dimensions {N: 1, C: 25, H: 20, W: 20} but with channels which are blocked by 8, you can define it using next parameters:<br/> 2. If you have a memory with real dimensions {N: 1, C: 25, H: 20, W: 20} but with channels that are blocked by 8, you can define it using next parameters:<br/>
<pre class="brush:cpp"> <pre class="brush:cpp">
InferenceEngine::BlockingDesc({1, 4, 20, 20, 8}, {0, 1, 2, 3, 1}) InferenceEngine::BlockingDesc({1, 4, 20, 20, 8}, {0, 1, 2, 3, 1})
</pre> </pre>
3. Also you can set strides and offsets if layout contains it. 3. Also you can set strides and offsets if layout contains it.
4. If you have a complex blob layout and you don't want to calculate the real offset to data you can use methods 4. If you have a complex blob layout and you don't want to calculate the real offset to data you can use the <code>InferenceEngine::TensorDesc::offset(size_t l)</code> or <code>InferenceEngine::TensorDesc::offset(SizeVector v)</code> methods.<br/>
<code>InferenceEngine::TensorDesc::offset(size_t l)</code> or <code>InferenceEngine::TensorDesc::offset(SizeVector v)</code>.<br/>
For example: For example:
<pre class="brush:cpp"> <pre class="brush:cpp">
InferenceEngine::BlockingDesc blk({1, 4, 20, 20, 8}, {0, 1, 2, 3, 1}); InferenceEngine::BlockingDesc blk({1, 4, 20, 20, 8}, {0, 1, 2, 3, 1});
@ -43,8 +49,7 @@ tdesc.offset(1); // = 8
tdesc.offset({0, 0, 0, 2}); // = 16 tdesc.offset({0, 0, 0, 2}); // = 16
tdesc.offset({0, 1, 0, 2}); // = 17 tdesc.offset({0, 1, 0, 2}); // = 17
</pre> </pre>
5. If you would like to create a TensorDesc with a planar format and for N dimensions (N can be different 1, 2, 4 and etc), you can use the method 5. If you would like to create a TensorDesc with a planar format and for N dimensions (N can be different 1, 2, 4 and etc), you can use the <code>InferenceEngine::TensorDesc::getLayoutByDims</code> method.
<code>InferenceEngine::TensorDesc::getLayoutByDims</code>.
<pre class="brush:cpp"> <pre class="brush:cpp">
InferenceEngine::TensorDesc::getLayoutByDims({1}); // InferenceEngine::Layout::C InferenceEngine::TensorDesc::getLayoutByDims({1}); // InferenceEngine::Layout::C
InferenceEngine::TensorDesc::getLayoutByDims({1, 2}); // InferenceEngine::Layout::NC InferenceEngine::TensorDesc::getLayoutByDims({1, 2}); // InferenceEngine::Layout::NC
@ -52,4 +57,4 @@ InferenceEngine::TensorDesc::getLayoutByDims({1, 2, 3, 4}); // InferenceEngine::
InferenceEngine::TensorDesc::getLayoutByDims({1, 2, 3}); // InferenceEngine::Layout::BLOCKED InferenceEngine::TensorDesc::getLayoutByDims({1, 2, 3}); // InferenceEngine::Layout::BLOCKED
InferenceEngine::TensorDesc::getLayoutByDims({1, 2, 3, 4, 5}); // InferenceEngine::Layout::NCDHW InferenceEngine::TensorDesc::getLayoutByDims({1, 2, 3, 4, 5}); // InferenceEngine::Layout::NCDHW
InferenceEngine::TensorDesc::getLayoutByDims({1, 2, 3, 4, 5, ...}); // InferenceEngine::Layout::BLOCKED InferenceEngine::TensorDesc::getLayoutByDims({1, 2, 3, 4, 5, ...}); // InferenceEngine::Layout::BLOCKED
</pre> </pre>

View File

@ -0,0 +1,446 @@
# Model Downloader {#openvino_docs_IE_DG_Tools_Model_Downloader}
This directory contains scripts that automate certain model-related tasks
based on configuration files in the models' directories.
* Model Downloader: `downloader.py` downloads model files from online sources
and, if necessary, patches them to make them more usable with Model
Optimizer;
* Model Converter: `converter.py` converts the models that are not in the
Inference Engine IR format into that format using Model Optimizer.
* Model Quantizer: `quantizer.py` quantizes full-precision models in the IR
format into low-precision versions using Post-Training Optimization Toolkit.
* Model Information Dumper: `info_dumper.py` prints information about the models
in a stable machine-readable format.
> **TIP**: You can quick start with the Model Downloader inside the OpenVINO™ Deep Learning Workbench (DL Workbench). DL Workbench is the OpenVINO™ toolkit UI that enables you to import a model, analyze its performance and accuracy, visualize the outputs, optimize and prepare the model for deployment on various Intel® platforms.
## Prerequisites
1. Install Python (version 3.6 or higher)
2. Install the tools' dependencies with the following command:
```sh
python3 -mpip install --user -r ./requirements.in
```
For the model converter, you will also need to install the OpenVINO&trade;
toolkit and the prerequisite libraries for Model Optimizer. See the
[OpenVINO toolkit documentation](https://docs.openvinotoolkit.org/) for details.
To convert models from certain frameworks, you will also need to install
additional dependencies.
@sphinxdirective
.. tab:: Caffe2
.. code-block:: python
python3 -mpip install --user -r ./requirements-caffe2.in
.. tab:: Pytorch
.. code-block:: python
python3 -mpip install --user -r ./requirements-pytorch.in
.. tab:: TensorFlow
.. code-block:: python
python3 -mpip install --user -r ./requirements-tensorflow.in
@endsphinxdirective
## Model Downloader
The basic usage is to run the script like this:
```sh
./downloader.py --all
```
This will download all models. The `--all` option can be replaced with
other filter options to download only a subset of models. See the "Shared options"
section.
### Model Downloader Starting Parameters
@sphinxdirective
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+
| Parameter | Explanation | Example |
+===========================+==================================================================================================================================================================================================================================================================================================================================================================================================+=====================================================================================+
| ``-o``/``--output_dir`` | By default, the script will download models into a directory tree rooted in the current directory. Use this parameter to download into a different directory. | ``./downloader.py --all --output_dir my/download/directory`` |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+
| ``--precisions`` | Specify comma separated precisions of weights to be downloaded | ``./downloader.py --name face-detection-retail-0004 --precisions FP16,FP16-INT8`` |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+
| ``--num_attempts`` | By default, the script will attempt to download each file only once. Use this parameter to change that and increase the robustness of the download process | ``./downloader.py --all --num_attempts 5 # attempt each download five times`` |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+
| ``--cache_dir`` | Make the script use the specified directory as a cache. The script will place a copy of each downloaded file in the cache, or, if it is already there, retrieve it from the cache instead of downloading it again. The cache format is intended to remain compatible in future Open Model Zoo versions, so you can use a cache to avoid redownloading most files when updating Open Model Zoo. | ``./downloader.py --all --cache_dir my/cache/directory`` |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+
| ``-j``/``--jobs`` | The script downloads files for multiple models concurrently. | ``./downloader.py --all -j8 # download up to 8 models at a time`` |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+
| ``--progress_format`` | By default, the script outputs progress information as unstructured, human-readable text. Use this option, if you want to consume progress information programmatically. | ``./downloader.py --all --progress_format=json`` |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------+
@endsphinxdirective
When this option is set to `json`, the script's standard output is replaced by
a machine-readable progress report, whose format is documented in the
"JSON progress report format" section. This option does not affect errors and
warnings, which will still be printed to the standard error stream in a
human-readable format.
You can also set this option to `text` to explicitly request the default text
format.
See the "Shared options" section for information on other options accepted by
the script.
### JSON progress report format
This section documents the format of the progress report produced by the script
when the `--progress_format=json` option is specified.
The report consists of a sequence of events, where each event is represented
by a line containing a JSON-encoded object. Each event has a member with the
name `$type` whose value determines the type of the event, as well as which
additional members it contains.
@sphinxdirective
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Event type | Additional members | Explanation |
+====================================+=========================================================================+================================================================================================================================================================================================================================================================================================================================================+
| ``model_download_begin`` | ``model`` (string), ``num_files`` (integer) | The script started downloading the model named by ``model``. ``num_files`` is the number of files that will be downloaded for this model. This event will always be followed by a corresponding ``model_download_end`` event. |
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``model_download_end`` | ``model`` (string), ``successful`` (boolean) | The script stopped downloading the model named by ``model``. ``successful`` is true if every file was downloaded successfully. |
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``model_file_download_begin`` | ``model`` (string), ``model_file`` (string), ``size`` (integer) | The script started downloading the file named by ``model_file`` of the model named by ``model``. ``size`` is the size of the file in bytes. This event will always occur between ``model_download_begin`` and ``model_download_end`` events for the model, and will always be followed by a corresponding ``model_file_download_end`` event. |
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``model_file_download_end`` | ``model`` (string), ``model_file`` (string), ``successful`` (boolean) | The script stopped downloading the file named by ``model_file`` of the model named by ``model``. ``successful`` is true if the file was downloaded successfully. |
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``model_file_download_progress`` | ``model`` (string), ``model_file`` (string), ``size`` (integer) | The script downloaded ``size`` bytes of the file named by ``model_file`` of the model named by ``model`` so far. Note that ``size`` can decrease in a subsequent event if the download is interrupted and retried. This event will always occur between ``model_file_download_begin`` and ``model_file_download_end`` events for the file. |
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``model_postprocessing_begin`` | ``model`` | The script started post-download processing on the model named by ``model``. This event will always be followed by a corresponding ``model_postprocessing_end`` event. |
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``model_postprocessing_end`` | ``model`` | The script stopped post-download processing on the model named by ``model``. |
+------------------------------------+-------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@endsphinxdirective
Additional event types and members may be added in the future.
Tools parsing the machine-readable format should avoid relying on undocumented details.
In particular:
* Tools should not assume that any given event will occur for a given model/file
(unless specified otherwise above) or will only occur once.
* Tools should not assume that events will occur in a certain order beyond
the ordering constraints specified above. In particular, when the `--jobs` option
is set to a value greater than 1, event sequences for different files or models
may get interleaved.
## Model Converter
The basic usage is to run the script like this:
```sh
./converter.py --all
```
This will convert all models into the Inference Engine IR format. Models that
were originally in that format are ignored. Models in PyTorch and Caffe2 formats will be
converted in ONNX format first.
The `--all` option can be replaced with other filter options to convert only
a subset of models. See the "Shared options" section.
### Model Converter Starting Parameters
@sphinxdirective
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| Parameter | Explanation | Example |
+=============================+==================================================================================================================================================================================================================================================================+==================================================================================================+
| ``-d``/``--download_dir`` | The current directory must be the root of a download tree created by the model downloader. Use this parameter to specify a different download tree path. | ``./converter.py --all --download_dir my/download/directory`` |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| ``-o``/``--output_dir`` | By default, the script will download models into a directory tree rooted in the current directory. Use this parameter to download into a different directory. Note: models in intermediate format are placed to this directory too. | ``./converter.py --all --output_dir my/output/directory`` |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| ``--precisions`` | By default, the script will produce models in every precision that is supported for conversion. Use this parameter to only produce models in a specific precision. If the specified precision is not supported for a model, that model will be skipped. | ``./converter.py --all --precisions=FP16`` |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| ``--add_mo_arg`` | Add extra Model Optimizer arguments to the ones specified in the model configuration. The option can be repeated to add multiple arguments | ``./converter.py --name=caffenet --add_mo_arg=--reverse_input_channels --add_mo_arg=--silent`` |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| ``-j``/``--jobs`` | Run multiple conversion commands concurrently. The argument to the option must be either a maximum number of concurrently executed commands, or "auto", in which case the number of CPUs in the system is used. By default, all commands are run sequentially. | ``./converter.py --all -j8 # run up to 8 commands at a time`` |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| ``--dry_run`` | Print the conversion commands without actually running them.. | ``./converter.py --all --dry_run`` |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| ``-p``/``--python`` | By default, the script will run Model Optimizer using the same Python executable that was used to run the script itself. Apply this parameter to use a different Python executable. | ``./converter.py --all --python my/python`` |
+-----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
@endsphinxdirective
The Python script will attempt to locate Model Optimizer using several methods:
1. If the `--mo` option was specified, then its value will be used as the path
to the script to run:
```sh
./converter.py --all --mo my/openvino/path/model_optimizer/mo.py
```
2. Otherwise, if the selected Python executable can import the `mo` package,
then that package will be used.
3. Otherwise, if the OpenVINO&trade; toolkit's `setupvars.sh`/`setupvars.bat`
script has been executed, the environment variables set by that script will
be used to locate Model Optimizer within the toolkit.
4. Otherwise, the script will fail.
See the "Shared options" section for information on other options accepted by
the script.
## Model Quantizer
Before you run the model quantizer, you must prepare a directory with
the datasets required for the quantization process. This directory will be
referred to as `<DATASET_DIR>` below. You can find more detailed information
about dataset preparation in the [Dataset Preparation Guide](../../data/datasets.md).
The basic usage is to run the script like this:
```sh
./quantizer.py --all --dataset_dir <DATASET_DIR>
```
This will quantize all models for which quantization is supported. Other models
are ignored.
The `--all` option can be replaced with other filter options to quantize only
a subset of models. See the "Shared options" section.
### Model Quantizer Starting Parameters
@sphinxdirective
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| Parameter | Explanation | Example |
+===========================+=====================================================================================================================================================================================================================================================================================================================+=========================================================================================+
| ``--model_dir`` | The current directory must be the root of a tree of model files create by the model converter. Use this parameter to specify a different model tree path | ``./quantizer.py --all --dataset_dir <DATASET_DIR> --model_dir my/model/directory`` |
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| ``-o``/``--output_dir`` | By default, the script will download models into a directory tree rooted in the current directory. Use this parameter to download into a different directory. Note: models in intermediate format are placed to this directory too. | ``./quantizer.py --all --dataset_dir <DATASET_DIR> --output_dir my/output/directory`` |
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| ``--precisions`` | By default, the script will produce models in every precision that is supported as a quantization output. Use this parameter to only produce models in a specific precision. | ``./quantizer.py --all --dataset_dir <DATASET_DIR> --precisions=FP16-INT8`` |
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| ``--target_device`` | It's possible to specify a target device for Post-Training Optimization Toolkitto optimize for. The supported values are those accepted by the "target\_device" option in Post-Training Optimization Toolkit's config files. If this option is unspecified, Post-Training Optimization Toolkit's default is used. | ``../quantizer.py --all --dataset_dir <DATASET_DIR> --target_device VPU`` |
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| ``--dry_run`` | The script can print the quantization commands without actually running them. With this option specified, the configuration file for Post-Training Optimization Toolkit will still be created, so that you can inspect it. | ``./quantizer.py --all --dataset_dir <DATASET_DIR> --dry_run`` |
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| ``-p``/``--python`` | By default, the script will run Model Optimizer using the same Python executable that was used to run the script itself. Apply this parameter to use a different Python executable. | ``./quantizer.py --all --dataset_dir <DATASET_DIR> --python my/python`` |
+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
@endsphinxdirective
The script will attempt to locate Post-Training Optimization Toolkit using several methods:
1. If the `--pot` option was specified, then its value will be used as the path
to the script to run:
```sh
./quantizer.py --all --dataset_dir <DATASET_DIR> --pot my/openvino/path/post_training_optimization_toolkit/main.py
```
2. Otherwise, if the selected Python executable can import the `pot` package,
then that package will be used.
3. Otherwise, if the OpenVINO&trade; toolkit's `setupvars.sh`/`setupvars.bat`
script has been executed, the environment variables set by that script will
be used to locate Post-Training Optimization Toolkit within the OpenVINO toolkit.
4. Otherwise, the script will fail.
See the "Shared options" section for information on other options accepted by
the script.
## Model Information Dumper
The basic usage is to run the script like this:
```sh
./info_dumper.py --all
```
This will print to standard output information about all models.
The only options accepted by the script are those described in the "Shared options"
section.
The script's output is a JSON array, each element of which is a JSON object
describing a single model. Each such object has the following keys:
@sphinxdirective
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Parameter | Explanation |
+======================================+=====================================================================================================================================================================================================================================================================================+
| ``name`` | the identifier of the model, as accepted by the ``--name`` option. |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``composite_model_name`` | the identifier of the composite model name, if the model is a part of composition of several models (e.g. encoder-decoder), otherwise - ``null`` |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``description`` | text describing the model. Paragraphs are separated by line feed characters. |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``framework`` | a string identifying the framework whose format the model is downloaded in. Current possible values are ``dldt`` (Inference Engine IR), ``caffe``, ``caffe2``, ``mxnet``, ``onnx``, ``pytorch`` and ``tf`` (TensorFlow). Additional possible values might be added in the future. |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``license_url`` | a URL for the license that the model is distributed under. |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``quantization_output_precisions`` | the list of precisions that the model can be quantized to by the model quantizer. Current possible values are ``FP16-INT8`` and ``FP32-INT8``; additional possible values might be added in the future. |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``quantization_output_precisions`` | the list of precisions that the model can be quantized to by the model quantizer. Current possible values are ``FP16-INT8`` and ``FP32-INT8``; additional possible values might be added in the future. |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``subdirectory`` | the subdirectory of the output tree into which the downloaded or converted files will be placed by the downloader or the converter, respectively. |
+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@endsphinxdirective
* `precisions`: the list of precisions that the model has IR files for. For models downloaded
in a format other than the Inference Engine IR format, these are the precisions that the model
converter can produce IR files in. Current possible values are:
* `FP16`
* `FP16-INT1`
* `FP16-INT8`
* `FP32`
* `FP32-INT1`
* `FP32-INT8`
Additional possible values might be added in the future.
* `task_type`: a string identifying the type of task that the model performs.
are:
@sphinxdirective
.. raw:: html
<div class="collapsible-section" data-title="Current possible values">
@endsphinxdirective
* `action_recognition`
* `classification`
* `colorization`
* `detection`
* `face_recognition`
* `feature_extraction`
* `head_pose_estimation`
* `human_pose_estimation`
* `image_inpainting`
* `image_processing`
* `image_translation`
* `instance_segmentation`
* `machine_translation`
* `monocular_depth_estimation`
* `named_entity_recognition`
* `noise_suppression`
* `object_attributes`
* `optical_character_recognition`
* `place_recognition`
* `question_answering`
* `salient_object_detection`
* `semantic_segmentation`
* `sound_classification`
* `speech_recognition`
* `style_transfer`
* `text_to_speech`
* `time_series`
* `token_recognition`
@sphinxdirective
.. raw:: html
</div>
@endsphinxdirective
Additional possible values might be added in the future.
## Shared options
The are certain options that all tools accept.
`-h`/`--help` can be used to print a help message:
```sh
./TOOL.py --help
```
There are several mutually exclusive filter options that select the models the
tool will process:
@sphinxdirective
+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------+
| Parameter | Explanation | Example |
+==============+===================================================================================================================================================================================================================================================================================+===========================================+
| ``--all`` | Selects all models | ``./TOOL.py --all`` |
+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------+
| ``--name`` | takes a comma-separated list of patterns and selects models that match at least one of these patterns. The patterns may contain shell-style wildcards. For composite models, the name of composite model is accepted, as well as the names of individual models it consists of. | ``./TOOL.py --name 'mtcnn,densenet-*'`` |
+--------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------+
@endsphinxdirective
See https://docs.python.org/3/library/fnmatch.html for a full description of
the pattern syntax.
`--list` takes a path to a file that must contain a list of patterns and
selects models that match at least one of those patterns.
For composite models, the name of composite model is accepted, as well as the names
of individual models it consists of.
```sh
./TOOL.py --list my.lst
```
The file must contain one pattern per line. The pattern syntax is the same
as for the `--name` option. Blank lines and comments starting with `#` are
ignored. For example:
```
mtcnn # get all three models: mtcnn-o, mtcnn-p, mtcnn-r
densenet-* # get all DenseNet variants
```
To see the available models, you can use the `--print_all` option. When this
option is specified, the tool will print all model names defined in the
configuration file and exit:
```
$ ./TOOL.py --print_all
action-recognition-0001-decoder
action-recognition-0001-encoder
age-gender-recognition-retail-0013
driver-action-recognition-adas-0002-decoder
driver-action-recognition-adas-0002-encoder
emotions-recognition-retail-0003
face-detection-adas-0001
face-detection-retail-0004
face-detection-retail-0005
[...]
```
Either `--print_all` or one of the filter options must be specified.

View File

@ -1,65 +1,136 @@
# Model Caching Overview {#openvino_docs_IE_DG_Model_caching_overview} # Model Caching Overview {#openvino_docs_IE_DG_Model_caching_overview}
## Introduction ## Introduction (C++)
As described in [Inference Engine Developer Guide](Deep_Learning_Inference_Engine_DevGuide.md), common application flow consists of the following steps: @sphinxdirective
.. raw:: html
1. **Create Inference Engine Core object** <div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
2. **Read the Intermediate Representation** - Read an Intermediate Representation file into an object of the `InferenceEngine::CNNNetwork` As described in the [Inference Engine Developer Guide](Deep_Learning_Inference_Engine_DevGuide.md), a common application flow consists of the following steps:
3. **Prepare inputs and outputs** 1. **Create an Inference Engine Core object**: First step to manage available devices and read network objects
4. **Set configuration** Pass device-specific loading configurations to the device 2. **Read the Intermediate Representation**: Read an Intermediate Representation file into an object of the `InferenceEngine::CNNNetwork`
5. **Compile and Load Network to device** - Use the `InferenceEngine::Core::LoadNetwork()` method with specific device 3. **Prepare inputs and outputs**: If needed, manipulate precision, memory layout, size or color format
6. **Set input data** 4. **Set configuration**: Pass device-specific loading configurations to the device
7. **Execute** 5. **Compile and Load Network to device**: Use the `InferenceEngine::Core::LoadNetwork()` method with a specific device
Step #5 can potentially perform several time-consuming device-specific optimizations and network compilations, 6. **Set input data**: Specify input blob
and such delays can lead to bad user experience on application startup. To avoid this, some devices offer
Import/Export network capability, and it is possible to either use [Compile tool](../../tools/compile_tool/README.md) 7. **Execute**: Carry out inference and process results
Step 5 can potentially perform several time-consuming device-specific optimizations and network compilations,
and such delays can lead to a bad user experience on application startup. To avoid this, some devices offer
import/export network capability, and it is possible to either use the [Compile tool](../../tools/compile_tool/README.md)
or enable model caching to export compiled network automatically. Reusing cached networks can significantly reduce load network time. or enable model caching to export compiled network automatically. Reusing cached networks can significantly reduce load network time.
### Set "CACHE_DIR" config option to enable model caching
## Set "CACHE_DIR" config option to enable model caching To enable model caching, the application must specify a folder to store cached blobs, which is done like this:
To enable model caching, the application must specify the folder where to store cached blobs. It can be done like this
@snippet snippets/InferenceEngine_Caching0.cpp part0 @snippet snippets/InferenceEngine_Caching0.cpp part0
With this code, if device supports Import/Export network capability, cached blob is automatically created inside the `myCacheFolder` folder With this code, if the device specified by `LoadNetwork` supports import/export network capability, a cached blob is automatically created inside the `myCacheFolder` folder.
CACHE_DIR config is set to the Core object. If device does not support Import/Export capability, cache is just not created and no error is thrown CACHE_DIR config is set to the Core object. If the device does not support import/export capability, cache is not created and no error is thrown.
Depending on your device, total time for loading network on application startup can be significantly reduced. Depending on your device, total time for loading network on application startup can be significantly reduced.
Please also note that very first LoadNetwork (when cache is not yet created) takes slightly longer time to 'export' compiled blob into a cache file Also note that the very first LoadNetwork (when cache is not yet created) takes slightly longer time to "export" the compiled blob into a cache file:
![caching_enabled] ![caching_enabled]
## Even faster: use LoadNetwork(modelPath) ### Even faster: use LoadNetwork(modelPath)
In some cases, applications do not need to customize inputs and outputs every time. Such applications always In some cases, applications do not need to customize inputs and outputs every time. Such an application always
call `cnnNet = ie.ReadNetwork(...)`, then `ie.LoadNetwork(cnnNet, ..)` and it can be further optimized. call `cnnNet = ie.ReadNetwork(...)`, then `ie.LoadNetwork(cnnNet, ..)` and it can be further optimized.
For such cases, more convenient API to load network in one call is introduced in the 2021.4 release. For these cases, the 2021.4 release introduces a more convenient API to load the network in a single call, skipping the export step:
@snippet snippets/InferenceEngine_Caching1.cpp part1 @snippet snippets/InferenceEngine_Caching1.cpp part1
With enabled model caching, total load time is even smaller - in case that ReadNetwork is optimized as well With model caching enabled, total load time is even smaller, if ReadNetwork is optimized as well.
@snippet snippets/InferenceEngine_Caching2.cpp part2 @snippet snippets/InferenceEngine_Caching2.cpp part2
![caching_times] ![caching_times]
### Advanced Examples
## Advanced examples Not every device supports network import/export capability. For those that don't, enabling caching has no effect.
Not every device supports network import/export capability, enabling of caching for such devices do not have any effect.
To check in advance if a particular device supports model caching, your application can use the following code: To check in advance if a particular device supports model caching, your application can use the following code:
@snippet snippets/InferenceEngine_Caching3.cpp part3 @snippet snippets/InferenceEngine_Caching3.cpp part3
## Introduction (Python)
@sphinxdirective
.. raw:: html
<div id="switcher-python" class="switcher-anchor">Python</div>
@endsphinxdirective
As described in Inference Engine Developer Guide, a common application flow consists of the following steps:
1. **Create an Inference Engine Core Object**
2. **Read the Intermediate Representation** - Read an Intermediate Representation file into an object of the [ie_api.IENetwork](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html)
3. **Prepare inputs and outputs**
4. **Set configuration** - Pass device-specific loading configurations to the device
5. **Compile and Load Network to device** - Use the `IECore.load_network()` method and specify the target device
6. **Set input data**
7. **Execute the model** - Run inference
Step #5 can potentially perform several time-consuming device-specific optimizations and network compilations, and such delays can lead to bad user experience on application startup. To avoid this, some devices offer Import/Export network capability, and it is possible to either use the [Compile tool](../../inference-engine/tools/compile_tool/README.md) or enable model caching to export the compiled network automatically. Reusing cached networks can significantly reduce load network time.
### Set the “CACHE_DIR” config option to enable model caching
To enable model caching, the application must specify the folder where to store cached blobs. It can be done using [IECore.set_config](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.set_config).
``` python
from openvino.inference_engine import IECore
ie = IECore()
ie.set_config(config={"CACHE_DIR": path_to_cache}, device_name=device)
net = ie.read_network(model=path_to_xml_file)
exec_net = ie.load_network(network=net, device_name=device)
```
With this code, if a device supports the Import/Export network capability, a cached blob is automatically created inside the path_to_cache directory `CACHE_DIR` config is set to the Core object. If device does not support Import/Export capability, cache is just not created and no error is thrown
Depending on your device, total time for loading network on application startup can be significantly reduced. Please also note that very first [IECore.load_network](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.load_network) (when the cache is not yet created) takes slightly longer time to export the compiled blob into a cache file.
![caching_enabled]
### Even Faster: Use IECore.load_network(path_to_xml_file)
In some cases, applications do not need to customize inputs and outputs every time. These applications always call [IECore.read_network](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.read_network), then `IECore.load_network(model=path_to_xml_file)` and may be further optimized. For such cases, it's more convenient to load the network in a single call to `ie.load_network()`
A model can be loaded directly to the device, with model caching enabled:
``` python
from openvino.inference_engine import IECore
ie = IECore()
ie.set_config(config={"CACHE_DIR" : path_to_cache}, device_name=device)
ie.load_network(network=path_to_xml_file, device_name=device)
```
![caching_times]
### Advanced Examples
Not every device supports network import/export capability, enabling of caching for such devices does not have any effect. To check in advance if a particular device supports model caching, your application can use the following code:
```python
all_metrics = ie.get_metric(device_name=device, metric_name="SUPPORTED_METRICS")
# Find the 'IMPORT_EXPORT_SUPPORT' metric in supported metrics
allows_caching = "IMPORT_EXPORT_SUPPORT" in all_metrics
```
> **NOTE**: The GPU plugin does not have the IMPORT_EXPORT_SUPPORT capability, and does not support model caching yet. However, the GPU plugin supports caching kernels (see the [GPU plugin documentation](supported_plugins/GPU.md)). Kernel caching for the GPU plugin can be accessed the same way as model caching: by setting the `CACHE_DIR` configuration key to a folder where the cache should be stored.
[caching_enabled]: ../img/caching_enabled.png [caching_enabled]: ../img/caching_enabled.png
[caching_times]: ../img/caching_times.png [caching_times]: ../img/caching_times.png

View File

@ -1,41 +1,37 @@
# ONNX format support in the OpenVINO™ {#openvino_docs_IE_DG_ONNX_Support} # ONNX Format Support {#openvino_docs_IE_DG_ONNX_Support}
Starting from the 2020.4 release, OpenVINO™ supports reading native ONNX models. ## Introduction (C++)
`Core::ReadNetwork()` method provides a uniform way to read models from IR or ONNX format, it is a recommended approach to reading models.
Example: @sphinxdirective
.. raw:: html
<div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
Starting with the 2020.4 release, OpenVINO™ supports reading native ONNX models. The `Core::ReadNetwork()` method provides a uniform way to read models from IR or ONNX format, it is a recommended approach to reading models. Example:
```cpp ```cpp
InferenceEngine::Core core; InferenceEngine::Core core;
auto network = core.ReadNetwork("model.onnx"); auto network = core.ReadNetwork("model.onnx");
``` ```
**Reshape feature:** ### Reshape Feature
OpenVINO™ does not provide a mechanism to specify pre-processing (like mean values subtraction, reverse input channels) for the ONNX format. If an ONNX model contains dynamic shapes for input, please use the `CNNNetwork::reshape` method to reshape the model.
OpenVINO™ doesn't provide a mechanism to specify pre-processing (like mean values subtraction, reverse input channels) for the ONNX format. ### Weights Saved in External Files
If an ONNX model contains dynamic shapes for input, please use the `CNNNetwork::reshape` method for shape specialization.
**Weights saved in external files:** OpenVINO™ supports ONNX models that store weights in external files. It is especially useful for models larger than 2GB because of protobuf limitations. To read such models, use the `ReadNetwork` overload which takes `modelPath` as input parameter (both `std::string` and `std::wstring`). Note that the `binPath` argument of `ReadNetwork` should be empty in this case, because paths to external weights are saved directly in an ONNX model.
Otherwise, a runtime exception is thrown. Reading models with external weights is not supported by the `ReadNetwork(const std::string& model, const Blob::CPtr& weights)` overload.
OpenVINO™ supports ONNX models that store weights in external files. It is especially useful for models larger than 2GB because of protobuf limitations.
To read such models, use the `ReadNetwork` overload which takes `modelPath` as input parameter (both `std::string` and `std::wstring`).
Note that the `binPath` argument of `ReadNetwork` should be empty in this case, because paths to external weights are saved directly in an ONNX model.
Otherwise, a runtime exception is thrown.
Reading models with external weights is not supported by the `ReadNetwork(const std::string& model, const Blob::CPtr& weights)` overload.
Paths to external weight files are saved in an ONNX model; these paths are relative to the model's directory path. Paths to external weight files are saved in an ONNX model; these paths are relative to the model's directory path.
It means that if a model is located at: It means that if a model is located at `home/user/workspace/models/model.onnx` and a file that contains external weights is in `home/user/workspace/models/data/weights.bin`, then the path saved in the model should be:
`home/user/workspace/models/model.onnx` `data/weights.bin`
and a file that contains external weights:
`home/user/workspace/models/data/weights.bin`
the path saved in model should be:
`data/weights.bin`.
**NOTE** > **NOTE**: A single model can use many external weights files.
* A single model can use many external weights files. > **NOTE**: Data of many tensors can be stored in a single external weights file (it is processed using offset and length values, which can be also saved in a model).
* Data of many tensors can be stored in a single external weights file (it is processed using offset and length values, which can be also saved in a model).
The described mechanism is the only possibility to read weights from external files. The following input parameters of the `ReadNetwork` function overloads are NOT supported for ONNX models and should be passed as empty: The described mechanism is the only way to read weights from external files. The following input parameters of the `ReadNetwork` function overloads are NOT supported for ONNX models and should be passed as empty:
* `const std::wstring& binPath` * `const std::wstring& binPath`
* `const std::string& binPath` * `const std::string& binPath`
* `const Blob::CPtr& weights` * `const Blob::CPtr& weights`
@ -43,8 +39,53 @@ The described mechanism is the only possibility to read weights from external fi
You can find more details about the external data mechanism in [ONNX documentation](https://github.com/onnx/onnx/blob/master/docs/ExternalData.md). You can find more details about the external data mechanism in [ONNX documentation](https://github.com/onnx/onnx/blob/master/docs/ExternalData.md).
To convert a model to use the external data feature, you can use [ONNX helper functions](https://github.com/onnx/onnx/blob/master/onnx/external_data_helper.py). To convert a model to use the external data feature, you can use [ONNX helper functions](https://github.com/onnx/onnx/blob/master/onnx/external_data_helper.py).
**Unsupported types of tensors:** Unsupported types of tensors:
* string
* complex64
* complex128
* `string`, ## Introduction (Python)
* `complex64`,
* `complex128`. @sphinxdirective
.. raw:: html
<div id="switcher-python" class="switcher-anchor">Python</div>
@endsphinxdirective
Starting with the 2020.4 release, OpenVINO™ supports reading native ONNX models. The `IECore.read_network()` method provides a uniform way to read models from IR or ONNX format, it is a recommended approach to reading models. Example:
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(model=path_to_onnx_file)
```
### Reshape Feature
OpenVINO™ does not provide a mechanism to specify pre-processing (like mean values subtraction, reverse input channels) for the ONNX format. If an ONNX model contains dynamic shapes for input, please use the [IENetwork.reshape](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.reshape) method to reshape the model.
```python
from openvino.inference_engine import IECore
ie = IECore()
net = ie.read_network(model=path_to_onnx_file)
input_layer = next(iter(net.input_info))
net.reshape({input_layer: new_shape})
```
### Weights Saved in External Files
OpenVINO™ supports ONNX models that store weights in external files. It is especially useful for models larger than 2GB because of protobuf limitations. To read such models, use the `model` parameter in the `IECore.read_network(model=path_to_onnx_file)` method. Note that the parameter for the path to the binary weight file, `weights=` should be empty in this case, because paths to external weights are saved directly in an ONNX model. Otherwise, a runtime exception is thrown. Reading models with external weights is **NOT** supported by the `read_network(weights=path_to_bin_file)` parameter.
Paths to external weight files are saved in an ONNX model; these paths are relative to the models directory path. It means that if a model is located at: `$HOME/workspace/models/model.onnx` and a file that contains external weights: `$HOME/workspace/models/data/weights.bin`, the path saved in model should be: data/weights.bin.
**NOTE**:
* A single model can use many external weights files.
* Data of many tensors can be stored in a single external weights file (it is processed using offset and length values, which can be also saved in a model).
The described mechanism is the only possibility to read weights from external files. The `weights` input parameter of the [IECore.read_network](api/ie_python_api/_autosummary/openvino.inference_engine.IECore.html#openvino.inference_engine.IECore.read_network) function is NOT supported for ONNX models and should not be passed, or set as None.
Unsupported types of tensors:
* string
* complex64
* complex128

View File

@ -0,0 +1,194 @@
# Operations Specifications {#openvino_docs_operations_specifications}
@sphinxdirective
.. toctree::
:maxdepth: 1
openvino_docs_ops_arithmetic_Abs_1
openvino_docs_ops_arithmetic_Acos_1
openvino_docs_ops_arithmetic_Acosh_3
openvino_docs_ops_pooling_AdaptiveAvgPool_8
openvino_docs_ops_pooling_AdaptiveMaxPool_8
openvino_docs_ops_arithmetic_Add_1
openvino_docs_ops_arithmetic_Asin_1
openvino_docs_ops_arithmetic_Asinh_3
openvino_docs_ops_infrastructure_Assign_3
openvino_docs_ops_arithmetic_Atan_1
openvino_docs_ops_arithmetic_Atanh_3
openvino_docs_ops_pooling_AvgPool_1
openvino_docs_ops_normalization_BatchNormInference_1
openvino_docs_ops_normalization_BatchNormInference_5
openvino_docs_ops_movement_BatchToSpace_2
openvino_docs_ops_convolution_BinaryConvolution_1
openvino_docs_ops_movement_Broadcast_1
openvino_docs_ops_movement_Broadcast_3
openvino_docs_ops_condition_Bucketize_3
openvino_docs_ops_sequence_CTCGreedyDecoder_1
openvino_docs_ops_sequence_CTCGreedyDecoderSeqLen_6
openvino_docs_ops_arithmetic_Ceiling_1
openvino_docs_ops_activation_Clamp_1
openvino_docs_ops_movement_Concat_1
openvino_docs_ops_infrastructure_Constant_1
openvino_docs_ops_type_ConvertLike_1
openvino_docs_ops_type_Convert_1
openvino_docs_ops_convolution_ConvolutionBackpropData_1
openvino_docs_ops_convolution_Convolution_1
openvino_docs_ops_arithmetic_Cos_1
openvino_docs_ops_arithmetic_Cosh_1
openvino_docs_ops_sequence_CTCLoss_4
openvino_docs_ops_arithmetic_CumSum_3
openvino_docs_ops_convolution_DeformableConvolution_8
openvino_docs_ops_detection_DeformablePSROIPooling_1
openvino_docs_ops_movement_DepthToSpace_1
openvino_docs_ops_detection_DetectionOutput_1
openvino_docs_ops_detection_DetectionOutput_8
openvino_docs_ops_signals_DFT_7
openvino_docs_ops_arithmetic_Divide_1
openvino_docs_ops_matrix_Einsum_7
openvino_docs_ops_activation_Elu_1
openvino_docs_ops_sparse_EmbeddingBagOffsetsSum_3
openvino_docs_ops_sparse_EmbeddingBagPackedSum_3
openvino_docs_ops_sparse_EmbeddingSegmentsSum_3
openvino_docs_ops_comparison_Equal_1
openvino_docs_ops_arithmetic_Erf_1
openvino_docs_ops_activation_Exp_1
openvino_docs_ops_detection_ExperimentalDetectronDetectionOutput_6
openvino_docs_ops_detection_ExperimentalDetectronGenerateProposalsSingleImage_6
openvino_docs_ops_detection_ExperimentalDetectronPriorGridGenerator_6
openvino_docs_ops_detection_ExperimentalDetectronROIFeatureExtractor_6
openvino_docs_ops_sort_ExperimentalDetectronTopKROIs_6
openvino_docs_ops_movement_ExtractImagePatches_3
openvino_docs_ops_quantization_FakeQuantize_1
openvino_docs_ops_arithmetic_FloorMod_1
openvino_docs_ops_arithmetic_Floor_1
openvino_docs_ops_normalization_GRN_1
openvino_docs_ops_sequence_GRUCell_3
openvino_docs_ops_sequence_GRUSequence_5
openvino_docs_ops_movement_GatherTree_1
openvino_docs_ops_movement_Gather_1
openvino_docs_ops_movement_Gather_7
openvino_docs_ops_movement_Gather_8
openvino_docs_ops_movement_GatherElements_6
openvino_docs_ops_movement_GatherND_5
openvino_docs_ops_movement_GatherND_8
openvino_docs_ops_activation_GELU_2
openvino_docs_ops_activation_GELU_7
openvino_docs_ops_comparison_GreaterEqual_1
openvino_docs_ops_comparison_Greater_1
openvino_docs_ops_convolution_GroupConvolutionBackpropData_1
openvino_docs_ops_convolution_GroupConvolution_1
openvino_docs_ops_activation_HardSigmoid_1
openvino_docs_ops_activation_HSigmoid_5
openvino_docs_ops_activation_HSwish_4
openvino_docs_ops_image_I420toBGR_8
openvino_docs_ops_image_I420toRGB_8
openvino_docs_ops_signals_IDFT_7
openvino_docs_ops_condition_If_8
openvino_docs_ops_image_Interpolate_1
openvino_docs_ops_image_Interpolate_4
openvino_docs_ops_normalization_LRN_1
openvino_docs_ops_sequence_LSTMCell_1
openvino_docs_ops_sequence_LSTMSequence_1
openvino_docs_ops_comparison_LessEqual_1
openvino_docs_ops_comparison_Less_1
openvino_docs_ops_arithmetic_Log_1
openvino_docs_ops_logical_LogicalAnd_1
openvino_docs_ops_logical_LogicalNot_1
openvino_docs_ops_logical_LogicalOr_1
openvino_docs_ops_logical_LogicalXor_1
openvino_docs_ops_activation_LogSoftmax_5
openvino_docs_ops_infrastructure_Loop_5
openvino_docs_ops_normalization_MVN_1
openvino_docs_ops_normalization_MVN_6
openvino_docs_ops_matrix_MatMul_1
openvino_docs_ops_sort_MatrixNonMaxSuppression_8
openvino_docs_ops_pooling_MaxPool_1
openvino_docs_ops_arithmetic_Maximum_1
openvino_docs_ops_arithmetic_Minimum_1
openvino_docs_ops_activation_Mish_4
openvino_docs_ops_arithmetic_Mod_1
openvino_docs_ops_sort_MulticlassNonMaxSuppression_8
openvino_docs_ops_arithmetic_Multiply_1
openvino_docs_ops_arithmetic_Negative_1
openvino_docs_ops_sort_NonMaxSuppression_1
openvino_docs_ops_sort_NonMaxSuppression_3
openvino_docs_ops_sort_NonMaxSuppression_4
openvino_docs_ops_sort_NonMaxSuppression_5
openvino_docs_ops_condition_NonZero_3
openvino_docs_ops_normalization_NormalizeL2_1
openvino_docs_ops_comparison_NotEqual_1
openvino_docs_ops_image_NV12toBGR_8
openvino_docs_ops_image_NV12toRGB_8
openvino_docs_ops_sequence_OneHot_1
openvino_docs_ops_activation_PReLU_1
openvino_docs_ops_detection_PSROIPooling_1
openvino_docs_ops_movement_Pad_1
openvino_docs_ops_infrastructure_Parameter_1
openvino_docs_ops_arithmetic_Power_1
openvino_docs_ops_detection_PriorBoxClustered_1
openvino_docs_ops_detection_PriorBox_1
openvino_docs_ops_detection_PriorBox_8
openvino_docs_ops_detection_Proposal_1
openvino_docs_ops_detection_Proposal_4
openvino_docs_ops_generation_RandomUniform_8
openvino_docs_ops_generation_Range_1
openvino_docs_ops_generation_Range_4
openvino_docs_ops_infrastructure_ReadValue_3
openvino_docs_ops_activation_ReLU_1
openvino_docs_ops_reduction_ReduceL1_4
openvino_docs_ops_reduction_ReduceL2_4
openvino_docs_ops_reduction_ReduceLogicalAnd_1
openvino_docs_ops_reduction_ReduceLogicalOr_1
openvino_docs_ops_reduction_ReduceMax_1
openvino_docs_ops_reduction_ReduceMean_1
openvino_docs_ops_reduction_ReduceMin_1
openvino_docs_ops_reduction_ReduceProd_1
openvino_docs_ops_reduction_ReduceSum_1
openvino_docs_ops_detection_RegionYolo_1
openvino_docs_ops_detection_ReorgYolo_1
openvino_docs_ops_shape_Reshape_1
openvino_docs_ops_infrastructure_Result_1
openvino_docs_ops_movement_Reverse_1
openvino_docs_ops_movement_ReverseSequence_1
openvino_docs_ops_sequence_RNNCell_3
openvino_docs_ops_sequence_RNNSequence_5
openvino_docs_ops_detection_ROIAlign_3
openvino_docs_ops_detection_ROIPooling_1
openvino_docs_ops_movement_Roll_7
openvino_docs_ops_arithmetic_Round_5
openvino_docs_ops_movement_ScatterElementsUpdate_3
openvino_docs_ops_movement_ScatterNDUpdate_3
openvino_docs_ops_movement_ScatterUpdate_3
openvino_docs_ops_condition_Select_1
openvino_docs_ops_activation_Selu_1
openvino_docs_ops_shape_ShapeOf_1
openvino_docs_ops_shape_ShapeOf_3
openvino_docs_ops_movement_ShuffleChannels_1
openvino_docs_ops_activation_Sigmoid_1
openvino_docs_ops_arithmetic_Sign_1
openvino_docs_ops_arithmetic_Sin_1
openvino_docs_ops_arithmetic_Sinh_1
openvino_docs_ops_activation_SoftMax_1
openvino_docs_ops_activation_SoftMax_8
openvino_docs_ops_activation_SoftPlus_4
openvino_docs_ops_movement_SpaceToBatch_2
openvino_docs_ops_movement_SpaceToDepth_1
openvino_docs_ops_movement_Split_1
openvino_docs_ops_arithmetic_Sqrt_1
openvino_docs_ops_arithmetic_SquaredDifference_1
openvino_docs_ops_shape_Squeeze_1
openvino_docs_ops_movement_StridedSlice_1
openvino_docs_ops_arithmetic_Subtract_1
openvino_docs_ops_activation_Swish_4
openvino_docs_ops_arithmetic_Tan_1
openvino_docs_ops_arithmetic_Tanh_1
openvino_docs_ops_infrastructure_TensorIterator_1
openvino_docs_ops_movement_Tile_1
openvino_docs_ops_sort_TopK_1
openvino_docs_ops_sort_TopK_3
openvino_docs_ops_movement_Transpose_1
openvino_docs_ops_shape_Unsqueeze_1
openvino_docs_ops_movement_VariadicSplit_1
@endsphinxdirective

View File

@ -1,5 +1,36 @@
# Inference Engine Samples {#openvino_docs_IE_DG_Samples_Overview} # Inference Engine Samples {#openvino_docs_IE_DG_Samples_Overview}
@sphinxdirective
.. toctree::
:maxdepth: 1
:hidden:
openvino_inference_engine_samples_classification_sample_async_README
openvino_inference_engine_ie_bridges_python_sample_classification_sample_async_README
openvino_inference_engine_samples_hello_classification_README
openvino_inference_engine_ie_bridges_c_samples_hello_classification_README
openvino_inference_engine_ie_bridges_python_sample_hello_classification_README
openvino_inference_engine_samples_hello_reshape_ssd_README
openvino_inference_engine_ie_bridges_python_sample_hello_reshape_ssd_README
openvino_inference_engine_samples_hello_nv12_input_classification_README
openvino_inference_engine_ie_bridges_c_samples_hello_nv12_input_classification_README
openvino_inference_engine_samples_hello_query_device_README
openvino_inference_engine_ie_bridges_python_sample_hello_query_device_README
openvino_inference_engine_samples_ngraph_function_creation_sample_README
openvino_inference_engine_ie_bridges_python_sample_ngraph_function_creation_sample_README
openvino_inference_engine_samples_object_detection_sample_ssd_README
openvino_inference_engine_ie_bridges_python_sample_object_detection_sample_ssd_README
openvino_inference_engine_ie_bridges_c_samples_object_detection_sample_ssd_README
openvino_inference_engine_samples_speech_sample_README
openvino_inference_engine_ie_bridges_python_sample_speech_sample_README
openvino_inference_engine_samples_style_transfer_sample_README
openvino_inference_engine_ie_bridges_python_sample_style_transfer_sample_README
openvino_inference_engine_samples_benchmark_app_README
openvino_inference_engine_tools_benchmark_tool_README
@endsphinxdirective
The Inference Engine sample applications are simple console applications that show how to utilize specific Inference Engine capabilities within an application, assist developers in executing specific tasks such as loading a model, running inference, querying specific device capabilities and etc. The Inference Engine sample applications are simple console applications that show how to utilize specific Inference Engine capabilities within an application, assist developers in executing specific tasks such as loading a model, running inference, querying specific device capabilities and etc.
After installation of Intel® Distribution of OpenVINO™ toolkit, С, C++ and Python* sample applications are available in the following directories, respectively: After installation of Intel® Distribution of OpenVINO™ toolkit, С, C++ and Python* sample applications are available in the following directories, respectively:
@ -102,7 +133,7 @@ for the debug configuration — in `<path_to_build_directory>/intel64/Debug/`.
The recommended Windows* build environment is the following: The recommended Windows* build environment is the following:
* Microsoft Windows* 10 * Microsoft Windows* 10
* Microsoft Visual Studio* 2017, or 2019. Make sure that C++ CMake tools for Windows is [enabled](https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=msvc-160#:~:text=The%20Visual%20C%2B%2B%20Tools%20for,Visual%20Studio%20generators%20are%20supported). * Microsoft Visual Studio* 2017, or 2019
* CMake* version 3.10 or higher * CMake* version 3.10 or higher
> **NOTE**: If you want to use Microsoft Visual Studio 2019, you are required to install CMake 3.14. > **NOTE**: If you want to use Microsoft Visual Studio 2019, you are required to install CMake 3.14.

View File

@ -1,27 +1,37 @@
Using Shape Inference {#openvino_docs_IE_DG_ShapeInference} # Using the Reshape Inference Feature {#openvino_docs_IE_DG_ShapeInference}
==========================================
OpenVINO™ provides the following methods for runtime model reshaping: ## Introduction (C++)
* **Set a new input shape** with the `InferenceEngine::CNNNetwork::reshape` method.<br> @sphinxdirective
The `InferenceEngine::CNNNetwork::reshape` method updates input shapes and propagates them down to the outputs of the model through all intermediate layers. .. raw:: html
<div id="switcher-cpp" class="switcher-anchor">C++</div>
@endsphinxdirective
OpenVINO™ provides two methods for runtime model reshaping: setting a new input shape and setting a new batch dimension value.
### Set a new input shape with the reshape() method
The `InferenceEngine::CNNNetwork::reshape` method updates input shapes and propagates them down to the outputs of the model through all intermediate layers.
> **NOTES**: > **NOTES**:
> - Starting with the 2021.1 release, the Model Optimizer converts topologies keeping shape-calculating sub-graphs by default, which enables correct shape propagation during reshaping in most cases. > - Starting with the 2021.1 release, the Model Optimizer converts topologies keeping shape-calculating sub-graphs by default, which enables correct shape propagation during reshaping in most cases.
> - Older versions of IRs are not guaranteed to reshape successfully. Please regenerate them with the Model Optimizer of the latest version of OpenVINO™.<br> > - Older versions of IRs are not guaranteed to reshape successfully. Please regenerate them with the Model Optimizer of the latest version of OpenVINO™.<br>
> - If an ONNX model does not have a fully defined input shape and the model was imported with the ONNX importer, reshape the model before loading it to the plugin. > - If an ONNX model does not have a fully defined input shape and the model was imported with the ONNX importer, reshape the model before loading it to the plugin.
* **Set a new batch dimension value** with the `InferenceEngine::CNNNetwork::setBatchSize` method.<br> ### Set a new batch dimension value with the setBatchSize() method
The meaning of a model batch may vary depending on the model design.
This method does not deduce batch placement for inputs from the model architecture.
It assumes that the batch is placed at the zero index in the shape for all inputs and uses the `InferenceEngine::CNNNetwork::reshape` method to propagate updated shapes through the model.
The method transforms the model before a new shape propagation to relax a hard-coded batch dimension in the model, if any. The meaning of a model batch may vary depending on the model design.
This method does not deduce batch placement for inputs from the model architecture.
It assumes that the batch is placed at the zero index in the shape for all inputs and uses the `InferenceEngine::CNNNetwork::reshape` method to propagate updated shapes through the model.
Use `InferenceEngine::CNNNetwork::reshape` instead of `InferenceEngine::CNNNetwork::setBatchSize` to set new input shapes for the model in case the model has: The method transforms the model before a new shape propagation to relax a hard-coded batch dimension in the model, if any.
* Multiple inputs with different zero-index dimension meanings
* Input without a batch dimension Use `InferenceEngine::CNNNetwork::reshape` instead of `InferenceEngine::CNNNetwork::setBatchSize` to set new input shapes for the model if the model has one of the following:
* 0D, 1D, or 3D shape
* Multiple inputs with different zero-index dimension meanings
* Input without a batch dimension
* 0D, 1D, or 3D shape
The `InferenceEngine::CNNNetwork::setBatchSize` method is a high-level API method that wraps the `InferenceEngine::CNNNetwork::reshape` method call and works for trivial models from the batch placement standpoint. The `InferenceEngine::CNNNetwork::setBatchSize` method is a high-level API method that wraps the `InferenceEngine::CNNNetwork::reshape` method call and works for trivial models from the batch placement standpoint.
Use `InferenceEngine::CNNNetwork::reshape` for other models. Use `InferenceEngine::CNNNetwork::reshape` for other models.
@ -37,10 +47,11 @@ Inference Engine takes three kinds of a model description as an input, which are
3. [nGraph function](../nGraph_DG/nGraph_dg.md) through the constructor of `InferenceEngine::CNNNetwork` 3. [nGraph function](../nGraph_DG/nGraph_dg.md) through the constructor of `InferenceEngine::CNNNetwork`
`InferenceEngine::CNNNetwork` keeps an `ngraph::Function` object with the model description internally. `InferenceEngine::CNNNetwork` keeps an `ngraph::Function` object with the model description internally.
The object should have fully defined input shapes to be successfully loaded to the Inference Engine plugins. The object should have fully-defined input shapes to be successfully loaded to Inference Engine plugins.
To resolve undefined input dimensions of a model, call the `CNNNetwork::reshape` method providing new input shapes before loading to the Inference Engine plugin. To resolve undefined input dimensions of a model, call the `CNNNetwork::reshape` method to provide new input shapes before loading to the Inference Engine plugin.
Run the following code right after `InferenceEngine::CNNNetwork` creation to explicitly check for model input names and shapes: Run the following code right after `InferenceEngine::CNNNetwork` creation to explicitly check for model input names and shapes:
```cpp ```cpp
CNNNetwork network = ... // read IR / ONNX model or create from nGraph::Function explicitly CNNNetwork network = ... // read IR / ONNX model or create from nGraph::Function explicitly
const auto parameters = network.getFunction()->get_parameters(); const auto parameters = network.getFunction()->get_parameters();
@ -55,37 +66,13 @@ To feed input data of a shape that is different from the model input shape, resh
Once the input shape of `InferenceEngine::CNNNetwork` is set, call the `InferenceEngine::Core::LoadNetwork` method to get an `InferenceEngine::ExecutableNetwork` object for inference with updated shapes. Once the input shape of `InferenceEngine::CNNNetwork` is set, call the `InferenceEngine::Core::LoadNetwork` method to get an `InferenceEngine::ExecutableNetwork` object for inference with updated shapes.
There are other approaches to reshape the model during the stage of <a href="_docs_MO_DG_prepare_model_convert_model_Converting_Model_General.html#when_to_specify_input_shapes">IR generation</a> or [nGraph::Function creation](../nGraph_DG/build_function.md). There are other approaches to reshape the model during the stage of <a href="_docs_MO_DG_prepare_model_convert_model_Converting_Model.html#when_to_specify_input_shapes">IR generation</a> or [nGraph::Function creation](../nGraph_DG/build_function.md).
Practically, some models are not ready to be reshaped. In this case, a new input shape cannot be set with the Model Optimizer or the `InferenceEngine::CNNNetwork::reshape` method. Practically, some models are not ready to be reshaped. In this case, a new input shape cannot be set with the Model Optimizer or the `InferenceEngine::CNNNetwork::reshape` method.
## Troubleshooting Reshape Errors ### Usage of Reshape Method <a name="usage_of_reshape_method"></a>
Operation semantics may impose restrictions on input shapes of the operation. The primary method of the feature is `InferenceEngine::CNNNetwork::reshape`. It gets new input shapes and propagates it from input to output for all intermediates layers of the given network.
Shape collision during shape propagation may be a sign that a new shape does not satisfy the restrictions.
Changing the model input shape may result in intermediate operations shape collision.
Examples of such operations:
- [Reshape](../ops/shape/Reshape_1.md) operation with a hard-coded output shape value
- [MatMul](../ops/matrix/MatMul_1.md) operation with the `Const` second input cannot be resized by spatial dimensions due to operation semantics
Model structure and logic should not change significantly after model reshaping.
- The Global Pooling operation is commonly used to reduce output feature map of classification models output.
Having the input of the shape [N, C, H, W], Global Pooling returns the output of the shape [N, C, 1, 1].
Model architects usually express Global Pooling with the help of the `Pooling` operation with the fixed kernel size [H, W].
During spatial reshape, having the input of the shape [N, C, H1, W1], Pooling with the fixed kernel size [H, W] returns the output of the shape [N, C, H2, W2], where H2 and W2 are commonly not equal to `1`.
It breaks the classification model structure.
For example, [publicly available Inception family models from TensorFlow*](https://github.com/tensorflow/models/tree/master/research/slim#pre-trained-models) have this issue.
- Changing the model input shape may significantly affect its accuracy.
For example, Object Detection models from TensorFlow have resizing restrictions by design.
To keep the model valid after the reshape, choose a new input shape that satisfies conditions listed in the `pipeline.config` file.
For details, refer to the <a href="_docs_MO_DG_prepare_model_convert_model_tf_specific_Convert_Object_Detection_API_Models.html#tf_od_custom_input_shape">Tensorflow Object Detection API models resizing techniques</a>.
## Usage of Reshape Method <a name="usage_of_reshape_method"></a>
The primary method of the feature is `InferenceEngine::CNNNetwork::reshape`.
It gets new input shapes and propagates it from input to output for all intermediates layers of the given network.
The method takes `InferenceEngine::ICNNNetwork::InputShapes` - a map of pairs: name of input data and its dimension. The method takes `InferenceEngine::ICNNNetwork::InputShapes` - a map of pairs: name of input data and its dimension.
The algorithm for resizing network is the following: The algorithm for resizing network is the following:
@ -100,9 +87,140 @@ Here is a code example:
@snippet snippets/ShapeInference.cpp part0 @snippet snippets/ShapeInference.cpp part0
Shape Inference feature is used in [Smart Classroom Demo](@ref omz_demos_smart_classroom_demo_cpp). The Shape Inference feature is used in [Smart Classroom Demo](@ref omz_demos_smart_classroom_demo_cpp).
## Extensibility ### Troubleshooting Reshape Errors
Inference Engine provides a special mechanism that allows to add the support of shape inference for custom operations. Operation semantics may impose restrictions on input shapes of the operation.
This mechanism is described in the [Extensibility documentation](Extensibility_DG/Intro.md) Shape collision during shape propagation may be a sign that a new shape does not satisfy the restrictions.
Changing the model input shape may result in intermediate operations shape collision.
Examples of such operations:
* [Reshape](../ops/shape/Reshape_1.md) operation with a hard-coded output shape value
* [MatMul](../ops/matrix/MatMul_1.md) operation with the `Const` second input cannot be resized by spatial dimensions due to operation semantics
Model structure and logic should not change significantly after model reshaping.
- The Global Pooling operation is commonly used to reduce output feature map of classification models output.
Having the input of the shape [N, C, H, W], Global Pooling returns the output of the shape [N, C, 1, 1].
Model architects usually express Global Pooling with the help of the `Pooling` operation with the fixed kernel size [H, W].
During spatial reshape, having the input of the shape [N, C, H1, W1], Pooling with the fixed kernel size [H, W] returns the output of the shape [N, C, H2, W2], where H2 and W2 are commonly not equal to `1`.
It breaks the classification model structure.
For example, [publicly available Inception family models from TensorFlow*](https://github.com/tensorflow/models/tree/master/research/slim#pre-trained-models) have this issue.
- Changing the model input shape may significantly affect its accuracy.
For example, Object Detection models from TensorFlow have resizing restrictions by design.
To keep the model valid after the reshape, choose a new input shape that satisfies conditions listed in the `pipeline.config` file.
For details, refer to the <a href="_docs_MO_DG_prepare_model_convert_model_tf_specific_Convert_Object_Detection_API_Models.html#tf_od_custom_input_shape">Tensorflow Object Detection API models resizing techniques</a>.
### Extensibility
The Inference Engine provides a special mechanism that allows adding support of shape inference for custom operations. This mechanism is described in the [Extensibility documentation](Extensibility_DG/Intro.md)
## Introduction (Python)
@sphinxdirective
.. raw:: html
<div id="switcher-python" class="switcher-anchor">Python</div>
@endsphinxdirective
OpenVINO™ provides the following methods for runtime model reshaping:
* Set a new input shape with the [IENetwork.reshape](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.reshape) method.
The [IENetwork.reshape](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.reshape) method updates input shapes and propagates them down to the outputs of the model through all intermediate layers.
**NOTES**:
* Model Optimizer converts topologies keeping shape-calculating sub-graphs by default, which enables correct shape propagation during reshaping in most cases.
* Older versions of IRs are not guaranteed to reshape successfully. Please regenerate them with the Model Optimizer of the latest version of OpenVINO™.
* If an ONNX model does not have a fully defined input shape and the model was imported with the ONNX importer, reshape the model before loading it to the plugin.
* Set a new batch dimension value with the [IENetwork.batch_size](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.batch_size) method.
The meaning of a model batch may vary depending on the model design. This method does not deduce batch placement for inputs from the model architecture. It assumes that the batch is placed at the zero index in the shape for all inputs and uses the [IENetwork.reshape](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.reshape) method to propagate updated shapes through the model.
The method transforms the model before a new shape propagation to relax a hard-coded batch dimension in the model, if any.
Use [IENetwork.reshape](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.reshape) rather than [IENetwork.batch_size](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.batch_size) to set new input shapes for the model if the model has:
* Multiple inputs with different zero-index dimension meanings
* Input without a batch dimension
* 0D, 1D, or 3D shape
The [IENetwork.batch_size](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.batch_size) method is a high-level API method that wraps the [IENetwork.reshape](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.reshape) method call and works for trivial models from the batch placement standpoint. Use [IENetwork.reshape](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.reshape) for other models.
Using the [IENetwork.batch_size](api/ie_python_api/_autosummary/openvino.inference_engine.IENetwork.html#openvino.inference_engine.IENetwork.batch_size) method for models with a non-zero index batch placement or for models with inputs that do not have a batch dimension may lead to undefined behaviour.
You can change input shapes multiple times using the `IENetwork.reshape` and `IENetwork.batch_size` methods in any order. If a model has a hard-coded batch dimension, use `IENetwork.batch_size` first to change the batch, then call `IENetwork.reshape` to update other dimensions, if needed.
Inference Engine takes three kinds of a model description as an input, which are converted into an IENetwork object:
1. Intermediate Representation (IR) through `IECore.read_network`
2. ONNX model through `IECore.read_network`
3. nGraph function through the constructor of IENetwork
IENetwork keeps an `ngraph::Function` object with the model description internally. The object should have fully defined input shapes to be successfully loaded to the Inference Engine plugins. To resolve undefined input dimensions of a model, call the `IENetwork.reshape` method providing new input shapes before loading to the Inference Engine plugin.
Run the following code right after IENetwork creation to explicitly check for model input names and shapes:
To feed input data of a shape that is different from the model input shape, reshape the model first.
Once the input shape of IENetwork is set, call the `IECore.load_network` method to get an ExecutableNetwork object for inference with updated shapes.
There are other approaches to reshape the model during the stage of IR generation or [nGraph function](https://docs.openvinotoolkit.org/latest/openvino_docs_nGraph_DG_PythonAPI.html#create_an_ngraph_function_from_a_graph) creation.
Practically, some models are not ready to be reshaped. In this case, a new input shape cannot be set with the Model Optimizer or the `IENetwork.reshape` method.
### Troubleshooting Reshape Errors
Operation semantics may impose restrictions on input shapes of the operation. Shape collision during shape propagation may be a sign that a new shape does not satisfy the restrictions. Changing the model input shape may result in intermediate operations shape collision.
Examples of such operations:
* Reshape operation with a hard-coded output shape value
* MatMul operation with the Const second input cannot be resized by spatial dimensions due to operation semantics
A model's structure and logic should not significantly change after model reshaping.
* The Global Pooling operation is commonly used to reduce output feature map of classification models output. Having the input of the shape [N, C, H, W], Global Pooling returns the output of the shape [N, C, 1, 1]. Model architects usually express Global Pooling with the help of the Pooling operation with the fixed kernel size [H, W]. During spatial reshape, having the input of the shape [N, C, H1, W1], Pooling with the fixed kernel size [H, W] returns the output of the shape [N, C, H2, W2], where H2 and W2 are commonly not equal to 1. It breaks the classification model structure. For example, publicly available Inception family models from TensorFlow* have this issue.
* Changing the model input shape may significantly affect its accuracy. For example, Object Detection models from TensorFlow have resizing restrictions by design. To keep the model valid after the reshape, choose a new input shape that satisfies conditions listed in the pipeline.config file. For details, refer to the Tensorflow Object Detection API models resizing techniques.
### Usage of the Reshape Method
The primary method of the feature is `IENetwork.reshape`. It gets new input shapes and propagates it from input to output for all intermediates layers of the given network. Use `IENetwork.input_info` to get names of input_layers and `.tensor_desc.dims` to get the current network input shape.
The following code example shows how to reshape a model to the size of an input image.
```python
import cv2
import numpy as np
from openvino.inference_engine import IECore
ie = IECore()
# Read an input image and transpose input to NCWH
image = cv2.imread(path_to_image_file)
input_image = image.transpose((2, 0, 1))
input_image = np.expand_dims(input_image, axis=0)
# Load the model and get input info
# Note that this model must support arbitrary input shapes
net = ie.read_network(model=path_to_xml_file)
input_layer = next(iter(net.input_info))
print(f"Input shape: {net.input_info[input_blob].tensor_desc.dims}")
# Call reshape
net.reshape({input_layer: input_image.shape})
print(f"New input shape: {net.input_info[input_blob].tensor_desc.dims}")
# Load the model to the device and proceed with inference
exec_net = ie.load_network(network=net, device_name="CPU")
```
### Extensibility
The Inference Engine provides a special mechanism that allows adding support of shape inference for custom operations. This mechanism is described in the [Extensibility documentation](Extensibility_DG/Intro.md)
### See Also:
[Hello Reshape Python Sample](../../inference_engine/ie_bridges/python/sample/hello_reshape_ssd/README.html)

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 47 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 246 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 96 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 79 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:17298610e06aed2ccfdad44c22a84a410ff4511456b28f6953091d9e593ab7fd
size 53668

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 203 KiB

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:83bcd7888d3843ddfd9a601288627e98f5874290c00b9988bf1beac9209f2e8d
size 79741

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d5cf2212b3634a264722b386899197a7f0fa56fbdad97c017d2733cc0d2694d4
size 105457

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dc7766d83d95b40e1dc6b5a63f7a801adf9780664f9ae6d4c88676c2f5b88688
size 107123

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 162 KiB

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c5bcecb8ddef4fdc797474da92ab6a9977a43d0d68e6fec75b2e0a41441042c2
size 22993

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9831807da09a8b1d75b5c20e5390526efdbacc7ccf9120221225d633abeb13be
size 47476

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4e9464a77d206d7fd642110a8c409f90b3885fb85e7d132012e86a5edfc72aeb
size 41636

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:72b8f5803b63465d349e5757fe59938269619f761d9a67dcfc03ab8e54bc0c3d
size 19158

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:62dac902ffb5f26ee034203910a77112ca87c7fc80a511cbd500930bb2919118
size 17983

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9fff52e5faaf108371db87e53959453216554152b15ca0432b1541f94def297e
size 19145

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:17298610e06aed2ccfdad44c22a84a410ff4511456b28f6953091d9e593ab7fd
size 53668

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e47c2b259bea6d3539f0c4556de4cc3a07f6d60af54e1cf32002b4a7bc2cc90a
size 25231

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:92d36b9527a3e316cd9eb2b6f5054c312466df004e4aa9c3458e165330bc6561
size 24157

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c47ede993681ba3f0a3e3f4274369ee1854365b1bcd1b5cb0f649a781fdf51bd
size 6215

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4a82b414dbc4f7ce2eae625bb7c9c7b88c154a7c476374683dd9886564560f67
size 7951

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9a4fce51076df19fbca04a36d6886765771f8ffc174bebbd751bfc77d91ab1f2
size 7081

Some files were not shown because too many files have changed in this diff Show More