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

This commit is contained in:
Ilya Lavrenov committed 2022-03-31 21:11:54 +03:00
commit fc37de4382
339 files changed
+7781 -4340

No files matched your search

+11 -1
View File
@@ -109,7 +109,8 @@ jobs:
set -e
$(REPO_DIR)/install_build_dependencies.sh
# Move jdk into contrib
sudo apt --assume-yes install openjdk-11-jdk
# 'clang' compiler is to check that samples can be built using it
sudo apt --assume-yes install openjdk-11-jdk clang
# For opencv-python: python3-setuptools and pip upgrade
python3 -m pip install --upgrade pip
python3 -m pip install -r $(REPO_DIR)/src/bindings/python/src/compatibility/openvino/requirements.txt
@@ -223,6 +224,14 @@ jobs:
displayName: 'Build cpp samples'
continueOnError: false
- script: |
export CC=clang
export CXX=clang++
$(INSTALL_DIR)/samples/cpp/build_samples.sh -i $(INSTALL_DIR)
workingDirectory: $(BUILD_SAMPLES_DIR)
displayName: 'Build cpp samples - clang'
continueOnError: false
- script: $(INSTALL_DIR)/samples/c/build_samples.sh -i $(INSTALL_DIR)
workingDirectory: $(BUILD_SAMPLES_DIR)
displayName: 'Build c samples'
@@ -341,6 +350,7 @@ jobs:
- script: |
export PATH=$HOME/.local/bin:$PATH
export IE_APP_PATH=$(INSTALL_DIR)/samples_bin
export LD_LIBRARY_PATH=$IE_APP_PATH:$LD_LIBRARY_PATH
export IE_APP_PYTHON_PATH=$(INSTALL_DIR)/samples/python/
export SHARE=$(INSTALL_DIR)/tests/smoke_tests/samples_smoke_tests_data/
export WORKSPACE=$(INSTALL_DIR)
-213
View File
@@ -1,213 +0,0 @@
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
DOCKER_CONTAINER_NAME= "openvino-onnx-ci-container"
DOCKER_IMAGE_TAG = "openvino-onnx-ci-image"
ONNX_MODEL_ZOO_SHA = "d58213534f2a4d1c4b19ba62b3bb5f544353256e"
BACKEND_CONFIGURATIONS = [
[ name: "Release", build_type: "Release" ],
[ name: "Debug", build_type: "Debug" ],
]
// workaround for aborting previous builds on PR update
@NonCPS
def stopPreviousRunningBuilds() {
def jobname = env.JOB_NAME
if (jobname.startsWith("onnx-ci/openvino onnx ci/openvino/PR")){
def buildnum = env.BUILD_NUMBER.toInteger()
def job = Jenkins.instance.getItemByFullName(jobname)
def job_newest = job.builds.first()
for (build in job.builds.reverse()[0..<-1]) {
if (build.isBuilding()){
echo "Stop task = ${build} because newest #${job_newest} is on the way"
build.doStop();
continue;
}
}
}
}
def getGitPrInfo(String project, String workdir) {
def gitPrInfo = [
prAuthorEmail : "",
commitAuthorEmail : "",
commitHash : "",
commitSubject : ""
]
try {
dir ("${workdir}/${project}") {
gitPrInfo.prAuthorEmail = sh (script: 'git log -1 --pretty="format:%ae" ', returnStdout: true).trim()
gitPrInfo.commitAuthorEmail = sh (script: 'git log -1 --pretty="format:%ce" ', returnStdout: true).trim()
gitPrInfo.commitSubject = sh (script: 'git log -1 --pretty="format:%H" ', returnStdout: true).trim()
gitPrInfo.commitHash = sh (script: 'git log -1 --pretty="format:%s" ', returnStdout: true).trim()
}
}
catch(e) {
echo "Failed to retrieve ${project} git repository information!"
echo "ERROR: ${e}"
}
return gitPrInfo
}
def notifyByEmail(def gitPrInfo) {
stage('Notify') {
String notifyPeople = "${gitPrInfo.prAuthorEmail}, ${gitPrInfo.commitAuthorEmail}"
emailext (
subject: "OpenVino CI: PR ${CHANGE_ID} ${currentBuild.result}!",
body: """
Status: ${currentBuild.result}
Pull Request Title: ${CHANGE_TITLE}
Pull Request: ${CHANGE_URL}
Branch: ${CHANGE_BRANCH}
Commit Hash: ${gitPrInfo.commitSubject}
Commit Subject: ${gitPrInfo.commitHash}
Jenkins Build: ${RUN_DISPLAY_URL}
""",
to: "${notifyPeople}"
)
}
}
def gitSubmoduleUpdate(String repository_name, String workdir) {
dir ("${workdir}/${repository_name}") {
sh label: "Init ${repository_name} submodules",
script:
"""
git submodule init && git submodule update \
--init \
--no-fetch \
--recursive
"""
}
}
def prepare_repository(String workdir) {
dir("${workdir}") {
println "Preparing repository in directory: ${workdir}"
checkout scm
gitSubmoduleUpdate(PROJECT_NAME, workdir)
}
}
def updateModels() {
sh """
./src/bindings/python/tests/test_onnx/model_zoo_preprocess.sh -d ${HOME}/ONNX_CI/models_data -o -s ${ONNX_MODEL_ZOO_SHA}
"""
}
def get_docker_container_name(Map configuration){
println "RUN get_docker_container_name for ${configuration.name}"
String docker_container_name = "${DOCKER_CONTAINER_NAME}_${BUILD_NUMBER}_${env.CHANGE_ID}_${configuration.name}"
return docker_container_name
}
def buildDockerImage(Map configuration, String workdir) {
String docker_image_tag = "${DOCKER_IMAGE_TAG}_${BUILD_NUMBER}_${env.CHANGE_ID}_${configuration.name}".toLowerCase()
println "docker_image_tag: ${docker_image_tag}"
updateModels()
sh """
docker build --tag=${docker_image_tag} \
--build-arg BUILD_TYPE=${configuration.build_type} \
--file=.ci/openvino-onnx/Dockerfile \
--build-arg http_proxy=${HTTP_PROXY} \
--build-arg https_proxy=${HTTPS_PROXY} .
"""
}
def runTests(Map configuration, String workdir) {
println "Run tests for ${configuration.name}"
String docker_image_tag = "${DOCKER_IMAGE_TAG}_${BUILD_NUMBER}_${env.CHANGE_ID}_${configuration.name}".toLowerCase()
String docker_container_name = get_docker_container_name(configuration)
// Run only basic unit tests in Debug configuration
if (configuration.build_type == "Debug") {
sh """
docker run --name ${docker_container_name} ${docker_image_tag}
"""
}
// Run unit-tests AND large model tests by default
else {
sh """
docker run --name ${docker_container_name} \
--volume ${HOME}/ONNX_CI/models_data/model_zoo/onnx_model_zoo_${ONNX_MODEL_ZOO_SHA}:/root/.onnx/model_zoo/onnx_model_zoo \
--volume ${HOME}/ONNX_CI/data/model_zoo/MSFT:/root/.onnx/model_zoo/MSFT \
${docker_image_tag} /bin/bash -c "tox && tox -e zoo_models"
"""
}
}
def getConfigurationsMap() {
def configurationsMap = [:]
for (backend in BACKEND_CONFIGURATIONS) {
def configuration = backend.clone()
configurationsMap[configuration.name] = {
stage(configuration.name) { CONFIGURATION_WORKFLOW(configuration) }
}
}
return configurationsMap
}
CONFIGURATION_WORKFLOW = { configuration ->
node("OpenVINO") {
String workdir = "${HOME}/workspace/${BUILD_NUMBER}_${env.CHANGE_ID}_${configuration.name}"
try {
PROJECT_NAME = "openvino"
stage("Clone repository") {
prepare_repository(workdir)
}
stage("Prepare Docker environment") {
dir("${workdir}") {
buildDockerImage(configuration, workdir)
}
}
stage("Run tests") {
timeout(time: 60, unit: 'MINUTES') {
runTests(configuration, workdir)
}
}
}
catch(e) {
// Set result to ABORTED if exception contains exit code of a process interrupted by SIGTERM
if ("$e".contains("143")) {
currentBuild.result = "ABORTED"
} else {
currentBuild.result = "FAILURE"
}
def gitPrInfo = getGitPrInfo(PROJECT_NAME, workdir)
notifyByEmail(gitPrInfo)
}
finally {
stage("Cleanup") {
String docker_container_name = get_docker_container_name(configuration)
sh """
docker rm -f ${docker_container_name}
rm -rf ${workdir}
"""
}
}
}
}
pipeline {
agent none
options {
skipDefaultCheckout true
timeout(activity: true, time: 120, unit: 'MINUTES')
}
stages {
stage('Parallel CI') {
steps {
stopPreviousRunningBuilds()
script {
parallelStagesMap = getConfigurationsMap()
parallel parallelStagesMap
}
}
}
}
}
-65
View File
@@ -1,65 +0,0 @@
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
timeout(30)
{
node(LABEL) {
BUILD_WORKSPACE = "$WORKSPACE/$BUILD_NUMBER"
WATCHDOG_ROOT = "$BUILD_WORKSPACE/.ci/openvino-onnx/watchdog"
VENV_PATH = "${BUILD_WORKSPACE}/.wdvenv"
try {
stage("Clone repository") {
dir ("$BUILD_WORKSPACE") {
checkout([$class: 'GitSCM', branches: [[name: "*/$BRANCH"]],
doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CloneOption', timeout: 30]], submoduleCfg: [],
userRemoteConfigs: [[credentialsId: "${GITHUB_KEY}", url: "${OPEN_VINO_URL}"]]])
}
}
stage("Prepare environment") {
sh """#!/bin/bash
if [ ! -d ${VENV_PATH} ]; then
python3 -m venv ${VENV_PATH}
source ${VENV_PATH}/bin/activate
pip install -r ${WATCHDOG_ROOT}/requirements.txt
fi
"""
}
stage("Run script") {
withCredentials([
usernamePassword(credentialsId: '7157091e-bc04-42f0-99fd-dc4da2922a55',
usernameVariable: 'username',
passwordVariable: 'password')])
{
dir ("$BUILD_WORKSPACE") {
sh """#!/bin/bash
source ${VENV_PATH}/bin/activate
export PYTHONHTTPSVERIFY=0
python ${WATCHDOG_ROOT}/src/main.py \
--msteams-url=${MSTEAMS_URL_FILE} \
--github-credentials '${username}' '${password}' \
--github-org=${GITHUB_ORG} \
--github-project=${GITHUB_PROJECT} \
--jenkins-token=${JENKINS_TOKEN_FILE} \
--jenkins-server=${JENKINS_SERVER} \
--jenkins-user=${JENKINS_USER} \
--ci-job=${CI_JOB_NAME} \
--watchdog-job=${WATCHDOG_JOB_NAME}
"""
}
}
}
} catch (e) {
echo "$e"
currentBuild.result = "FAILURE"
} finally {
stage("Cleanup") {
sh """
cd $BUILD_WORKSPACE
rm -rf ..?* .[!.]* *
"""
}
}
}
}
@@ -1,6 +0,0 @@
python-jenkins==1.7.0
retrying==1.3.3
pygithub==1.51
timeout-decorator==0.4.1
requests==2.23.0
wheel
@@ -1,108 +0,0 @@
#!/usr/bin/python3
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import logging
import timeout_decorator
from datetime import datetime
from retrying import retry
from github import Github, GithubException
# Logging
logging.basicConfig(format='%(name)s - %(levelname)s - %(message)s')
log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
_RETRY_LIMIT = 3
_RETRY_COOLDOWN_MS = 2000
_REQUEST_TIMEOUT_S = 10
class GitWrapper:
"""Class wrapping PyGithub API.
The purpose of this class is to wrap methods from PyGithub API used in Watchdog, for less error-prone and
more convenient use. Docs for used API, including wrapped methods can be found at:
https://pygithub.readthedocs.io/en/latest/introduction.html
:param github_credentials: Credentials used for GitHub
:param repository: GitHub repository name
:param project: GitHub project name
:type github_credentials: String
:type repository: String
:type project: String
"""
def __init__(self, github_credentials, repository, project):
self.git = Github(*github_credentials)
self.repository = repository
self.project = project
self.github_credentials = github_credentials
@retry(stop_max_attempt_number=_RETRY_LIMIT, wait_fixed=_RETRY_COOLDOWN_MS)
def get_git_time(self):
"""Retrieve time from GitHub.
Used to reliably determine time during Watchdog run.
:return: Datetime object describing current time
:rtype: datetime
"""
try:
datetime_object = self._get_git_time()
except ValueError as e:
raise GitWrapperError(str(e))
except GithubException as e:
message = 'GitHub Exception during API status retrieval. Exception: {}'.format(str(e))
raise GitWrapperError(message)
except timeout_decorator.TimeoutError:
message = 'GitHub Exception during API status retrieval. Timeout during API request.'
raise GitWrapperError(message)
return datetime_object
@retry(stop_max_attempt_number=_RETRY_LIMIT, wait_fixed=_RETRY_COOLDOWN_MS)
def get_pull_requests(self):
"""Retrieve paginated list of pull requests from GitHub.
:return: Paginated list of Pull Requests in GitHub repo
:rtype: github.PaginatedList.PaginatedList of github.PullRequest.PullRequest
"""
try:
prs = self._get_pull_requests()
except GithubException as e:
message = 'GitHub Exception during API status retrieval. Exception: {}'.format(str(e))
raise GitWrapperError(message)
return prs
@timeout_decorator.timeout(_REQUEST_TIMEOUT_S)
def _get_git_time(self):
"""Private method retrieving time from GitHub.
:return: Datetime object describing current time
:rtype: datetime
"""
datetime_string = self.git.get_api_status().raw_headers.get('date', '')
datetime_format = '%a, %d %b %Y %H:%M:%S %Z'
datetime_object = datetime.strptime(datetime_string, datetime_format)
return datetime_object
@timeout_decorator.timeout(_REQUEST_TIMEOUT_S)
def _get_pull_requests(self):
"""Private method retrieving pull requests from GitHub.
:return: Paginated list of Pull Requests in GitHub repo
:rtype: github.PaginatedList.PaginatedList of github.PullRequest.PullRequest
"""
return self.git.get_organization(self.repository).get_repo(self.project).get_pulls()
class GitWrapperError(Exception):
"""Base class for exceptions raised in GitWrapper.
:param message Explanation of the error
"""
def __init__(self, message):
self.message = message
log.exception(message)
@@ -1,91 +0,0 @@
#!/usr/bin/python3
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import requests
import jenkins
import logging
from retrying import retry
# Logging
logging.basicConfig(format='%(name)s - %(levelname)s - %(message)s')
log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
_RETRY_LIMIT = 3
_RETRY_COOLDOWN_MS = 5000
class JenkinsWrapper:
"""Class wrapping Python-Jenkins API.
The purpose of this class is to wrap methods from Python-Jenkins API used in Watchdog, for less error-prone and
more convenient use. Docs for used API, including wrapped methods can be found at:
https://python-jenkins.readthedocs.io/en/latest/
:param jenkins_token: Token used for Jenkins
:param jenkins_user: Username used to connect to Jenkins
:param jenkins_server: Jenkins server address
:type jenkins_token: String
:type jenkins_user: String
:type jenkins_server: String
"""
def __init__(self, jenkins_token, jenkins_user, jenkins_server):
self.jenkins_server = jenkins_server
self.jenkins = jenkins.Jenkins(jenkins_server, username=jenkins_user,
password=jenkins_token)
@retry(stop_max_attempt_number=_RETRY_LIMIT, wait_fixed=_RETRY_COOLDOWN_MS)
def get_build_console_output(self, job_name, build_number):
return self.jenkins.get_build_console_output(job_name, build_number)
@retry(stop_max_attempt_number=_RETRY_LIMIT, wait_fixed=_RETRY_COOLDOWN_MS)
def get_job_info(self, job_name):
return self.jenkins.get_job_info(job_name)
@retry(stop_max_attempt_number=_RETRY_LIMIT, wait_fixed=_RETRY_COOLDOWN_MS)
def get_build_info(self, job_name, build_number):
return self.jenkins.get_build_info(job_name, build_number)
@retry(stop_max_attempt_number=_RETRY_LIMIT, wait_fixed=_RETRY_COOLDOWN_MS)
def get_queue_item(self, queue_id):
"""Attempt to retrieve Jenkins job queue item.
Exception communicating queue doesn't exist is expected,
in that case method returns empty dict.
:param queue_id: Jenkins job queue ID number
:type queue_id: int
:return: Dictionary representing Jenkins job queue item
:rtype: dict
"""
try:
return self.jenkins.get_queue_item(queue_id)
except Exception as e:
# Exception 'queue does not exist' is expected behaviour when job is running
if 'queue' in str(e) and 'does not exist' in str(e):
return {}
else:
raise
@retry(stop_max_attempt_number=_RETRY_LIMIT, wait_fixed=_RETRY_COOLDOWN_MS)
def get_idle_ci_hosts(self):
"""Query Jenkins for idle servers.
Send GET request to Jenkins server, querying for idle servers labeled
for OpenVino-ONNX CI job.
:return: Number of idle hosts delegated to OpenVino-ONNX CI
:rtype: int
"""
jenkins_request_url = self.jenkins_server + 'label/ci&&onnx/api/json?pretty=true'
try:
log.info('Sending request to Jenkins: %s', jenkins_request_url)
r = requests.Request(method='GET', url=jenkins_request_url, verify=False)
response = self.jenkins.jenkins_request(r).json()
return int(response['totalExecutors']) - int(response['busyExecutors'])
except Exception as e:
log.exception('Failed to send request to Jenkins!\nException message: %s', str(e))
raise
-89
View File
@@ -1,89 +0,0 @@
#!/usr/bin/python3
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import argparse
import sys
from watchdog import Watchdog
DEFAULT_MSTEAMS_URL_FILE = '/home/lab_nerval/tokens/msteams_url'
DEFAULT_GITHUB_ORGANIZATION = 'openvinotoolkit'
DEFAULT_GITHUB_PROJECT = 'openvino'
DEFAULT_JENKINS_TOKEN_FILE = '/home/lab_nerval/tokens/crackerjack'
DEFAULT_JENKINS_SERVER = 'https://crackerjack.intel.com/'
DEFAULT_JENKINS_USER = 'lab_nerval'
DEFAULT_CI_JOB_NAME = 'onnx/OpenVino_CI'
DEFAULT_WATCHDOG_JOB_NAME = 'onnx/ci_watchdog'
def main(args):
"""
Read args passed to script, load tokens and run watchdog.
Keyword arguments:
:param args: arguments parsed by argparse ArgumentParser
:return: returns status code 0 on successful completion
"""
jenkins_server = args.jenkins_server.strip()
jenkins_user = args.jenkins_user.strip()
jenkins_token = open(args.jenkins_token).read().replace('\n', '').strip()
msteams_url = open(args.msteams_url).read().replace('\n', '').strip()
github_credentials = args.github_credentials
github_org = args.github_org
github_project = args.github_project
ci_job = args.ci_job.strip()
watchdog_job = args.watchdog_job.strip()
quiet = args.quiet
wd = Watchdog(jenkins_token=jenkins_token,
jenkins_server=jenkins_server,
jenkins_user=jenkins_user,
github_credentials=github_credentials,
git_org=github_org,
git_project=github_project,
msteams_url=msteams_url,
ci_job_name=ci_job,
watchdog_job_name=watchdog_job)
wd.run(quiet=quiet)
return 0
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--msteams-url', help='Path to MS Teams channel url to communicate messages.',
default=DEFAULT_MSTEAMS_URL_FILE, action='store', required=False)
parser.add_argument('--github-credentials', help='GitHub user credentials to access repo.',
nargs="+", required=True)
parser.add_argument('--github-org', help='Name of organization on GitHub.',
default=DEFAULT_GITHUB_ORGANIZATION, action='store', required=False)
parser.add_argument('--github-project', help='Name of project on GitHub.',
default=DEFAULT_GITHUB_PROJECT, action='store', required=False)
parser.add_argument('--jenkins-token', help='Path to Jenkins user token to access build info.',
default=DEFAULT_JENKINS_TOKEN_FILE, action='store', required=False)
parser.add_argument('--jenkins-server', help='Jenkins server address.',
default=DEFAULT_JENKINS_SERVER, action='store', required=False)
parser.add_argument('--jenkins-user', help='Jenkins user used to log in.',
default=DEFAULT_JENKINS_USER, action='store', required=False)
parser.add_argument('--ci-job', help='Jenkins CI job name.',
default=DEFAULT_CI_JOB_NAME, action='store', required=False)
parser.add_argument('--watchdog-job', help='Jenkins CI Watchdog job name.',
default=DEFAULT_WATCHDOG_JOB_NAME, action='store', required=False)
parser.add_argument('--quiet', help="Quiet mode - doesn\'t send message to communicator.",
action='store_true', required=False)
args = parser.parse_args()
sys.exit(main(args))
@@ -1,128 +0,0 @@
#!/usr/bin/python3
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import requests
class MSTeamsCommunicator:
"""Class communicating with MSTeams using Incoming Webhook.
The purpose of this class is to use MSTeams API to send message.
Docs for used API, including wrapped methods can be found at:
https://docs.microsoft.com/en-us/outlook/actionable-messages/send-via-connectors
"""
def __init__(self, _ci_alerts_channel_url):
self._ci_alerts_channel_url = _ci_alerts_channel_url
self._queued_messages = {
self._ci_alerts_channel_url: [],
}
@property
def messages(self):
"""
Get list of queued messages.
:return: List of queued messages
:return type: List[String]
"""
return self._queued_messages.values()
def queue_message(self, message):
"""
Queue message to be sent later.
:param message: Message content
:type message: String
"""
self._queued_messages[self._ci_alerts_channel_url].append(message)
def _parse_text(self, watchdog_log, message):
"""
Parse text to display as alert.
:param watchdog_log: Watchdog log content
:param message: Unparsed message content
:type watchdog_log: String
:type message: String
"""
message_split = message.split('\n')
log_url = None
if len(message_split) == 3:
log_url = message_split[-1]
title = message_split[0]
text = message_split[1]
header = watchdog_log.split(' - ')
header_formatted = '{} - [Watchdog Log]({})'.format(header[0], header[1])
return title, log_url, '{}\n\n{}'.format(header_formatted, text)
def _json_request_content(self, title, log_url, text_formatted):
"""
Create final json request to send message to MS Teams channel.
:param title: Title of alert
:param log_url: URL to PR
:param text_formatted: General content of alert - finally formatted
:type title: String
:type title: String
:type title: String
"""
data = {
'@context': 'https://schema.org/extensions',
'@type': 'MessageCard',
'themeColor': '0072C6',
'title': title,
'text': text_formatted,
'potentialAction':
[
{
'@type': 'OpenUri',
'name': 'Open PR',
'targets':
[
{
'os': 'default',
'uri': log_url,
},
],
},
],
}
return data
def _send_to_channel(self, watchdog_log, message_queue, channel_url):
"""
Send MSTeams message to specified channel.
:param watchdog_log: Watchdog log content
:param message_queue: Queued messages to send
:param channel_url: Channel url
:type watchdog_log: String
:type message_queue: String
:type channel_url: String
"""
for message in message_queue:
title, log_url, text_formatted = self._parse_text(watchdog_log, message)
data = self._json_request_content(title, log_url, text_formatted)
try:
requests.post(url=channel_url, json=data)
except Exception as ex:
raise Exception('!!CRITICAL!! MSTeamsCommunicator: Could not send message '
'due to {}'.format(ex))
def send_message(self, watchdog_log, quiet=False):
"""
Send queued messages as single communication.
:param watchdog_log: Watchdog log content
:param quiet: Flag for disabling sending report through MS Teams
:type watchdog_log: String
:type quiet: Boolean
"""
for channel, message_queue in self._queued_messages.items():
if not quiet and message_queue:
self._send_to_channel(watchdog_log, message_queue, channel)
-505
View File
@@ -1,505 +0,0 @@
#!/usr/bin/python3
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import datetime
import time
import re
import logging
import requests
from ms_teams_communicator import MSTeamsCommunicator
from jenkins_wrapper import JenkinsWrapper
from jenkins import NotFoundException
from git_wrapper import GitWrapper, GitWrapperError
import os
import json
# Logging
logging.basicConfig(format='%(name)s - %(levelname)s - %(message)s')
log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
# Watchdog static constant variables
_SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
_BUILD_DURATION_THRESHOLD = datetime.timedelta(minutes=60)
_CI_START_THRESHOLD = datetime.timedelta(minutes=30)
_AWAITING_JENKINS_THRESHOLD = datetime.timedelta(minutes=5)
_WATCHDOG_DIR = os.path.expanduser('~')
_PR_REPORTS_CONFIG_KEY = 'pr_reports'
_CI_BUILD_FAIL_MESSAGE = 'ERROR: py3: commands failed'
_CI_BUILD_SUCCESS_MESSAGE = 'py3: commands succeeded'
_GITHUB_CI_CHECK_NAME = 'OpenVINO-ONNX'
INTERNAL_ERROR_MESSAGE_HEADER = '!!! --- !!! INTERNAL WATCHDOG ERROR !!! --- !!!'
ERROR_MESSAGE_HEADER = '!!! OpenVino-ONNX CI Error !!!'
WARNING_MESSAGE_HEADER = 'OpenVino-ONNX CI WARNING'
INFO_MESSAGE_HEADER = 'OpenVino-ONNX CI INFO'
class Watchdog:
"""Class describing OpenVino-ONNX-CI Watchdog.
Watchdog connects to GitHub and retrieves the list of current pull requests (PRs) in
OpenVino repository. Then it connects to specified Jenkins server to
check CI jobs associated with every PR. Watchdog verifies time durations for Jenkins
initial response, job queue and execution against time treshold constants. Every fail
is logged and reported through MS Teams communicators.
:param jenkins_token: Token used for Jenkins
:param jenkins_server: Jenkins server address
:param jenkins_user: Username used to connect to Jenkins
:param github_credentials: Credentials used to connect to GitHub
:param msteams_url: URL used to connect to MS Teams channel
:param ci_job_name: OpenVino-ONNX CI job name used in Jenkins
:param watchdog_job_name: Watchdog job name used in Jenkins
:type jenkins_token: String
:type jenkins_server: String
:type jenkins_user: String
:type github_credentials: String
:type msteams_url: String
:type ci_job_name: String
:type watchdog_job_name: String
.. note::
Watchdog and OpenVino-ONNX CI job must be placed on the same Jenkins server.
"""
def __init__(self, jenkins_token, jenkins_server, jenkins_user, github_credentials, git_org,
git_project, msteams_url, ci_job_name, watchdog_job_name):
self._config_path = os.path.join(_WATCHDOG_DIR, '{}/.{}_ci_watchdog.json'.format(_WATCHDOG_DIR, git_project))
# Jenkins Wrapper object for CI job
self._jenkins = JenkinsWrapper(jenkins_token,
jenkins_user=jenkins_user,
jenkins_server=jenkins_server)
# Load GitHub token and log in, retrieve pull requests
self._git = GitWrapper(github_credentials, repository=git_org, project=git_project)
# Create MS Teams api object
self._msteams_hook = MSTeamsCommunicator(msteams_url)
self._ci_job_name = ci_job_name.lower()
self._watchdog_job_name = watchdog_job_name
# Read config file
self._config = self._read_config_file()
# Time at Watchdog initiation
self._now_time = datetime.datetime.now()
self._current_prs = {}
self._ms_teams_enabled = True
def run(self, quiet=False):
"""Run main watchdog logic.
Retrieve list of pull requests and pass it to the method responsible for checking them.
:param quiet: Flag for disabling sending report through communicator
:type quiet: Boolean
"""
try:
pull_requests = self._git.get_pull_requests()
except GitWrapperError:
message = 'Failed to retrieve Pull Requests!'
log.exception(message)
self._queue_message(message, message_severity='internal')
# Check all pull requests
for pr in pull_requests:
try:
self._check_pr(pr)
except Exception as e:
log.exception(str(e))
self._queue_message(str(e), message_severity='internal', pr=pr)
self._update_config()
self._send_message(quiet=quiet)
def _read_config_file(self):
"""Read Watchdog config file stored on the system.
The file stores every fail already reported along with timestamp. This
mechanism is used to prevent Watchdog from reporting same failure
multiple times. In case there's no config under the expected path,
appropriate data structure is created and returned.
:return: Returns dict of dicts with reported fails with their timestamps
:rtype: dict of dicts
"""
if os.path.isfile(self._config_path):
log.info('Reading config file in: {}'.format(self._config_path))
file = open(self._config_path, 'r')
data = json.load(file)
else:
log.info('No config file found in: {}'.format(self._config_path))
data = {_PR_REPORTS_CONFIG_KEY: {}}
return data
def _check_pr(self, pr):
"""Check pull request (if there's no reason to skip).
Retrieve list of statuses for every PR's last commit and interpret them. Filters out statuses
unrelated to OpenVino-ONNX Jenkins CI and passes relevant statuses to method that interprets them.
If no commit statuses related to Jenkins are available after time defined by
**_AWAITING_JENKINS_THRESHOLD** calls appropriate method to check for builds waiting in queue.
:param pr: GitHub Pull Requests
:type pr: github.PullRequest.PullRequest
"""
log.info('===============================================')
log.info('Checking PR#{}'.format(pr.number))
# Get last Jenkins status
last_status = self._get_last_status(pr)
# Append PR checked in current run for Watchdog config
self._current_prs[str(pr.number)] = self._get_pr_timestamps(pr, last_status)
if self._should_ignore(pr) or self._updated_since_last_run(pr):
log.info('Ignoring PR#{}'.format(pr.number))
return
# Calculate time passed since PR update (any commit, merge or comment)
pr_time_delta = self._now_time - pr.updated_at
if last_status:
# Interpret found CI statuses
log.info('Last status: {} at {}'.format(last_status.description, last_status.updated_at))
self._interpret_status(last_status, pr)
elif pr_time_delta > _CI_START_THRESHOLD:
# If there's no status after assumed time - check if build is waiting in queue
log.info('CI for PR {}: NO JENKINS STATUS YET'.format(pr.number))
self._check_missing_status(pr)
@staticmethod
def _get_pr_timestamps(pr, last_status):
"""Get dict containing PR timestamp and last status timestamp.
:param pr: Single PR being currently checked
:type pr: github.PullRequest.PullRequest
:return: Dictionary with PR and last status update timestamps
:rtype: dict
"""
pr_timestamp = time.mktime(pr.updated_at.timetuple())
if last_status:
status_timestamp = time.mktime(last_status.updated_at.timetuple())
else:
status_timestamp = None
pr_dict = {'pr_timestamp': pr_timestamp,
'status_timestamp': status_timestamp}
return pr_dict
@staticmethod
def _get_last_status(pr):
"""Get last commit status posted from Jenkins.
:param pr: Single PR being currently checked
:type pr: github.PullRequest.PullRequest
:return: Either last PR status posted from Jenkins or None
:rtype: github.CommitStatus.CommitStatus
"""
# Find last commit in PR
last_commit = pr.get_commits().reversed[0]
# Get statuses and filter them to contain only those related to Jenkins CI
# and check if CI in Jenkins started
statuses = last_commit.get_statuses()
jenk_statuses = [stat for stat in statuses if
_GITHUB_CI_CHECK_NAME in stat.context]
try:
last_status = jenk_statuses[0]
except IndexError:
last_status = None
return last_status
@staticmethod
def _should_ignore(pr):
"""Determine if PR should be ignored.
:param pr: Single PR being currently checked
:type pr: github.PullRequest.PullRequest
:return: Returns True if PR should be ignored
:rtype: Bool
"""
# Ignore PR if it has WIP label or WIP in title
if 'WIP' in pr.title:
log.info('PR#{} should be ignored. WIP tag in title.'.format(pr.number))
return True
label_names = [label.name for label in pr.labels]
if 'WIP' in label_names:
log.info('PR#{} should be ignored. WIP label present.'.format(pr.number))
return True
# Ignore PR if base ref is not master
if 'master' not in pr.base.ref:
log.info('PR#{} should be ignored. Base ref is not master'.format(pr.number))
return True
# Ignore PR if mergeable state is 'dirty' or 'behind'.
# Practically this ignores PR in case of merge conflicts
ignored_mergeable_states = ['behind', 'dirty', 'draft']
if pr.mergeable_state in ignored_mergeable_states:
log.info('PR#{} should be ignored. Mergeable state is {}. '.format(pr.number, pr.mergeable_state))
return True
# If no criteria for ignoring PR are met - return false
return False
def _updated_since_last_run(self, pr):
# Ignore if PR was already checked and there was no update in meantime
pr_number = str(pr.number)
current_pr_timestamps = self._current_prs.get(pr_number)
last_pr_timestamps = self._config[_PR_REPORTS_CONFIG_KEY].get(pr_number)
if current_pr_timestamps == last_pr_timestamps:
log.info('PR#{} - No update since last check'.format(pr.number))
return True
else:
return False
def _check_missing_status(self, pr):
"""Verify if missing status is expected.
This method checks if CI build for last was scheduled and still waits in queue for
executor.
:param pr: Single PR being currently checked
:type pr: github.PullRequest.PullRequest
"""
pr_time_delta = self._now_time - pr.updated_at
try:
build_number = self._build_scheduled(pr)
if self._build_in_queue(pr, build_number):
message = ('PR# {}: build waiting in queue after {} minutes.'
.format(pr.number, pr_time_delta.seconds / 60))
severity = 'warning'
else:
message = ('PR# {}: missing status on GitHub after {} minutes.'
.format(pr.number, pr_time_delta.seconds / 60))
severity = 'error'
self._queue_message(message, message_severity=severity, pr=pr)
except TypeError:
log.info('Committer outside of OpenVino organization')
def _build_scheduled(self, pr):
"""Check if Jenkins build corresponding to PR was scheduled.
This method takes last Jenkins build for given PR and compares hash from Jenkins console output
and sha from PR object to determine if CI build for appropriate commit was scheduled.
:param pr: Single PR being currently checked
:type pr: github.PullRequest.PullRequest
:return: Returns build number or -1 if no build found
:rtype: int
"""
pr_number = str(pr.number)
project_name_full = self._ci_job_name + '/PR-' + pr_number
try:
# Retrieve console output from last Jenkins build for job corresponding to this PR
last_build_number = self._jenkins.get_job_info(project_name_full)['lastBuild']['number']
console_output = self._jenkins.get_build_console_output(project_name_full, last_build_number)
# Check if CI build was scheduled - commit hash on GH must match hash in last Jenkins build console output
# Retrieve hash from Jenkins output
match_string = '(?:Obtained .ci/[a-zA-Z/]+Jenkinsfile from ([a-z0-9]{40}))'
retrieved_sha = re.search(match_string, console_output).group(1)
if retrieved_sha == pr.get_commits().reversed[0].sha:
return last_build_number
else:
return -1
except (NotFoundException, AttributeError, requests.exceptions.HTTPError):
message = ('PR #{}: Jenkins build corresponding to commit {} not found!'
.format(pr_number, pr.get_commits().reversed[0].sha))
self._queue_message(message, message_severity='error', pr=pr)
return -1
def _build_in_queue(self, pr, build_number):
"""Check if Jenkins build waits in queue.
This method verifies if CI build is waiting in queue based on console output.
:param pr: Single PR being currently checked
:param build_number: Jenkins build number to retrieve console output from
:type pr: github.PullRequest.PullRequest
:type build_number: int
:return: Returns True if CI build is waiting in queue
:rtype: Bool
"""
pr_number = str(pr.number)
project_name_full = self._ci_job_name + '/PR-' + pr_number
# Retrieve console output
try:
console_output = self._jenkins.get_build_console_output(project_name_full, build_number)
except NotFoundException:
return False
# Check if build is waiting in queue (and not already running on an executor)
if 'Waiting for next available executor on' in console_output \
and 'Running on' not in console_output:
log.info('CI for PR %s: WAITING IN QUEUE', pr_number)
return True
else:
return False
def _interpret_status(self, status, pr):
"""
Verify GitHub status passed to the method.
This method verifies last commit status for given PR, calling appropriate methods
to further validate the status.
:param status: GitHub commit status
:param pr: Single PR being currently checked
:type status: github.CommitStatus.CommitStatus
:type pr: github.PullRequest.PullRequest
"""
try:
# Retrieve build number for Jenkins build related to this PR
build_number = self._retrieve_build_number(status.target_url)
# CI build finished - verify if expected output is present
finished_statuses = ['Build finished', 'This commit cannot be built', 'This commit looks good']
pending_statuses = ['This commit is being built', 'Testing in progress',
'This commit is scheduled to be built']
if any(phrase in status.description for phrase in finished_statuses):
self._check_finished(pr, build_number)
# CI build in progress - verify timeouts for build queue and duration
elif any(phrase in status.description for phrase in pending_statuses):
self._check_in_progress(pr, build_number)
else:
message = 'ONNX CI job for PR# {}: unrecognized status: {}'.format(pr.number, status.description)
self._queue_message(message, message_severity='error', pr=pr)
except Exception:
# Log Watchdog internal error in case any status can't be properly verified
message = 'Failed to verify status "{}" for PR# {}'.format(status.description, pr.number)
log.exception(message)
self._queue_message(message, message_severity='internal', pr=pr)
def _retrieve_build_number(self, url):
"""Retrieve Jenkins CI job build number from URL address coming from GitHub commit status.
:param url: URL address from GitHub commit status
:type url: String
:return: Returns build number
:rtype: int
"""
# Retrieve the build number from url string
match_obj = re.search('(?:/PR-[0-9]+/)([0-9]+)', url)
try:
number = int(match_obj.group(1))
return number
except Exception:
log.exception('Failed to retrieve build number from url link: %s', url)
raise
def _queue_message(self, message, message_severity='info', pr=None):
"""Add a message to message queue in communicator object.
The queued message is constructed based on message string passed as
a method argument and message header. Message header is mapped to message severity
also passed as an argument.
:param message: Message content
:param message_severity: Message severity level
:type message: String
:type message_severity: int
"""
log.info(message)
internal = False
if 'internal' in message_severity:
message_header = INTERNAL_ERROR_MESSAGE_HEADER
internal = True
elif 'error' in message_severity:
message_header = ERROR_MESSAGE_HEADER
elif 'warning' in message_severity:
message_header = WARNING_MESSAGE_HEADER
else:
message_header = INFO_MESSAGE_HEADER
# If message is related to PR attatch url
if pr:
message = message + '\n' + pr.html_url
send = message_header + '\n' + message
if self._ms_teams_enabled:
self._msteams_hook.queue_message(send)
def _check_finished(self, pr, build_number):
"""Verify if finished build output contains expected string for either fail or success.
:param pr: Single PR being currently checked
:param build_number: Jenkins CI job build number
:type pr: github.PullRequest.PullRequest
:type build_number: int
"""
pr_number = str(pr.number)
log.info('CI for PR %s: FINISHED', pr_number)
# Check if FINISH was valid FAIL / SUCCESS
project_name_full = self._ci_job_name + '/PR-' + pr_number
build_output = self._jenkins.get_build_console_output(project_name_full, build_number)
if _CI_BUILD_FAIL_MESSAGE not in build_output \
and _CI_BUILD_SUCCESS_MESSAGE not in build_output:
message = ('ONNX CI job for PR #{}: finished but no tests success or fail '
'confirmation is present in console output!'.format(pr_number))
self._queue_message(message, message_severity='error', pr=pr)
def _send_message(self, quiet=False):
"""Send messages queued in MS Teams objects to designated channel.
Queued messages are being sent as a single communication.
:param quiet: Flag for disabling sending report through communicator
:type quiet: Boolean
"""
if any(messages for messages in self._msteams_hook.messages):
try:
watchdog_build = self._jenkins.get_job_info(self._watchdog_job_name)['lastBuild']
watchdog_build_number = watchdog_build['number']
watchdog_build_link = watchdog_build['url']
except Exception:
watchdog_build_number = 'UNKNOWN'
watchdog_build_link = self._jenkins.jenkins_server
send = self._watchdog_job_name + '- build ' + str(
watchdog_build_number) + ' - ' + watchdog_build_link
if self._ms_teams_enabled:
self._msteams_hook.send_message(send, quiet=quiet)
else:
log.info('Nothing to report.')
def _check_in_progress(self, pr, build_number):
"""Check if CI build succesfully started.
Checks if build started within designated time threshold, and job is
currently running - it didn't cross the time threshold.
:param pr: Single PR being currently checked
:param build_number: Jenkins CI job build number
:type pr: github.PullRequest.PullRequest
:type build_number: int
"""
pr_number = str(pr.number)
log.info('CI for PR %s: TESTING IN PROGRESS', pr_number)
project_name_full = self._ci_job_name + '/PR-' + pr_number
build_info = self._jenkins.get_build_info(project_name_full, build_number)
build_datetime = datetime.datetime.fromtimestamp(build_info['timestamp'] / 1000.0)
build_delta = self._now_time - build_datetime
log.info('Build %s: IN PROGRESS, started: %s minutes ago', str(build_number),
str(build_delta))
# If build still waiting in queue
if build_delta > _CI_START_THRESHOLD and self._build_in_queue(pr, build_number):
message = ('ONNX CI job build #{}, for PR #{} waiting in queue after {} '
'minutes'.format(build_number, pr_number, str(build_delta.seconds / 60)))
self._queue_message(message, message_severity='warning', pr=pr)
elif build_delta > _BUILD_DURATION_THRESHOLD:
# CI job take too long, possibly froze - communicate failure
message = ('ONNX CI job build #{}, for PR #{} started, '
'but did not finish in designated time of {} '
'minutes!'.format(build_number, pr_number,
str(_BUILD_DURATION_THRESHOLD.seconds / 60)))
self._queue_message(message, message_severity='error', pr=pr)
def _update_config(self):
"""Update Watchdog config file with PRs checked in current Watchdog run, remove old entries.
:param current_prs: List of PR numbers checked during current Watchdog run
:type current_prs: list of ints
"""
# Cleanup config of old reports
log.info('Writing to config file at: {}'.format(self._config_path))
new_config = {_PR_REPORTS_CONFIG_KEY: self._current_prs}
file = open(self._config_path, 'w+')
json.dump(new_config, file)
+58 -11
View File
@@ -1,4 +1,4 @@
name: IE Python Checks
name: Python API Checks
on:
workflow_dispatch:
@@ -23,8 +23,9 @@ jobs:
with:
python-version: '3.6'
- name: Install dependencies
run: python -m pip install -r src/bindings/python/src/compatibility/openvino/requirements_dev.txt
- name: Run Flake on samples
run: python -m pip install -r src/bindings/python/requirements_test.txt
# samples code-style
- name: Run flake8 on samples
run: python -m flake8 ./ --config=setup.cfg
working-directory: samples/python
- name: Create code style diff for samples
@@ -38,21 +39,53 @@ jobs:
with:
name: samples_diff
path: samples_diff.diff
- name: Run Flake on src
# IE Python API Flake code-style
- name: Run flake8 on IE Python API
run: python -m flake8 ./ --config=setup.cfg
working-directory: src/bindings/python/src/compatibility/openvino
- name: Create code style diff for Python src
- name: Create code style diff for IE Python API
if: failure()
run: |
python -m black -l 160 -S ./
git diff > src_diff.diff
git diff > ie_python_diff.diff
working-directory: src/bindings/python/src/compatibility/openvino
- uses: actions/upload-artifact@v2
if: failure()
with:
name: src_diff
path: src_diff.diff
- name: Run Flake on wheel
name: ie_python_diff
path: ie_python_diff.diff
# nGraph Python API Flake code-style
- name: Run flake8 on nGraph Python API
run: python -m flake8 ./src/compatibility/ngraph --config=setup.cfg
working-directory: src/bindings/python
- name: Create code style diff for nGraph Python API
if: failure()
run: |
python -m black -l 160 -S ./
git diff > pyngraph_diff.diff
working-directory: src/bindings/python/src/compatibility/ngraph
- uses: actions/upload-artifact@v2
if: failure()
with:
name: pyngraph_diff
path: pyngraph_diff.diff
# Python API 2.0 Flake code-style
- name: Run flake8 on Python API 2.0
run: python -m flake8 ./src/openvino --config=setup.cfg
working-directory: src/bindings/python
- name: Create code style diff for Python API 2.0
if: failure()
run: |
python -m black -l 160 -S ./
git diff > pyopenvino_diff.diff
working-directory: src/bindings/python/src/openvino
- uses: actions/upload-artifact@v2
if: failure()
with:
name: pyopenvino_diff
path: pyopenvino_diff.diff
# wheel Flake code-style
- name: Run flake8 on wheel
run: python -m flake8 ./ --config=../setup.cfg
working-directory: src/bindings/python/wheel
- name: Create code style diff for wheel
@@ -66,10 +99,24 @@ jobs:
with:
name: wheel_diff
path: wheel_diff.diff
- name: Run MyPy
# Python API 2.0 tests Flake code-style
- name: Run flake8 on python tests
# ignore lack of docs in tests
run: python -m flake8 tests/ --config=setup.cfg
working-directory: src/bindings/python
# IE Python API mypy check
- name: Run mypy on IE Python API
run: python -m mypy ./ --config-file ./setup.cfg
working-directory: src/bindings/python/src/compatibility/openvino
# nGraph Python API mypy check
- name: Run mypy on nGraph Python API
run: python -m mypy ./src/compatibility/ngraph --config-file ./setup.cfg
working-directory: src/bindings/python
# Python API 2.0 mypy check
- name: Run mypy on Python API 2.0
run: python -m mypy ./src/openvino --config-file ./setup.cfg
working-directory: src/bindings/python
- name: Run Bandit
run: python -m bandit -r ./ -f screen
working-directory: src/bindings/python/src/compatibility/openvino
+1 -3
View File
@@ -4,7 +4,7 @@
if(DEFINED BUILD_SHARED_LIBS AND NOT BUILD_SHARED_LIBS)
# 'target_link_libraries' does not work correctly when called from
# different directly where 'add_library' is called: CMake generates
# different directory where 'add_library' is called: CMake generates
# incorrect OpenVINOConfig.cmake in this case
cmake_minimum_required(VERSION 3.17)
else()
@@ -17,8 +17,6 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "CMake build type" FORCE)
endif()
set(IE_MAIN_SOURCE_DIR ${OpenVINO_SOURCE_DIR}/inference-engine)
find_package(IEDevScripts REQUIRED
PATHS "${OpenVINO_SOURCE_DIR}/cmake/developer_package"
NO_CMAKE_FIND_ROOT_PATH
+1 -1
View File
@@ -44,7 +44,7 @@ Please report questions, issues and suggestions using:
[Open Model Zoo]:https://github.com/openvinotoolkit/open_model_zoo
[OpenVINO™ Runtime]:https://docs.openvino.ai/latest/openvino_docs_OV_Runtime_User_Guide.html
[Model Optimizer]:https://docs.openvino.ai/latest/openvino_docs_MO_DG_Deep_Learning_Model_Optimizer_DevGuide.html
[Post-Training Optimization Tool]:https://docs.openvino.ai/latest/pot_README.html
[Post-Training Optimization Tool]:https://docs.openvino.ai/latest/pot_introduction.html
[Samples]:https://github.com/openvinotoolkit/openvino/tree/master/samples
[tag on StackOverflow]:https://stackoverflow.com/search?q=%23openvino
+44 -27
View File
@@ -23,9 +23,7 @@ message(STATUS "MODELS_PATH=" ${MODELS_PATH})
fetch_models_and_validation_set()
if(COMMAND get_linux_name)
get_linux_name(LINUX_OS_NAME)
endif()
get_linux_name(LINUX_OS_NAME)
if(CMAKE_CROSSCOMPILING AND CMAKE_HOST_SYSTEM_NAME MATCHES Linux AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
set(protoc_version "3.18.2")
@@ -109,16 +107,6 @@ if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO" AND NOT ENABLE_SYST
TARGET_PATH "${TEMP}/tbb"
ENVIRONMENT "TBBROOT"
SHA256 "f1c9b9e2861efdaa01552bd25312ccbc5feeb45551e5f91ae61e29221c5c1479")
if(ENABLE_TBBBIND_2_5)
RESOLVE_DEPENDENCY(TBBBIND_2_5
ARCHIVE_WIN "tbbbind_2_5_static_win_v1.zip"
TARGET_PATH "${TEMP}/tbbbind_2_5"
ENVIRONMENT "TBBBIND_2_5_ROOT"
SHA256 "a67afeea8cf194f97968c800dab5b5459972908295242e282045d6b8953573c1")
else()
message(WARNING "prebuilt TBBBIND_2_5 is not available.
Build oneTBB from sources and set TBBROOT environment var before OpenVINO cmake configure")
endif()
elseif(ANDROID) # Should be before LINUX due LINUX is detected as well
RESOLVE_DEPENDENCY(TBB
ARCHIVE_ANDROID "tbb2020_20200404_android.tgz"
@@ -131,16 +119,6 @@ if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO" AND NOT ENABLE_SYST
TARGET_PATH "${TEMP}/tbb"
ENVIRONMENT "TBBROOT"
SHA256 "95b2f3b0b70c7376a0c7de351a355c2c514b42c4966e77e3e34271a599501008")
if(ENABLE_TBBBIND_2_5)
RESOLVE_DEPENDENCY(TBBBIND_2_5
ARCHIVE_LIN "tbbbind_2_5_static_lin_v2.tgz"
TARGET_PATH "${TEMP}/tbbbind_2_5"
ENVIRONMENT "TBBBIND_2_5_ROOT"
SHA256 "865e7894c58402233caf0d1b288056e0e6ab2bf7c9d00c9dc60561c484bc90f4")
else()
message(WARNING "prebuilt TBBBIND_2_5 is not available.
Build oneTBB from sources and set TBBROOT environment var before OpenVINO cmake configure")
endif()
elseif(LINUX AND AARCH64)
RESOLVE_DEPENDENCY(TBB
ARCHIVE_LIN "keembay/tbb2020_38404_kmb_lic.tgz"
@@ -160,13 +138,54 @@ if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO" AND NOT ENABLE_SYST
update_deps_cache(TBBROOT "${TBB}" "Path to TBB root folder")
if(EXISTS "${TBBROOT}/lib/cmake/TBB/TBBConfig.cmake")
# oneTBB case
update_deps_cache(TBB_DIR "${TBB}/lib/cmake/TBB" "Path to TBB cmake folder")
update_deps_cache(TBB_DIR "${TBBROOT}/lib/cmake/TBB" "Path to TBB cmake folder")
elseif(EXISTS "${TBBROOT}/lib64/cmake/TBB/TBBConfig.cmake")
# 64-bits oneTBB case
update_deps_cache(TBB_DIR "${TBBROOT}/lib64/cmake/TBB" "Path to TBB cmake folder")
elseif(EXISTS "${TBBROOT}/cmake/TBBConfig.cmake")
# custom downloaded or user provided TBB
update_deps_cache(TBB_DIR "${TBBROOT}/cmake" "Path to TBB cmake folder")
else()
update_deps_cache(TBB_DIR "${TBB}/cmake" "Path to TBB cmake folder")
message(FATAL_ERROR "Failed to find TBBConfig.cmake in ${TBBROOT} tree")
endif()
update_deps_cache(TBBBIND_2_5_DIR "${TBBBIND_2_5}/cmake" "Path to TBBBIND_2_5 cmake folder")
debug_message(STATUS "tbb=" ${TBB})
debug_message(STATUS "tbb_dir=" ${TBB_DIR})
debug_message(STATUS "tbbroot=" ${TBBROOT})
if(DEFINED IE_PATH_TO_DEPS)
unset(IE_PATH_TO_DEPS)
endif()
endif()
## TBBBind_2_5 package
if(ENABLE_TBBBIND_2_5)
if(DEFINED ENV{THIRDPARTY_SERVER_PATH})
set(IE_PATH_TO_DEPS "$ENV{THIRDPARTY_SERVER_PATH}")
elseif(DEFINED THIRDPARTY_SERVER_PATH)
set(IE_PATH_TO_DEPS "${THIRDPARTY_SERVER_PATH}")
endif()
if(WIN32 AND X86_64)
RESOLVE_DEPENDENCY(TBBBIND_2_5
ARCHIVE_WIN "tbbbind_2_5_static_win_v1.zip"
TARGET_PATH "${TEMP}/tbbbind_2_5"
ENVIRONMENT "TBBBIND_2_5_ROOT"
SHA256 "a67afeea8cf194f97968c800dab5b5459972908295242e282045d6b8953573c1")
elseif(LINUX AND X86_64)
RESOLVE_DEPENDENCY(TBBBIND_2_5
ARCHIVE_LIN "tbbbind_2_5_static_lin_v2.tgz"
TARGET_PATH "${TEMP}/tbbbind_2_5"
ENVIRONMENT "TBBBIND_2_5_ROOT"
SHA256 "865e7894c58402233caf0d1b288056e0e6ab2bf7c9d00c9dc60561c484bc90f4")
else()
message(WARNING "prebuilt TBBBIND_2_5 is not available.
Build oneTBB from sources and set TBBROOT environment var before OpenVINO cmake configure")
endif()
update_deps_cache(TBBBIND_2_5_DIR "${TBBBIND_2_5}/cmake" "Path to TBBBIND_2_5 cmake folder")
if(DEFINED IE_PATH_TO_DEPS)
unset(IE_PATH_TO_DEPS)
@@ -265,8 +284,6 @@ else()
reset_deps_cache(OpenCV_DIR)
endif()
include(${OpenVINO_SOURCE_DIR}/src/cmake/ie_parallel.cmake)
if(ENABLE_INTEL_GNA)
reset_deps_cache(
GNA_EXT_DIR
+1 -4
View File
@@ -26,10 +26,7 @@ endif()
find_package(TBB
CONFIG
PATHS ${TBBROOT}/cmake
${TBBROOT}/lib/cmake/TBB # oneTBB case
${IEDevScripts_DIR}/${IE_OWN_TBB_CONFIG}
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH
)
NO_DEFAULT_PATH)
find_package_handle_standard_args(TBB CONFIG_MODE)
+2 -4
View File
@@ -7,7 +7,7 @@ include(target_flags)
# FIXME: there are compiler failures with LTO and Cross-Compile toolchains. Disabling for now, but
# this must be addressed in a proper way
ie_dependent_option (ENABLE_LTO "Enable Link Time Optimization" OFF "LINUX;NOT CMAKE_CROSSCOMPILING; CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9" OFF)
ie_dependent_option (ENABLE_LTO "Enable Link Time Optimization" OFF "LINUX;NOT CMAKE_CROSSCOMPILING;CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9" OFF)
ie_option (OS_FOLDER "create OS dedicated folder in output" OFF)
@@ -79,6 +79,4 @@ if(ENABLE_AVX512F)
endif()
endif()
if (VERBOSE_BUILD)
set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "" FORCE)
endif()
set(CMAKE_VERBOSE_MAKEFILE ${VERBOSE_BUILD} CACHE BOOL "" FORCE)
+4
View File
@@ -31,4 +31,8 @@ if (LINUX)
set(${res_var} NOTFOUND PARENT_SCOPE)
endif ()
endfunction()
else()
function(get_linux_name res_var)
set(${res_var} NOTFOUND PARENT_SCOPE)
endfunction()
endif ()
+26 -3
View File
@@ -82,7 +82,7 @@ else()
set(ENABLE_TBBBIND_2_5_DEFAULT OFF)
endif()
ie_dependent_option (ENABLE_TBBBIND_2_5 "Enable TBBBind_2_5 static usage in OpenVINO runtime" ON "ENABLE_TBBBIND_2_5_DEFAULT" OFF)
ie_dependent_option (ENABLE_TBBBIND_2_5 "Enable TBBBind_2_5 static usage in OpenVINO runtime" ${ENABLE_TBBBIND_2_5_DEFAULT} "THREADING MATCHES TBB" OFF)
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)
@@ -134,9 +134,32 @@ set(IE_EXTRA_MODULES "" CACHE STRING "Extra paths for extra modules to include i
ie_dependent_option(ENABLE_TBB_RELEASE_ONLY "Only Release TBB libraries are linked to the Inference Engine binaries" ON "THREADING MATCHES TBB;LINUX" OFF)
ie_dependent_option (ENABLE_SYSTEM_PUGIXML "use the system version of pugixml" OFF "BUILD_SHARED_LIBS" OFF)
ie_dependent_option (ENABLE_SYSTEM_PUGIXML "use the system copy of pugixml" OFF "BUILD_SHARED_LIBS" OFF)
ie_option (ENABLE_SYSTEM_TBB "use the system version of TBB" OFF)
get_linux_name(LINUX_OS_NAME)
if(LINUX_OS_NAME MATCHES "^Ubuntu [0-9]+\.[0-9]+$" AND NOT DEFINED ENV{TBBROOT})
# Debian packages are enabled on Ubuntu systems
set(ENABLE_SYSTEM_TBB_DEFAULT ON)
# check whether "default" (customly provided or system one) is available
find_package(TBB QUIET)
if(NOT TBB_FOUND)
message(WARNING "System TBB is not found, custom TBB version will be downloaded from shared drive")
# we still need to download prebuilt version of TBB
set(ENABLE_SYSTEM_TBB_DEFAULT OFF)
endif()
# remove found TBB (or invalid TBB_DIR-NOTFOUND) from cache
unset(TBB_DIR CACHE)
unset(TBB_DIR)
unset(TBB_FOUND)
unset(TBB_IMPORTED_TARGETS)
unset(TBB_VERSION)
else()
set(ENABLE_SYSTEM_TBB_DEFAULT OFF)
endif()
ie_dependent_option (ENABLE_SYSTEM_TBB "use the system version of TBB" ${ENABLE_SYSTEM_TBB_DEFAULT} "THREADING MATCHES TBB;LINUX" OFF)
ie_option (ENABLE_DEBUG_CAPS "enable OpenVINO debug capabilities at runtime" OFF)
+24 -19
View File
@@ -12,7 +12,7 @@
# * `Runtime`: OpenVINO C++ and C Core & Inference Runtime, frontend common
# * `ONNX`: OpenVINO ONNX frontend
# * `Paddle`: OpenVINO Paddle frontend
# * `TF`: OpenVINO TensorFlow frontend
# * `TensorFlow`: OpenVINO TensorFlow frontend
#
# If no components are specified, `Runtime` component is provided:
#
@@ -147,25 +147,29 @@ set(_ov_package_prefix_dir "${PACKAGE_PREFIX_DIR}")
set(THREADING "@THREADING@")
if((THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") AND NOT TBB_FOUND)
set(ov_system_tbb "@ENABLE_SYSTEM_TBB@")
if(ov_system_tbb)
# OpenVINO is built against system TBB
_ov_find_dependency(TBB
COMPONENTS tbb tbbmalloc)
else()
set(enable_system_tbb "@ENABLE_SYSTEM_TBB@")
if(NOT enable_system_tbb)
set_and_check(_tbb_dir "@PACKAGE_IE_TBB_DIR@")
# TBB is located in OpenVINO package
_ov_find_dependency(TBB
COMPONENTS tbb tbbmalloc
CONFIG
PATHS
# TBB is specified via TBBROOT CMake variable
${TBBROOT}/cmake
# TBB is searched in OV Package location
${_tbb_dir}
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH)
set(find_package_tbb_extra_args
CONFIG
PATHS
# oneTBB case exposed via export TBBROOT=<custom TBB root>
"$ENV{TBBROOT}/lib64/cmake/TBB"
"$ENV{TBBROOT}/lib/cmake/TBB"
# "$ENV{TBB_DIR}"
# for custom TBB exposed via cmake -DTBBROOT=<custom TBB root>
"${TBBROOT}/cmake"
# _tbb_dir points to TBB_DIR (custom | temp | system) used to build OpenVINO
${_tbb_dir}
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH)
unset(_tbb_dir)
endif()
unset(enable_system_tbb)
_ov_find_dependency(TBB
COMPONENTS tbb tbbmalloc
${find_package_tbb_extra_args})
set(install_tbbbind "@install_tbbbind@")
if(install_tbbbind)
@@ -176,6 +180,7 @@ if((THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO") AND NOT TBB_FOUND
NO_DEFAULT_PATH)
set_target_properties(${TBBBIND_2_5_IMPORTED_TARGETS} PROPERTIES IMPORTED_GLOBAL ON)
endif()
unset(install_tbbbind)
endif()
_ov_find_dependency(Threads)
@@ -187,7 +192,7 @@ if(ENABLE_INTEL_GNA AND NOT ENABLE_INTEL_GNA_SHARED AND NOT libGNA_FOUND)
_ov_find_dependency(libGNA
COMPONENTS KERNEL
CONFIG
PATHS ${CMAKE_CURRENT_LIST_DIR}
PATHS "${CMAKE_CURRENT_LIST_DIR}"
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH)
endif()
+1 -1
View File
@@ -9,7 +9,7 @@ For more details about low-precision model representation please refer to this [
During the model load each plugin can interpret quantization rules expressed in *FakeQuantize* operations:
- Independently based on the definition of *FakeQuantize* operation.
- Using a special library of low-precision transformations (LPT) which applies common rules for generic operations,
such as Convolution, Fully-Connected, Eltwise, etc., and translates "fake-quantized" models into the models with low-precision operations. For more information about low-precision flow please refer to the following [document](../OV_Runtime_UG/Int8Inference.md).
such as Convolution, Fully-Connected, Eltwise, etc., and translates "fake-quantized" models into models with low-precision operations.
Here we provide only a high-level overview of the interpretation rules of FakeQuantize.
At runtime each FakeQuantize can be split into two independent operations: **Quantize** and **Dequantize**.
@@ -72,11 +72,7 @@ For example, if you would like to infer a model with `Convolution` operation in
> There are several supported quantization approaches on activations and on weights. All supported approaches are described in [Quantization approaches](#quantization-approaches) section below. In demonstrated model [FakeQuantize operation quantization](#fakequantize-operation) approach is used.
### Low precision tools
There are two tools to quantize a model:
1. [Post-Training Optimization Toolkit](@ref pot_docs_LowPrecisionOptimizationGuide) (POT)
2. [Neural Network Compression Framework](https://github.com/openvinotoolkit/nncf) (NNCF)
Additionally, low precision transformations can handle ONNX quantized models.
For more details on how to get a quantized model, refer to [Model Optimization](@ref openvino_docs_model_optimization_guide) document.
## Quantization approaches
LPT transformations support two quantization approaches:
@@ -42,7 +42,7 @@ The IR is a pair of files describing the model:
* <code>.bin</code> - Contains the weights and biases binary data.
> **NOTE**: The generated IR can be additionally optimized for inference by [Post-training Optimization tool](../../tools/pot/README.md)
> **NOTE**: The generated IR can be additionally optimized for inference by [Post-training optimization](../../tools/pot/docs/Introduction.md)
> that applies post-training quantization methods.
> **TIP**: You also can work with the Model Optimizer inside the OpenVINO™ [Deep Learning Workbench](https://docs.openvino.ai/latest/workbench_docs_Workbench_DG_Introduction.html) (DL Workbench).
+1 -1
View File
@@ -17,4 +17,4 @@ although for the majority of models accuracy degradation is negligible. For deta
compressed `FP16` models refer to [Working with devices](../../OV_Runtime_UG/supported_plugins/Device_Plugins.md) page.
> **NOTE**: `FP16` compression is sometimes used as initial step for `INT8` quantization, please refer to
> [Post-Training Optimization tool](../../../tools/pot/README.md) for more information about that.
> [Post-training optimization](../../../tools/pot/docs/Introduction.md) for more information about that.
@@ -3,11 +3,11 @@
## Introduction
OpenVINO Runtime CPU and GPU devices can infer models in the low precision.
For details, refer to [Low Precision Inference on the CPU](../../../OV_Runtime_UG/Int8Inference.md).
For details, refer to [Model Optimization Guide](@ref openvino_docs_model_optimization_guide).
Intermediate Representation (IR) should be specifically formed to be suitable for low precision inference.
Such an IR is called a Low Precision IR and you can generate it in two ways:
- [Quantize regular IR with the Post-Training Optimization tool](@ref pot_README)
- [Quantize regular IR with the Post-Training Optimization tool](@ref pot_introduction)
- Use the Model Optimizer for a model pretrained for Low Precision inference: TensorFlow\* pre-TFLite models (`.pb` model file with `FakeQuantize*` operations) and ONNX\* quantized models.
Both TensorFlow and ONNX quantized models could be prepared by [Neural Network Compression Framework](https://github.com/openvinotoolkit/nncf/blob/develop/README.md).
+4 -6
View File
@@ -1,4 +1,4 @@
# Low-Precision 8-bit Integer Inference {#openvino_docs_IE_DG_Int8Inference}
# Low-Precision 8-bit Integer Inference
## Disclaimer
@@ -14,9 +14,7 @@ Low-precision 8-bit inference is optimized for:
## Introduction
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 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 more details on how to get quantized model please refer to [Model Optimization](@ref openvino_docs_model_optimization_guide) document.
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).
@@ -46,10 +44,10 @@ If you infer the model with the OpenVINO™ CPU plugin and collect performance c
## 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).
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_introduction) 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.
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 the 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_introduction) 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.
@@ -60,6 +60,7 @@
openvino_docs_ops_detection_ExperimentalDetectronROIFeatureExtractor_6
openvino_docs_ops_sort_ExperimentalDetectronTopKROIs_6
openvino_docs_ops_movement_ExtractImagePatches_3
openvino_docs_ops_generation_Eye_9
openvino_docs_ops_quantization_FakeQuantize_1
openvino_docs_ops_arithmetic_FloorMod_1
openvino_docs_ops_arithmetic_Floor_1
@@ -75,3 +75,36 @@ Another feature of `AsyncInferQueue` is ability of setting callbacks. When callb
The callback of `AsyncInferQueue` is uniform for every job. When executed, GIL is acquired to ensure safety of data manipulation inside the function.
@snippet docs/snippets/ov_python_exclusives.py asyncinferqueue_set_callback
### Releasing the GIL
Some functions in Python API release the Global Lock Interpreter (GIL) while running work-intensive code. It can help you to achieve more parallelism in your application using Python threads. For more information about GIL please refer to the Python documentation.
@snippet docs/snippets/ov_python_exclusives.py releasing_gil
> **NOTE**: While GIL is released functions can still modify and/or operate on Python objects in C++, thus there is no reference counting. User is responsible for thread safety if sharing of these objects with other thread occurs. It can affects your code only if multiple threads are spawned in Python.:
#### List of functions that release the GIL
- openvino.runtime.AsyncInferQueue.start_async
- openvino.runtime.AsyncInferQueue.is_ready
- openvino.runtime.AsyncInferQueue.wait_all
- openvino.runtime.AsyncInferQueue.get_idle_request_id
- openvino.runtime.CompiledModel.create_infer_request
- openvino.runtime.CompiledModel.infer_new_request
- openvino.runtime.CompiledModel.__call__
- openvino.runtime.CompiledModel.export
- openvino.runtime.CompiledModel.get_runtime_model
- openvino.runtime.Core.compile_model
- openvino.runtime.Core.read_model
- openvino.runtime.Core.import_model
- openvino.runtime.Core.query_model
- openvino.runtime.Core.get_available_devices
- openvino.runtime.InferRequest.infer
- openvino.runtime.InferRequest.start_async
- openvino.runtime.InferRequest.wait
- openvino.runtime.InferRequest.wait_for
- openvino.runtime.InferRequest.get_profiling_info
- openvino.runtime.InferRequest.query_state
- openvino.runtime.Model.reshape
- openvino.preprocess.PrePostProcessor.build
@@ -17,11 +17,31 @@ The following code shows how to change the application code in each step to migr
Inference Engine API:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:create_core
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:create_core
@endsphinxtab
@endsphinxtabset
OpenVINO™ Runtime API 2.0:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:create_core
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:create_core
@endsphinxtab
@endsphinxtabset
### 1.1 (Optional) Load extensions
@@ -29,21 +49,61 @@ To load model with custom operation, you need to add extensions for these operat
Inference Engine API:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:load_old_extension
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:load_old_extension
@endsphinxtab
@endsphinxtabset
OpenVINO™ Runtime API 2.0:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:load_old_extension
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:load_old_extension
@endsphinxtab
@endsphinxtabset
## 2. Read model from the disk
Inference Engine API:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:read_model
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:read_model
@endsphinxtab
@endsphinxtabset
OpenVINO™ Runtime API 2.0:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:read_model
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:read_model
@endsphinxtab
@endsphinxtabset
Read model has the same structure as in the example from [Model Creation](./graph_construction.md) migration guide.
@@ -58,11 +118,31 @@ See detailed guide [how to migrate preprocessing in OpenVINO Runtime API 2.0](./
Inference Engine API:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:compile_model
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:compile_model
@endsphinxtab
@endsphinxtabset
OpenVINO™ Runtime API 2.0:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:compile_model
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:compile_model
@endsphinxtab
@endsphinxtabset
If you need to configure OpenVINO Runtime devices with additional configuration parameters, please, refer to the migration [Configure devices](./configure_devices.md) guide.
@@ -70,11 +150,31 @@ If you need to configure OpenVINO Runtime devices with additional configuration
Inference Engine API:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:create_infer_request
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:create_infer_request
@endsphinxtab
@endsphinxtabset
OpenVINO™ Runtime API 2.0:
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:create_infer_request
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:create_infer_request
@endsphinxtab
@endsphinxtabset
## 5. Fill input tensors
@@ -84,25 +184,65 @@ Inference Engine API fills inputs as `I32` precision (**not** aligned with the o
@sphinxtab{IR v10}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_input_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_input_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{IR v11}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_input_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_input_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{ONNX}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_input_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_input_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{Model created in code}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_input_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_input_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@@ -114,25 +254,65 @@ OpenVINO™ Runtime API 2.0 fills inputs as `I64` precision (aligned with the or
@sphinxtab{IR v10}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_input_tensor_v10
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_input_tensor_v10
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{IR v11}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_input_tensor_aligned
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_input_tensor_aligned
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{ONNX}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_input_tensor_aligned
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_input_tensor_aligned
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{Model created in code}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_input_tensor_aligned
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_input_tensor_aligned
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@@ -146,13 +326,33 @@ Inference Engine API:
@sphinxtab{Sync}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:inference
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:inference
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{Async}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:start_async_and_wait
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:start_async_and_wait
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@@ -164,13 +364,33 @@ OpenVINO™ Runtime API 2.0:
@sphinxtab{Sync}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:inference
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:inference
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{Async}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:start_async_and_wait
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:start_async_and_wait
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@@ -184,25 +404,65 @@ Inference Engine API processes outputs as `I32` precision (**not** aligned with
@sphinxtab{IR v10}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:inference
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_output_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_output_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{IR v11}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_output_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_output_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{ONNX}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_output_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_output_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{Model created in code}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ie_common.cpp ie:get_output_tensor
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ie_common.py ie:get_output_tensor
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@@ -216,25 +476,65 @@ OpenVINO™ Runtime API 2.0 processes outputs:
@sphinxtab{IR v10}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_output_tensor_v10
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_output_tensor_v10
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{IR v11}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_output_tensor_aligned
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_output_tensor_aligned
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{ONNX}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_output_tensor_aligned
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_output_tensor_aligned
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@sphinxtab{Model created in code}
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_common.cpp ov_api_2_0:get_output_tensor_aligned
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_common.py ov_api_2_0:get_output_tensor_aligned
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@@ -22,6 +22,10 @@ Inference Engine API:
@sphinxtabset
@sphinxtab{C++}
@sphinxtabset
@sphinxtab{Devices}
@snippet docs/snippets/ov_properties_migration.cpp core_set_config
@@ -42,6 +46,36 @@ Inference Engine API:
@endsphinxtabset
@endsphinxtab
@sphinxtab{Python}
@sphinxtabset
@sphinxtab{Devices}
@snippet docs/snippets/ov_properties_migration.py core_set_config
@endsphinxtab
@sphinxtab{Model Loading}
@snippet docs/snippets/ov_properties_migration.py core_load_network
@endsphinxtab
@sphinxtab{Execution}
@snippet docs/snippets/ov_properties_migration.py executable_network_set_config
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@endsphinxtabset
OpenVINO Runtime API 2.0:
@sphinxtabset
@@ -106,6 +140,10 @@ Inference Engine API:
@sphinxtabset
@sphinxtab{C++}
@sphinxtabset
@sphinxtab{Device Configuration}
@snippet docs/snippets/ov_properties_migration.cpp core_get_config
@@ -132,6 +170,42 @@ Inference Engine API:
@endsphinxtabset
@endsphinxtab
@sphinxtab{Python}
@sphinxtabset
@sphinxtab{Device Configuration}
@snippet docs/snippets/ov_properties_migration.py core_get_config
@endsphinxtab
@sphinxtab{Device metrics}
@snippet docs/snippets/ov_properties_migration.py core_get_metric
@endsphinxtab
@sphinxtab{Execution config}
@snippet docs/snippets/ov_properties_migration.py executable_network_get_config
@endsphinxtab
@sphinxtab{Execution metrics}
@snippet docs/snippets/ov_properties_migration.py executable_network_get_metric
@endsphinxtab
@endsphinxtabset
@endsphinxtab
@endsphinxtabset
OpenVINO Runtime API 2.0:
@sphinxtabset
@@ -5,11 +5,31 @@ Code snippets below show how application code should be changed for migration to
### nGraph API
@snippet snippets/ngraph.cpp ngraph:graph
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ngraph.cpp ngraph:graph
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ngraph.py ngraph:graph
@endsphinxtab
@endsphinxtabset
### OpenVINO™ Runtime API 2.0:
@snippet snippets/ov_graph.cpp ov:graph
@sphinxtabset
@sphinxtab{C++}
@snippet docs/snippets/ov_graph.cpp ov:graph
@endsphinxtab
@sphinxtab{Python}
@snippet docs/snippets/ov_graph.py ov:graph
@endsphinxtab
@endsphinxtabset
**See also:**
- [Hello Model Creation C++ Sample](../../../samples/cpp/model_creation_sample/README.md)
+1 -1
View File
@@ -47,7 +47,7 @@ CPU plugin supports the following data types as inference precision of internal
Selected precision of each primitive depends on the operation precision in IR, quantization primitives, and available hardware capabilities.
u1/u8/i8 data types are used for quantized operations only, i.e. those are not selected automatically for non-quantized operations.
See [low-precision optimization guide](@ref pot_docs_LowPrecisionOptimizationGuide) for more details on how to get quantized model.
See [low-precision optimization guide](@ref openvino_docs_model_optimization_guide) for more details on how to get a quantized model.
> **NOTE**: Platforms that do not support Intel® AVX512-VNNI have a known "saturation issue" which in some cases leads to reduced computational accuracy for u8/i8 precision calculations.
> See [saturation (overflow) issue section](@ref pot_saturation_issue) to get more information on how to detect such issues and possible workarounds.
+2 -2
View File
@@ -90,7 +90,7 @@ can cause the user's request to be executed on CPU, thereby unnecessarily increa
Intel® GNA essentially operates in the low-precision mode which represents a mix of 8-bit (`i8`), 16-bit (`i16`), and 32-bit (`i32`) integer computations.
GNA plugin users are encouraged to use the [Post-Training Optimization Tool](@ref pot_README) to get a model with quantization hints based on statistics for the provided dataset.
GNA plugin users are encouraged to use the [Post-Training Optimization Tool](@ref pot_introduction) to get a model with quantization hints based on statistics for the provided dataset.
Unlike other plugins supporting low-precision execution, the GNA plugin can calculate quantization factors at the model loading time, so you can run a model without calibration. However, this mode may not provide satisfactory accuracy because the internal quantization algorithm is based on heuristics which may or may not be efficient, depending on the model and dynamic range of input data and this mode is going to be deprecated soon.
@@ -101,7 +101,7 @@ GNA plugin supports the following data types as inference precision of internal
[Hello Query Device C++ Sample](@ref openvino_inference_engine_samples_hello_query_device_README) can be used to print out supported data types for all detected devices.
[POT API Usage sample for GNA](@ref pot_sample_speech_README) demonstrates how a model can be quantized for GNA using POT API in 2 modes:
[POT API Usage sample for GNA](@ref pot_example_speech_README) demonstrates how a model can be quantized for GNA using POT API in 2 modes:
* Accuracy (i16 weights)
* Performance (i8 weights)
+2 -2
View File
@@ -109,7 +109,7 @@ GPU plugin supports the following data types as inference precision of internal
Selected precision of each primitive depends on the operation precision in IR, quantization primitives, and available hardware capabilities.
u1/u8/i8 data types are used for quantized operations only, i.e. those are not selected automatically for non-quantized operations.
See [low-precision optimization guide](@ref pot_docs_LowPrecisionOptimizationGuide) for more details on how to get quantized model.
For more details on how to get a quantized model, refer to [Model Optimization](@ref openvino_docs_model_optimization_guide) document.
Floating-point precision of a GPU primitive is selected based on operation precision in IR except [compressed f16 IR form](../../MO_DG/prepare_model/FP16_Compression.md) which is executed in f16 precision.
@@ -298,7 +298,7 @@ The behavior depends on specific parameters of the operations and hardware confi
## GPU Performance Checklist: Summary <a name="gpu-checklist"></a>
Since the OpenVINO relies on the OpenCL&trade; kernels for the GPU implementation. Thus, many general OpenCL tips apply:
- Prefer `FP16` inference precision over `FP32`, as the Model Optimizer can generate both variants and the `FP32` is default. Also, consider [int8 inference](../Int8Inference.md)
- Prefer `FP16` inference precision over `FP32`, as the Model Optimizer can generate both variants and the `FP32` is default. Also, consider [int8 inference](@ref openvino_docs_model_optimization_guide).
- Try to group individual infer jobs by using [automatic batching](../automatic_batching.md)
- Consider [caching](../Model_caching_overview.md) to minimize model load time
- If your application is simultaneously using the inference on the CPU or otherwise loads the host heavily, make sure that the OpenCL driver threads do not starve. You can use [CPU configuration options](./CPU.md) to limit number of inference threads for the CPU plugin.
+1 -1
View File
@@ -96,7 +96,7 @@ With the [Model Downloader](@ref omz_tools_downloader) and [Model Optimizer](MO_
The [OpenVINO™ Runtime User Guide](./OV_Runtime_UG/openvino_intro.md) explains the process of creating your own application that runs inference with the OpenVINO™ toolkit. The [API Reference](./api_references.html) defines the OpenVINO Runtime API for Python, C++, and C. The OpenVINO Runtime API is what you'll use to create an OpenVINO™ inference application, use enhanced operations sets and other features. After writing your application, you can use the [Deployment with OpenVINO](./OV_Runtime_UG/deployment/deployment_intro.md) for deploying to target devices.
## Tuning for Performance
The toolkit provides a [Performance Optimization Guide](optimization_guide/dldt_optimization_guide.md) and utilities for squeezing the best performance out of your application, including [Accuracy Checker](@ref omz_tools_accuracy_checker), [Post-Training Optimization Tool](@ref pot_README), and other tools for measuring accuracy, benchmarking performance, and tuning your application.
The toolkit provides a [Performance Optimization Guide](optimization_guide/dldt_optimization_guide.md) and utilities for squeezing the best performance out of your application, including [Accuracy Checker](@ref omz_tools_accuracy_checker), [Post-Training Optimization Tool](@ref pot_introduction), and other tools for measuring accuracy, benchmarking performance, and tuning your application.
## Graphical Web Interface for OpenVINO™ Toolkit
You can choose to use the [OpenVINO™ Deep Learning Workbench](@ref workbench_docs_Workbench_DG_Introduction), a web-based tool that guides you through the process of converting, measuring, optimizing, and deploying models. This tool also serves as a low-effort introduction to the toolkit and provides a variety of useful interactive charts for understanding performance.
+1 -1
View File
@@ -11,7 +11,7 @@ OpenVINO™ toolkit is a comprehensive toolkit for quickly developing applicatio
| [Model Optimizer](../MO_DG/Deep_Learning_Model_Optimizer_DevGuide.md) | `mo` |**Model Optimizer** imports, converts, and optimizes models that were trained in popular frameworks to a format usable by OpenVINO components. <br>Supported frameworks include Caffe\*, TensorFlow\*, MXNet\*, PaddlePaddle\*, and ONNX\*. |
| [Benchmark Tool](../../tools/benchmark_tool/README.md)| `benchmark_app` | **Benchmark Application** allows you to estimate deep learning inference performance on supported devices for synchronous and asynchronous modes. |
| [Accuracy Checker](@ref omz_tools_accuracy_checker) and <br> [Annotation Converter](@ref omz_tools_accuracy_checker_annotation_converters) | `accuracy_check` <br> `convert_annotation` |**Accuracy Checker** is a deep learning accuracy validation tool that allows you to collect accuracy metrics against popular datasets. The main advantages of the tool are the flexibility of configuration and a set of supported datasets, preprocessing, postprocessing, and metrics. <br> **Annotation Converter** is a utility that prepares datasets for evaluation with Accuracy Checker. |
| [Post-Training Optimization Tool](../../tools/pot/README.md)| `pot` |**Post-Training Optimization Tool** allows you to optimize trained models with advanced capabilities, such as quantization and low-precision optimizations, without the need to retrain or fine-tune models. Optimizations are also available through the [API](../../tools/pot/openvino/tools/pot/api/README.md). |
| [Post-Training Optimization Tool](../../tools/pot/docs/pot_introduction.md)| `pot` |**Post-Training Optimization Tool** allows you to optimize trained models with advanced capabilities, such as quantization and low-precision optimizations, without the need to retrain or fine-tune models. |
| [Model Downloader and other Open Model Zoo tools](@ref omz_tools_downloader)| `omz_downloader` <br> `omz_converter` <br> `omz_quantizer` <br> `omz_info_dumper`| **Model Downloader** is a tool for getting access to the collection of high-quality and extremely fast pre-trained deep learning [public](@ref omz_models_group_public) and [Intel](@ref omz_models_group_intel)-trained models. These free pre-trained models can be used to speed up the development and production deployment process without training your own models. The tool downloads model files from online sources and, if necessary, patches them to make them more usable with Model Optimizer. A number of additional tools are also provided to automate the process of working with downloaded models:<br> **Model Converter** is a tool for converting Open Model Zoo models that are stored in an original deep learning framework format into the OpenVINO Intermediate Representation (IR) using Model Optimizer. <br> **Model Quantizer** is a tool for automatic quantization of full-precision models in the IR format into low-precision versions using the Post-Training Optimization Tool. <br> **Model Information Dumper** is a helper utility for dumping information about the models to a stable, machine-readable format.
The developer package also installs the OpenVINO™ Runtime package as a dependency.
+170
View File
@@ -0,0 +1,170 @@
## Eye <a name="Eye"></a> {#openvino_docs_ops_generation_Eye_9}
**Versioned name**: *Eye-9*
**Category**: *Generation*
**Short description**: *Eye* operation generates shift matrix or a batch of matrices.
**Detailed description**:
*Eye* operation generates an identity matrix or a batch matrices with ones on the diagonal and zeros everywhere else. The index of the diagonal to be populated with ones is given by `diagonal_index`: `output[..., i, i + diagonal_index] = 1`.
Example 1. *Eye* output with `output_type` = `f32`:
```
num_rows = 3
output = [[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
```
Example 2. *Eye* output with `output_type` = `i32`:
```
num_rows = 3
num_columns = 4
diagonal_index = 2
output = [[0 0 1 0]
[0 0 0 1]
[0 0 0 0]]
```
Example 3. *Eye* output with `output_type` = `i32`:
```
num_rows = 3
num_columns = 4
diagonal_index = -1
output = [[0 0 0 0]
[1 0 0 0]
[0 1 0 0]]
```
Example 4. *Eye* output with `output_type` = `f16`:
```
num_rows = 2
diagonal_index = 5
batch_shape = [1, 2]
output = [[[[0. 0.]
[0. 0.]]
[[0. 0.]
[0. 0.]]]]
```
**Attributes**:
* *output_type*
* **Description**: the type of the output
* **Range of values**: any numeric type
* **Type**: string
* **Required**: *Yes*
**Inputs**:
* **1**: `num_rows` - scalar or 1D tensor with 1 non-negative element of type *T_NUM* describing the number of rows in matrix. **Required.**
* **2**: `num_columns` - scalar or 1D tensor with 1 non-negative element of type *T_NUM* describing the number of columns in matrix. This input is optional, and its default value equals to `num_rows`.
* **3**: `diagonal_index` - scalar or 1D tensor with element of type *T_NUM* describing the index of the diagonal to be populated. A positive value refers to an upper diagonal and a negative value refers to a lower diagonal. Value `0` populates the main diagonal. If `diagonal_index` is a positive value and is not smaller than `num_rows` or if `diagonal_index` is a negative value and is not larger than `num_columns`, the matrix will be filled with only zeros. This input is optional, and its default value equals to `0`.
* **4**: `batch_shape` - 1D tensor with non-negative values of type *T_NUM* defines leading batch dimensions of output shape. If `batch_shape` is an empty list, *Eye* operation generates a 2D tensor (matrix). This input is optional, and its default value equal to an empty tensor.
**Outputs**:
* **1**: A tensor with the type specified by the *output_type* attribute. The shape is `batch_shape + [num_rows, num_columns]`
**Types**
* *T_NUM*: `int32` or `int64`.
**Examples**
*Example 1*
```xml
<layer ... name="Eye" type="Eye">
<data output_type="i32"/>
<input>
<port id="0" precision="I32"/> <!-- num rows : 10-->
</input>
<output>
<port id="3" precision="I32" names="Eye:0">
<dim>10</dim>
<dim>10</dim>
</port>
</output>
</layer>
```
*Example 2*
```xml
<layer ... name="Eye" type="Eye">
<data output_type="i64"/>
<input>
<port id="0" precision="I32"/> <!-- num rows : 5 -->
<port id="1" precision="I32"/> <!-- num columns -->
</input>
<output>
<port id="3" precision="I64" names="Eye:0">
<dim>5</dim>
<dim>-1</dim>
</port>
</output>
</layer>
```
*Example 3*
```xml
<layer ... name="Eye" type="Eye">
<data output_type="i64"/>
<input>
<port id="0" precision="I32"/> <!-- num rows -->
<port id="2" precision="I32"/> <!-- diagonal index -->
</input>
<output>
<port id="3" precision="I64" names="Eye:0">
<dim>-1</dim>
<dim>-1</dim>
</port>
</output>
</layer>
```
*Example 4*
```xml
<layer ... name="Eye" type="Eye">
<data output_type="f32"/>
<input>
<port id="0" precision="I32"/> <!-- num rows -->
<port id="2" precision="I32"/> <!-- diagonal index -->
<port id="3" precision="I32"/> <!-- batch_shape : [2, 3] -->
</input>
<output>
<port id="3" precision="F32" names="Eye:0">
<dim>2</dim>
<dim>3</dim>
<dim>-1</dim>
<dim>-1</dim>
</port>
</output>
</layer>
```
+1
View File
@@ -60,6 +60,7 @@ declared in `namespace opset9`.
* [ExperimentalDetectronROIFeatureExtractor_6](detection/ExperimentalDetectronROIFeatureExtractor_6.md)
* [ExperimentalDetectronTopKROIs_6](sort/ExperimentalDetectronTopKROIs_6.md)
* [ExtractImagePatches](movement/ExtractImagePatches_3.md)
* [Eye](generation/Eye_9.md)
* [FakeQuantize](quantization/FakeQuantize_1.md)
* [Floor](arithmetic/Floor_1.md)
* [FloorMod](arithmetic/FloorMod_1.md)
@@ -17,7 +17,7 @@
## Deployment Optimizations Overview {#openvino_docs_deployment_optimization_guide_overview}
Runtime or deployment optimizations are focused on tuning of the inference _parameters_ (e.g. optimal number of the requests executed simultaneously) and other means of how a model is _executed_.
As referenced in the parent [performance introduction topic](./dldt_optimization_guide.md), the [dedicated document](./model_optimization_guide.md) covers the **model-level optimizations** like quantization that unlocks the [int8 inference](../OV_Runtime_UG/Int8Inference.md). Model-optimizations are most general and help any scenario and any device (that accelerated the quantized models). The relevant _runtime_ configuration is `ov::hint::inference_precision` allowing the devices to trade the accuracy for the performance (e.g. by allowing the fp16/bf16 execution for the layers that remain in fp32 after quantization of the original fp32 model).
As referenced in the parent [performance introduction topic](./dldt_optimization_guide.md), the [dedicated document](./model_optimization_guide.md) covers the **model-level optimizations** like quantization that unlocks the 8-bit inference. Model-optimizations are most general and help any scenario and any device (that e.g. accelerates the quantized models). The relevant _runtime_ configuration is `ov::hint::inference_precision` allowing the devices to trade the accuracy for the performance (e.g. by allowing the fp16/bf16 execution for the layers that remain in fp32 after quantization of the original fp32 model).
Then, possible optimization should start with defining the use-case. For example, whether the target scenario emphasizes throughput over latency like processing millions of samples by overnight jobs in the data centers.
In contrast, real-time usages would likely trade off the throughput to deliver the results at minimal latency. Often this is a combined scenario that targets highest possible throughput while maintaining a specific latency threshold.
@@ -8,7 +8,7 @@ This provides much better performance for the networks than batching especially
Compared with the batching, the parallelism is somewhat transposed (i.e. performed over inputs, with much less synchronization within CNN ops):
![](../img/cpu_streams_explained.png)
Notice that [high-level performance hints](../OV_Runtime_UG/performance_hints.md) allows the implementation to select the optimal number of the streams, _depending on the model compute demands_ and CPU capabilities (including [int8 inference](../OV_Runtime_UG/Int8Inference.md) hardware acceleration, number of cores, etc).
Note that [high-level performance hints](../OV_Runtime_UG/performance_hints.md) allows the implementation to select the optimal number of the streams, _depending on the model compute demands_ and CPU capabilities (including [int8 inference](@ref openvino_docs_model_optimization_guide) hardware acceleration, number of cores, etc).
## Automatic Batching Internals
As explained in the section on the [automatic batching](../OV_Runtime_UG/automatic_batching.md), the feature performs on-the-fly grouping of the inference requests to improve device utilization.
@@ -6,19 +6,19 @@
:maxdepth: 1
:hidden:
pot_README
pot_introduction
docs_nncf_introduction
openvino_docs_IE_DG_Int8Inference
(Experimental) Protecting Model <pot_ranger_README>
@endsphinxdirective
Model optimization assumes applying transformations to the model and relevant data flow to improve the inference performance. These transformations are basically offline and can require the availability of training and validation data. It includes such methods as quantization, pruning, preprocessing optimization, etc. OpenVINO provides several tools to optimize models at different steps of model development:
Model optimization is an optional offline step of improving final model performance by applying special optimization methods like quantization, pruning, preprocessing optimization, etc. OpenVINO provides several tools to optimize models at different steps of model development:
- **Post-training Optimization tool [(POT)](../../tools/pot/README.md)** is designed to optimize the inference of deep learning models by applying post-training methods that do not require model retraining or fine-tuning, like post-training quantization.
- **Model Optimizer** implements optimization to a model, most of them added by default, but you can configure mean/scale values, batch size, RGB vs BGR input channels, and other parameters to speed up preprocess of a model ([Embedding Preprocessing Computation](../MO_DG/prepare_model/Additional_Optimizations.md)).
- **Neural Network Compression Framework [(NNCF)](./nncf_introduction.md)** provides a suite of advanced algorithms for Neural Networks inference optimization with minimal accuracy drop, for example, quantization, pruning algorithms.
- **Post-training Optimization tool** [(POT)](../../tools/pot/docs/Introduction.md) is designed to optimize the inference of deep learning models by applying post-training methods that do not require model retraining or fine-tuning, for example, post-training 8-bit quantization.
- **Model Optimizer** implements optimization to a model, most of them added by default, but you can configure mean/scale values, batch size, RGB vs BGR input channels, and other parameters to speed-up preprocess of a model ([Embedding Preprocessing Computation](../MO_DG/prepare_model/Additional_Optimizations.md))
- **Neural Network Compression Framework** [(NNCF)](./nncf_introduction.md) provides a suite of advanced methods for training-time model optimization within the DL framework, such as PyTorch and TensorFlow. It supports methods, like Quantization-aware Training and Filter Pruning. NNCF-optimized models can be inferred with OpenVINO using all the available workflows.
## Detailed workflow:
@@ -27,9 +27,13 @@
To understand which development optimization tool you need, refer to the diagram:
POT is the easiest way to get optimized models, and usually takes several minutes depending on the model size and used HW. NNCF can be considered as an alternative or addition when the first one does not give accurate results.
Post-training methods are limited in terms of achievable accuracy and for challenging use cases accuracy might degrade. In this case, training-time optimization with NNCF is an option.
Once the model is optimized using the aforementioned tools it can be used for inference using the regular OpenVINO inference workflow. No changes to the code are required.
![](../img/WHAT_TO_USE.svg)
If you are not familiar with model optimization methods, we recommend starting from [post-training methods](@ref pot_introduction).
## See also
- [Deployment optimization](./dldt_deployment_optimization_guide.md)
+4 -5
View File
@@ -1,8 +1,8 @@
# Neural Network Compression Framework {#docs_nncf_introduction}
This document describes the Neural Network Compression Framework (NNCF) which is being developed as a separate project outside of OpenVINO&trade; but it is highly aligned with OpenVINO&trade; in terms of the supported optimization features and models. It is open-sourced and available on [GitHub](https://github.com/openvinotoolkit/nncf).
This document describes the Neural Network Compression Framework (NNCF) which is distributed as a separate tool but is highly aligned with OpenVINO&trade; in terms of the supported optimization features and models. It is open-sourced and available on [GitHub](https://github.com/openvinotoolkit/nncf).
## Introduction
Neural Network Compression Framework (NNCF) is aimed at optimizing Deep Neural Network (DNN) by applying optimization methods, such as quantization, pruning, etc., to the original framework model. It mostly provides in-training optimization capabilities which means that optimization methods require model fine-tuning during and after optimization. The diagram below shows the model optimization workflow using NNCF.
Neural Network Compression Framework (NNCF) is aimed at optimizing Deep Neural Network (DNN) by applying optimization methods, such as quantization, pruning, etc., to the original framework model. It provides in-training optimization capabilities which means that optimization methods require model fine-tuning or even re-training. The diagram below shows the model optimization workflow using NNCF.
![](../img/nncf_workflow.png)
### Features
@@ -42,7 +42,6 @@ NNCF provides various examples and tutorials that demonstrate usage of optimizat
### Tutorials
- [Quantization-aware training of PyTorch model](https://github.com/openvinotoolkit/openvino_notebooks/tree/main/notebooks/302-pytorch-quantization-aware-training)
- [Quantization-aware training of TensorFlow model](https://github.com/openvinotoolkit/openvino_notebooks/tree/main/notebooks/305-tensorflow-quantization-aware-training)
- (Experimental) [Post-training quantization of PyTorch model](https://github.com/openvinotoolkit/openvino_notebooks/tree/main/notebooks/112-pytorch-post-training-quantization-nncf)
### Samples
- PyTorch:
@@ -58,6 +57,6 @@ NNCF provides various examples and tutorials that demonstrate usage of optimizat
## See also
- [Compressed Model Zoo](https://github.com/openvinotoolkit/nncf#nncf-compressed-model-zoo)
- [NNCF in HuggingFace Optimum](https://github.com/dkurt/optimum-openvino)
- [OpenVINO&trade; Post-training Optimization tool](../../tools/pot/README.md)
- [NNCF in HuggingFace Optimum](https://github.com/openvinotoolkit/openvino_contrib/tree/master/modules/optimum)
- [Post-training optimization](../../tools/pot/docs/Introduction.md)
+90
View File
@@ -0,0 +1,90 @@
# Copyright (C) 2022 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
#! [ie:create_core]
import numpy as np
import openvino.inference_engine as ie
core = ie.IECore()
#! [ie:create_core]
#! [ie:read_model]
network = core.read_network("model.xml")
#! [ie:read_model]
#! [ie:compile_model]
# Load network to the device and create infer requests
exec_network = core.load_network(network, "CPU", num_requests=4)
#! [ie:compile_model]
#! [ie:create_infer_request]
# Done in the previous step
#! [ie:create_infer_request]
#! [ie:get_input_tensor]
infer_request = exec_network.requests[0]
# Get input blobs mapped to input layers names
input_blobs = infer_request.input_blobs
data = input_blobs["data1"].buffer
# Original I64 precision was converted to I32
assert data.dtype == np.int32
# Fill the first blob ...
#! [ie:get_input_tensor]
#! [ie:inference]
results = infer_request.infer()
#! [ie:inference]
input_data = iter(list())
def process_results(results, frame_id):
pass
#! [ie:start_async_and_wait]
# Start async inference on a single infer request
infer_request.async_infer()
# Wait for 1 milisecond
infer_request.wait(1)
# Wait for inference completion
infer_request.wait()
# Demonstrates async pipeline using ExecutableNetwork
results = []
# Callback to process inference results
def callback(output_blobs, _):
# Copy the data from output blobs to numpy array
results_copy = {out_name: out_blob.buffer[:] for out_name, out_blob in output_blobs.items()}
results.append(process_results(results_copy))
# Setting callback for each infer requests
for infer_request in exec_network.requests:
infer_request.set_completion_callback(callback, py_data=infer_request.output_blobs)
# Async pipline is managed by ExecutableNetwork
total_frames = 100
for _ in range(total_frames):
# Wait for at least one free request
exec_network.wait(num_request=1)
# Get idle id
idle_id = exec_network.get_idle_request_id()
# Start asynchronous inference on idle request
exec_network.start_async(request_id=idle_id, inputs=next(input_data))
# Wait for all requests to complete
exec_network.wait()
#! [ie:start_async_and_wait]
#! [ie:get_output_tensor]
# Get output blobs mapped to output layers names
output_blobs = infer_request.output_blobs
data = output_blobs["out1"].buffer
# Original I64 precision was converted to I32
assert data.dtype == np.int32
# Process output data
#! [ie:get_output_tensor]
#! [ie:load_old_extension]
core.add_extension("path_to_extension_library.so", "CPU")
#! [ie:load_old_extension]
+44
View File
@@ -0,0 +1,44 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
#! [ngraph:graph]
# _____________ _____________
# | Parameter | | Parameter |
# | data1 | | data2 |
# |___________| |___________|
# | |
# | |
# \ /
# \ /
# \ /
# ____\____/____
# | Concat |
# | concat |
# |____________|
# |
# |
# |
# _______|_______
# | Result |
# | result |
# |_____________|
import ngraph as ng
import numpy as np
data1 = ng.opset8.parameter([1, 3, 2, 2], np.int64)
data1.friendly_name = "data1" # operation name
data2 = ng.opset8.parameter([1, 2, 2, 2], np.int64)
data2.friendly_name = "data2" # operation name
concat = ng.opset8.concat([data1, data2], 1)
concat.friendly_name = "concat" # operation name
result = ng.opset8.result(concat)
result.friendly_name = "result" # operation name
f = ng.Function(result, [data1, data2], "function_name")
#! [ngraph:graph]
+109
View File
@@ -0,0 +1,109 @@
# Copyright (C) 2022 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
import numpy as np
#! [ov_api_2_0:create_core]
import openvino.runtime as ov
core = ov.Core()
#! [ov_api_2_0:create_core]
#! [ov_api_2_0:read_model]
model = core.read_model("model.xml")
#! [ov_api_2_0:read_model]
#! [ov_api_2_0:compile_model]
compiled_model = core.compile_model(model, "CPU")
#! [ov_api_2_0:compile_model]
#! [ov_api_2_0:create_infer_request]
infer_request = compiled_model.create_infer_request()
#! [ov_api_2_0:create_infer_request]
#! [ov_api_2_0:get_input_tensor_aligned]
# Get input tensor by index
input_tensor1 = infer_request.get_input_tensor(0)
# Element types, names and layouts are aligned with framework
assert input_tensor1.data.dtype == np.int64
# Fill the first data ...
# Get input tensor by tensor name
input_tensor2 = infer_request.get_tensor("data2_t")
assert input_tensor2.data.dtype == np.int64
# Fill the second data ...
#! [ov_api_2_0:get_input_tensor_aligned]
#! [ov_api_2_0:get_input_tensor_v10]
# Get input tensor by index
input_tensor1 = infer_request.get_input_tensor(0)
# IR v10 works with converted precisions (i64 -> i32)
assert input_tensor1.data.dtype == np.int32
# Fill the first data ...
# Get input tensor by tensor name
input_tensor2 = infer_request.get_tensor("data2_t")
# IR v10 works with converted precisions (i64 -> i32)
assert input_tensor2.data.dtype == np.int32
# Fill the second data ..
#! [ov_api_2_0:get_input_tensor_v10]
#! [ov_api_2_0:inference]
results = infer_request.infer()
#! [ov_api_2_0:inference]
input_data = iter(list())
def process_results(results, frame_id):
pass
#! [ov_api_2_0:start_async_and_wait]
# Start async inference on a single infer request
infer_request.start_async()
# Wait for 1 milisecond
infer_request.wait_for(1)
# Wait for inference completion
infer_request.wait()
# Demonstrates async pipeline using AsyncInferQueue
results = []
def callback(request, frame_id):
# Copy the data from output tensors to numpy array and process it
results_copy = {output: data[:] for output, data in request.results.items()}
results.append(process_results(results_copy, frame_id))
# Create AsyncInferQueue with 4 infer requests
infer_queue = ov.AsyncInferQueue(compiled_model, jobs=4)
# Set callback for each infer request in the queue
infer_queue.set_callback(callback)
total_frames = 100
for i in range(total_frames):
# Wait for at least one available infer request and start asynchronous inference
infer_queue.start_async(next(input_data), userdata=i)
# Wait for all requests to complete
infer_queue.wait_all()
#! [ov_api_2_0:start_async_and_wait]
#! [ov_api_2_0:get_output_tensor_aligned]
# Model has only one output
output_tensor = infer_request.get_output_tensor()
# Element types, names and layouts are aligned with framework
assert output_tensor.data.dtype == np.int64
# process output data ...
#! [ov_api_2_0:get_output_tensor_aligned]
#! [ov_api_2_0:get_output_tensor_v10]
# Model has only one output
output_tensor = infer_request.get_output_tensor()
# IR v10 works with converted precisions (i64 -> i32)
assert output_tensor.data.dtype == np.int32
# process output data ...
#! [ov_api_2_0:get_output_tensor_v10]
#! [ov_api_2_0:load_old_extension]
core.add_extension("path_to_extension_library.so")
#! [ov_api_2_0:load_old_extension]
+46
View File
@@ -0,0 +1,46 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
#! [ov:graph]
# _____________ _____________
# | Parameter | | Parameter |
# | data1 | | data2 |
# |___________| |___________|
# | |
# data1_t | | data2_t
# \ /
# \ /
# \ /
# ____\____/____
# | Concat |
# | concat |
# |____________|
# |
# | concat_t
# |
# _______|_______
# | Result |
# | result |
# |_____________|
import openvino.runtime as ov
data1 = ov.opset8.parameter([1, 3, 2, 2], ov.Type.i64)
data1.friendly_name = "data1" # operation name
data1.output(0).name = "data1_t" # tensor name
data2 = ov.opset8.parameter([1, 2, 2, 2], ov.Type.i64)
data2.friendly_name = "data2" # operation name
data2.output(0).name = "data2_t" # tensor name
concat = ov.opset8.concat([data1, data2], 1)
concat.friendly_name = "concat" # operation name
concat.output(0).name = "concat_t" # tensor name
result = ov.opset8.result(concat)
result.friendly_name = "result" # operation name
model = ov.Model(result, [data1, data2], "model_name")
#! [ov:graph]
+2 -2
View File
@@ -54,12 +54,12 @@ return 0;
int main_old() {
InferenceEngine::Core core;
//! [core_get_metric]
auto full_device_name = core.GetConfig("CPU", METRIC_KEY(FULL_DEVICE_NAME)).as<std::string>();
auto full_device_name = core.GetMetric("CPU", METRIC_KEY(FULL_DEVICE_NAME)).as<std::string>();
//! [core_get_metric]
//! [core_get_config]
// a user has to parse std::string after
auto num_streams = core.GetMetric("CPU", CONFIG_KEY(CPU_THROUGHPUT_STREAMS)).as<std::string>();
auto num_streams = core.GetConfig("CPU", CONFIG_KEY(CPU_THROUGHPUT_STREAMS)).as<std::string>();
//! [core_get_config]
//! [core_set_config]
+38
View File
@@ -42,3 +42,41 @@ perf_mode = compiled_model.get_property("PERFORMANCE_HINT")
# ! [compiled_model_get_ro_property]
nireq = compiled_model.get_property("OPTIMAL_NUMBER_OF_INFER_REQUESTS")
# ! [compiled_model_get_ro_property]
from openvino.inference_engine import IECore
core = IECore()
#! [core_get_metric]
full_device_name = core.get_metric("CPU", "FULL_DEVICE_NAME")
#! [core_get_metric]
#! [core_get_config]
num_streams = core.get_config("CPU", "CPU_THROUGHPUT_STREAMS")
#! [core_get_config]
#! [core_set_config]
core.set_config({"PERF_COUNT": "YES"}, "CPU")
#! [core_set_config]
net = core.read_network("sample.xml")
#! [core_load_network]
exec_network = core.load_network(net, "MULTI", {"DEVICE_PRIORITIES": "CPU, GPU",
"PERFORMANCE_HINT": "THROUGHPUT",
"ENFORCE_BF16": "NO"})
#! [core_load_network]
#! [executable_network_set_config]
# turn CPU off for multi-device execution
exec_network.set_config({"DEVICE_PRIORITIES": "GPU"})
#! [executable_network_set_config]
#! [executable_network_get_metric]
nireq = exec_network.get_metric("OPTIMAL_NUMBER_OF_INFER_REQUESTS")
#! [executable_network_get_metric]
#! [executable_network_get_config]
perf_hint = exec_network.get_config("PERFORMANCE_HINT")
#! [executable_network_get_config]
+36
View File
@@ -131,3 +131,39 @@ infer_queue.wait_all()
assert all(data_done)
#! [asyncinferqueue_set_callback]
#! [releasing_gil]
import openvino.runtime as ov
import cv2 as cv
from threading import Thread
input_data = []
# Processing input data will be done in a separate thread
# while compilation of the model and creation of the infer request
# is going to be executed in the main thread.
def prepare_data(input, image_path):
image = cv.imread(image_path)
h, w = list(input.shape)[-2:]
image = cv.resize(image, (h, w))
image = image.transpose((2, 0, 1))
image = np.expand_dims(image, 0)
input_data.append(image)
core = ov.Core()
model = core.read_model("model.xml")
# Create thread with prepare_data function as target and start it
thread = Thread(target=prepare_data, args=[model.input(), "path/to/image"])
thread.start()
# The GIL will be released in compile_model.
# It allows a thread above to start the job,
# while main thread is running in the background.
compiled = core.compile_model(model, "GPU")
# After returning from compile_model, the main thread acquires the GIL
# and starts create_infer_request which releases it once again.
request = compiled.create_infer_request()
# Join the thread to make sure the input_data is ready
thread.join()
# running the inference
request.infer(input_data)
#! [releasing_gil]
+1 -1
View File
@@ -38,7 +38,7 @@ bool Identity::evaluate(ov::TensorVector& outputs, const ov::TensorVector& input
auto in = inputs[0];
auto out = outputs[0];
out.set_shape(in.get_shape());
memcpy(out.data(), in.data(), in.get_size());
memcpy(out.data(), in.data(), in.get_byte_size());
return true;
}
@@ -368,6 +368,20 @@ std::vector<StridedSliceStrideOptionalParams> generateStrideOptionalParams() {
std::vector<int64_t>{0, 0, 0},
reference_tests::Tensor(IN_ET, {1, 4}, std::vector<T>{20, 21, 22, 23}),
"strided_slice_stride_optional_dynamic"),
// strided_slice_stride_optional_dynamic_empty_output_tensor
StridedSliceStrideOptionalParams(
PartialShape::dynamic(),
reference_tests::Tensor(IN_ET, {2, 3, 4}, std::vector<T>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}),
reference_tests::Tensor(element::i64, {2}, std::vector<int64_t>{0, 0}),
reference_tests::Tensor(element::i64, {2}, std::vector<int64_t>{-1, 0}),
std::vector<int64_t>{1, 0},
std::vector<int64_t>{1, 0},
std::vector<int64_t>{},
std::vector<int64_t>{},
std::vector<int64_t>{},
reference_tests::Tensor(IN_ET, {2, 0, 4}, std::vector<T>{}),
"strided_slice_stride_optional_dynamic_empty_output_tensor"),
};
return params;
}
+1
View File
@@ -64,6 +64,7 @@ if [ -f /etc/lsb-release ]; then
libgstreamer1.0-0 \
gstreamer1.0-plugins-base \
libusb-1.0-0-dev \
libtbb-dev \
libtinfo5 \
libopenblas-dev
if apt-cache search --names-only '^libjson-c2'| grep -q libjson-c2; then
@@ -16,10 +16,10 @@ find_package(OpenCV COMPONENTS core imgproc imgcodecs QUIET)
if(NOT OpenCV_FOUND)
message(WARNING "OPENCV is disabled or not found, ${TARGET_NAME} is built without OPENCV support")
else()
add_definitions(-DUSE_OPENCV)
target_compile_definitions(${TARGET_NAME} PRIVATE USE_OPENCV)
endif()
target_link_libraries(${TARGET_NAME} PUBLIC ${OpenCV_LIBRARIES})
target_link_libraries(${TARGET_NAME} PRIVATE ${OpenCV_LIBRARIES})
target_include_directories(${TARGET_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
+40 -31
View File
@@ -14,39 +14,48 @@ ie_add_sample(NAME ${TARGET_NAME}
# Optional OpenCL dependnency
find_package(OpenCL)
find_path(OpenCL_HPP_INCLUDE_DIR
NAMES
CL/cl2.hpp OpenCL/cl2.hpp
HINTS
${opencl_root_hints}
ENV "PROGRAMFILES(X86)"
ENV AMDAPPSDKROOT
ENV INTELOCLSDKROOT
ENV NVSDKCOMPUTE_ROOT
ENV CUDA_PATH
ENV ATISTREAMSDKROOT
ENV OCL_ROOT
PATH_SUFFIXES
include
OpenCL/common/inc
"AMD APP/include")
if(TARGET OpenCL)
# Use OpenCL CPP headers from sources if present
set(OpenCL_HEADERS ${OPENCL_HEADERS_DIR})
set(OpenCL_LIB "OpenCL")
elseif(OpenCL_HPP_INCLUDE_DIR)
# Append OpenCL CPP headers to C headers and use both
set(OpenCL_HEADERS ${OpenCL_INCLUDE_DIR} ${OpenCL_HPP_INCLUDE_DIR})
set(OpenCL_LIB "OpenCL::OpenCL")
if(DEFINED ENABLE_INTEL_GPU AND NOT ENABLE_INTEL_GPU)
# Intel GPU plugin is turned off explicitly
option(SAMPLES_ENABLE_OPENCL "Use OpenCL in benchmark_app" OFF)
else()
option(SAMPLES_ENABLE_OPENCL "Use OpenCL in benchmark_app" ON)
endif()
if(OpenCL_FOUND AND OpenCL_HEADERS)
target_link_libraries(${TARGET_NAME} PRIVATE ${OpenCL_LIB})
target_include_directories(${TARGET_NAME} PRIVATE ${OpenCL_HEADERS})
target_compile_definitions(${TARGET_NAME} PRIVATE HAVE_GPU_DEVICE_MEM_SUPPORT)
if(SAMPLES_ENABLE_OPENCL)
find_package(OpenCL)
find_path(OpenCL_HPP_INCLUDE_DIR
NAMES
CL/cl2.hpp OpenCL/cl2.hpp
HINTS
${opencl_root_hints}
ENV "PROGRAMFILES(X86)"
ENV AMDAPPSDKROOT
ENV INTELOCLSDKROOT
ENV NVSDKCOMPUTE_ROOT
ENV CUDA_PATH
ENV ATISTREAMSDKROOT
ENV OCL_ROOT
PATH_SUFFIXES
include
OpenCL/common/inc
"AMD APP/include")
if(TARGET OpenCL)
# Use OpenCL CPP headers from sources if present
set(OpenCL_HEADERS ${OPENCL_HEADERS_DIR})
set(OpenCL_LIB "OpenCL")
elseif(OpenCL_HPP_INCLUDE_DIR)
# Append OpenCL CPP headers to C headers and use both
set(OpenCL_HEADERS ${OpenCL_INCLUDE_DIR} ${OpenCL_HPP_INCLUDE_DIR})
set(OpenCL_LIB "OpenCL::OpenCL")
endif()
if(OpenCL_FOUND AND OpenCL_HEADERS)
target_link_libraries(${TARGET_NAME} PRIVATE ${OpenCL_LIB})
target_include_directories(${TARGET_NAME} PRIVATE ${OpenCL_HEADERS})
target_compile_definitions(${TARGET_NAME} PRIVATE HAVE_GPU_DEVICE_MEM_SUPPORT)
endif()
endif()
# Optional OpenCV dependency
-4
View File
@@ -167,12 +167,8 @@ This section provides step-by-step instructions on how to run the Benchmark Tool
```sh
omz_downloader --name googlenet-v1 -o <models_dir>
```
<<<<<<< HEAD
3. Convert the model to the OpenVINO IR format. Run the Model Optimizer using the `mo` command with the path to the model, model format and output directory to generate the IR files:
=======
2. Convert the model to the OpenVINO IR format. Run the Model Optimizer using the `mo` command with the path to the model, model format (which must be FP32 for CPU and FPG) and output directory to generate the IR files:
>>>>>>> cf8ccb590a... Removed obsolete code snippets (#11061)
```sh
mo --input_model <models_dir>/public/googlenet-v1/googlenet-v1.caffemodel --data_type FP32 --output_dir <ir_dir>
```
+37 -27
View File
@@ -49,7 +49,10 @@ int main(int argc, char* argv[]) {
BaseFile* fileOutput;
ArkFile arkFile;
NumpyFile numpyFile;
auto extInputFile = fileExt(FLAGS_i);
std::pair<std::string, std::vector<std::string>> input_data;
if (!FLAGS_i.empty())
input_data = parse_parameters(FLAGS_i);
auto extInputFile = fileExt(input_data.first);
if (extInputFile == "ark") {
file = &arkFile;
} else if (extInputFile == "npz") {
@@ -60,9 +63,9 @@ int main(int argc, char* argv[]) {
std::vector<std::string> inputFiles;
std::vector<uint32_t> numBytesThisUtterance;
uint32_t numUtterances(0);
if (!FLAGS_i.empty()) {
if (!input_data.first.empty()) {
std::string outStr;
std::istringstream stream(FLAGS_i);
std::istringstream stream(input_data.first);
uint32_t currentNumUtterances(0), currentNumBytesThisUtterance(0);
while (getline(stream, outStr, ',')) {
std::string filename(fileNameNoExt(outStr) + "." + extInputFile);
@@ -89,19 +92,26 @@ int main(int argc, char* argv[]) {
std::vector<std::string> output_names;
std::vector<size_t> ports;
// --------------------------- Processing custom outputs ---------------------------------------------
if (!FLAGS_oname.empty()) {
output_names = convert_str_to_vector(FLAGS_oname);
for (const auto& output_name : output_names) {
auto pos_layer = output_name.rfind(":");
if (pos_layer == std::string::npos) {
throw std::logic_error("Output " + output_name + " doesn't have a port");
}
outputs.push_back(output_name.substr(0, pos_layer));
try {
ports.push_back(std::stoi(output_name.substr(pos_layer + 1)));
} catch (const std::exception&) {
throw std::logic_error("Ports should have integer type");
}
std::pair<std::string, std::vector<std::string>> output_data;
std::pair<std::string, std::vector<std::string>> reference_data;
if (!FLAGS_o.empty())
output_data = parse_parameters(FLAGS_o);
if (!FLAGS_r.empty())
reference_data = parse_parameters(FLAGS_r);
if (!output_data.second.empty())
output_names = output_data.second;
else if (!reference_data.second.empty())
output_names = reference_data.second;
for (const auto& output_name : output_names) {
auto pos_layer = output_name.rfind(":");
if (pos_layer == std::string::npos) {
throw std::logic_error("Output " + output_name + " doesn't have a port");
}
outputs.push_back(output_name.substr(0, pos_layer));
try {
ports.push_back(std::stoi(output_name.substr(pos_layer + 1)));
} catch (const std::exception&) {
throw std::logic_error("Ports should have integer type");
}
}
// ------------------------------ Preprocessing ------------------------------------------------------
@@ -304,8 +314,8 @@ int main(int argc, char* argv[]) {
std::vector<ov::Tensor> ptrInputBlobs;
auto cInputInfo = executableNet.inputs();
check_number_of_inputs(cInputInfo.size(), numInputFiles);
if (!FLAGS_iname.empty()) {
std::vector<std::string> inputNameBlobs = convert_str_to_vector(FLAGS_iname);
if (!input_data.second.empty()) {
std::vector<std::string> inputNameBlobs = input_data.second;
if (inputNameBlobs.size() != cInputInfo.size()) {
std::string errMessage(std::string("Number of network inputs ( ") + std::to_string(cInputInfo.size()) +
" ) is not equal to the number of inputs entered in the -iname argument ( " +
@@ -328,15 +338,15 @@ int main(int argc, char* argv[]) {
std::vector<std::string> output_name_files;
std::vector<std::string> reference_name_files;
size_t count_file = 1;
if (!FLAGS_o.empty()) {
output_name_files = convert_str_to_vector(FLAGS_o);
if (!output_data.first.empty()) {
output_name_files = convert_str_to_vector(output_data.first);
if (output_name_files.size() != outputs.size() && !outputs.empty()) {
throw std::logic_error("The number of output files is not equal to the number of network outputs.");
}
count_file = output_name_files.empty() ? 1 : output_name_files.size();
}
if (!FLAGS_r.empty()) {
reference_name_files = convert_str_to_vector(FLAGS_r);
if (!reference_data.first.empty()) {
reference_name_files = convert_str_to_vector(reference_data.first);
if (reference_name_files.size() != outputs.size() && !outputs.empty()) {
throw std::logic_error("The number of reference files is not equal to the number of network outputs.");
}
@@ -429,9 +439,9 @@ int main(int argc, char* argv[]) {
BaseFile* fileReferenceScores;
std::string refUtteranceName;
if (!FLAGS_r.empty()) {
if (!reference_data.first.empty()) {
/** Read file with reference scores **/
auto exReferenceScoresFile = fileExt(FLAGS_r);
auto exReferenceScoresFile = fileExt(reference_data.first);
if (exReferenceScoresFile == "ark") {
fileReferenceScores = &arkFile;
} else if (exReferenceScoresFile == "npz") {
@@ -540,12 +550,12 @@ int main(int argc, char* argv[]) {
continue;
}
ptrInputBlobs.clear();
if (FLAGS_iname.empty()) {
if (input_data.second.empty()) {
for (auto& input : cInputInfo) {
ptrInputBlobs.push_back(inferRequest.inferRequest.get_tensor(input));
}
} else {
std::vector<std::string> inputNameBlobs = convert_str_to_vector(FLAGS_iname);
std::vector<std::string> inputNameBlobs = input_data.second;
for (const auto& input : inputNameBlobs) {
ov::Tensor blob = inferRequests.begin()->inferRequest.get_tensor(input);
if (!blob) {
@@ -638,7 +648,7 @@ int main(int argc, char* argv[]) {
for (size_t next_output = 0; next_output < count_file; next_output++) {
if (!FLAGS_o.empty()) {
auto exOutputScoresFile = fileExt(FLAGS_o);
auto exOutputScoresFile = fileExt(output_data.first);
if (exOutputScoresFile == "ark") {
fileOutput = &arkFile;
} else if (exOutputScoresFile == "npz") {
@@ -96,10 +96,6 @@ static const char scale_factor_message[] =
/// @brief message for batch size argument
static const char batch_size_message[] = "Optional. Batch size 1-8 (default 1)";
/// @brief message for #threads for CPU inference
static const char infer_num_threads_message[] = "Optional. Number of threads to use for concurrent async"
" inference requests on the GNA.";
/// @brief message for left context window argument
static const char context_window_message_l[] =
"Optional. Number of frames for left context windows (default is 0). "
@@ -184,9 +180,6 @@ DEFINE_string(sf, "", scale_factor_message);
/// @brief Batch size (default 0)
DEFINE_int32(bs, 0, batch_size_message);
/// @brief Number of threads to use for inference on the CPU (also affects Hetero cases)
DEFINE_int32(nthreads, 1, infer_num_threads_message);
/// @brief Right context window size (default 0)
DEFINE_int32(cw_r, 0, context_window_message_r);
+38 -5
View File
@@ -432,7 +432,7 @@ bool check_name(const ov::OutputVector& nodes, const std::string& node_name) {
/**
* @brief Parse scale factors per input
* Format : <input_name1>:<sf1>,<input2>:<sf2> or just <sf>
* Format : <input_name1>=<sf1>,<input2>=<sf2> or just <sf>
* @param inputs model inputs
* @param values_string values_string input string
* @return map of scale factors per input
@@ -454,11 +454,11 @@ std::map<std::string, float> parse_scale_factors(const ov::OutputVector& inputs,
std::map<std::string, float> result;
auto scale_factor_strings = split(values_string, ',');
for (auto& scale_factor_string : scale_factor_strings) {
auto values = split(scale_factor_string, ':');
auto values = split(scale_factor_string, '=');
if (values.size() == 1) {
if (scale_factor_strings.size() != 1) {
throw std::logic_error("Unrecognized scale factor format! "
"Please specify <input_name1>:<sf1>,<input_name2>:<sf2> or "
"Please specify <input_name1>=<sf1>,<input_name2>=<sf2> or "
"just <sf> to be applied to all inputs");
}
auto scale_factor = get_sf(values.at(0));
@@ -468,8 +468,7 @@ std::map<std::string, float> parse_scale_factors(const ov::OutputVector& inputs,
} else if (values.size() > 0) {
auto sf_sting = values.back();
values.pop_back();
// input name can contain port, concat back
auto input_name = concat(values, ':');
auto input_name = values.back();
check_name(inputs, input_name);
result[input_name] = get_sf(sf_sting, input_name);
}
@@ -535,3 +534,37 @@ std::map<std::string, std::string> parse_input_layouts(const std::string& layout
throw std::logic_error("Can't parse input parameter string: " + layout_string);
return return_value;
}
/**
* @brief Parse parameters for inputs/outputs like as "<name1>=<file1.ark/.npz>,<name2>=<file2.ark/.npz>" or
* "<file.ark/.npz>" in case of one input/output
* @param file_paths_string input/output path
* @return pair of filename and vector of tensor_names
*/
std::pair<std::string, std::vector<std::string>> parse_parameters(const std::string file_paths_string) {
auto search_string = file_paths_string;
char comma_delim = ',';
char equal_delim = '=';
std::string filename = "";
std::vector<std::string> tensor_names;
std::vector<std::string> filenames;
if (!std::count(search_string.begin(), search_string.end(), comma_delim) &&
!std::count(search_string.begin(), search_string.end(), equal_delim)) {
return {search_string, tensor_names};
}
search_string += comma_delim;
std::vector<std::string> splitted = split(search_string, comma_delim);
for (size_t j = 0; j < splitted.size(); j++) {
auto semicolon_pos = splitted[j].find_first_of(equal_delim);
if (semicolon_pos != std::string::npos) {
tensor_names.push_back(splitted[j].substr(0, semicolon_pos));
filenames.push_back(splitted[j].substr(semicolon_pos + 1, std::string::npos));
}
}
for (std::vector<std::string>::const_iterator name = filenames.begin(); name != filenames.end(); ++name) {
filename += *name;
if (name != filenames.end() - 1)
filename += comma_delim;
}
return {filename, tensor_names};
}
@@ -14,7 +14,7 @@ from openvino.runtime import AsyncInferQueue, Core, InferRequest, Layout, Type
def parse_args() -> argparse.Namespace:
"""Parse and return command line arguments"""
"""Parse and return command line arguments."""
parser = argparse.ArgumentParser(add_help=False)
args = parser.add_argument_group('Options')
# fmt: off
@@ -9,7 +9,7 @@ from openvino.runtime import Core
def param_to_string(parameters) -> str:
"""Convert a list / tuple of parameters returned from IE to a string"""
"""Convert a list / tuple of parameters returned from IE to a string."""
if isinstance(parameters, (list, tuple)):
return ', '.join([str(x) for x in parameters])
else:
@@ -16,7 +16,7 @@ from data import digits
def create_ngraph_function(model_path: str) -> Model:
"""Create a model on the fly from the source code using ngraph"""
"""Create a model on the fly from the source code using ngraph."""
def shape_and_length(shape: list) -> typing.Tuple[list, int]:
length = reduce(lambda x, y: x * y, shape)
+5 -1
View File
@@ -1,7 +1,11 @@
[flake8]
# ignore:
# D100 - Missing docstring in public module
# D101 - Missing docstring in public class
# D103 - Missing docstring in public function
filename = *.py
max-line-length = 160
ignore = E203
ignore = E203,D100,D101,D103
max-parameters-amount = 8
show_source = True
docstring-convention = google
+2 -2
View File
@@ -5,7 +5,7 @@ import argparse
def build_arg_parser() -> argparse.ArgumentParser:
"""Create and return argument parser"""
"""Create and return argument parser."""
parser = argparse.ArgumentParser(add_help=False)
args = parser.add_argument_group('Options')
model = parser.add_mutually_exclusive_group(required=True)
@@ -73,7 +73,7 @@ def build_arg_parser() -> argparse.ArgumentParser:
def parse_args() -> argparse.Namespace:
"""Parse and validate command-line arguments"""
"""Parse and validate command-line arguments."""
parser = build_arg_parser()
args = parser.parse_args()
+6 -6
View File
@@ -15,9 +15,9 @@ class FileData(NamedTuple):
def read_ark_file(file_name: str) -> FileData:
"""Read utterance matrices from a .ark file"""
"""Read utterance matrices from a .ark file."""
def read_key(input_file: IO[Any]) -> str:
"""Read a identifier of utterance matrix"""
"""Read a identifier of utterance matrix."""
key = ''
char = input_file.read(1).decode()
@@ -28,7 +28,7 @@ def read_ark_file(file_name: str) -> FileData:
return key
def read_matrix(input_file: IO[Any]) -> np.ndarray:
"""Read a utterance matrix"""
"""Read a utterance matrix."""
header = input_file.read(5).decode()
if 'FM' in header:
num_of_bytes = 4
@@ -61,7 +61,7 @@ def read_ark_file(file_name: str) -> FileData:
def write_ark_file(file_name: str, keys: List[str], utterances: List[np.ndarray]):
"""Write utterance matrices to a .ark file"""
"""Write utterance matrices to a .ark file."""
with open(file_name, 'wb') as output_file:
for key, matrix in zip(keys, utterances):
# write a utterance key
@@ -86,7 +86,7 @@ def write_ark_file(file_name: str, keys: List[str], utterances: List[np.ndarray]
def read_utterance_file(file_name: str) -> FileData:
"""Read utterance matrices from a file"""
"""Read utterance matrices from a file."""
file_extension = file_name.split('.')[-1]
if file_extension == 'ark':
@@ -100,7 +100,7 @@ def read_utterance_file(file_name: str) -> FileData:
def write_utterance_file(file_name: str, keys: List[str], utterances: List[np.ndarray]):
"""Write utterance matrices to a file"""
"""Write utterance matrices to a file."""
file_extension = file_name.split('.')[-1]
if file_extension == 'ark':
@@ -22,7 +22,7 @@ from utils import (GNA_ATOM_FREQUENCY, GNA_CORE_FREQUENCY,
def do_inference(data: Dict[str, np.ndarray], infer_request: InferRequest, cw_l: int = 0, cw_r: int = 0) -> np.ndarray:
"""Do a synchronous matrix inference"""
"""Do a synchronous matrix inference."""
frames_to_infer = {}
result = {}
+4 -4
View File
@@ -35,7 +35,7 @@ def compare_with_reference(result: np.ndarray, reference: np.ndarray):
def get_scale_factor(matrix: np.ndarray) -> float:
"""Get scale factor for quantization using utterance matrix"""
"""Get scale factor for quantization using utterance matrix."""
# Max to find scale factor
target_max = 16384
max_val = np.max(matrix)
@@ -46,14 +46,14 @@ def get_scale_factor(matrix: np.ndarray) -> float:
def set_scale_factors(plugin_config: dict, scale_factors: list):
"""Set a scale factor provided for each input"""
"""Set a scale factor provided for each input."""
for i, scale_factor in enumerate(scale_factors):
log.info(f'For input {i} using scale factor of {scale_factor:.7f}')
plugin_config[f'GNA_SCALE_FACTOR_{i}'] = str(scale_factor)
def parse_scale_factors(args: argparse.Namespace) -> list:
"""Get a list of scale factors for input files"""
"""Get a list of scale factors for input files."""
input_files = re.split(', |,', args.input)
scale_factors = re.split(', |,', str(args.scale_factor))
scale_factors = list(map(float, scale_factors))
@@ -72,7 +72,7 @@ def parse_scale_factors(args: argparse.Namespace) -> list:
def parse_outputs_from_args(args: argparse.Namespace) -> Tuple[List[str], List[int]]:
"""Get a list of outputs specified in the args"""
"""Get a list of outputs specified in the args."""
name_and_port = [output.split(':') for output in re.split(', |,', args.output_layers)]
try:
return [name for name, _ in name_and_port], [int(port) for _, port in name_and_port]
+35 -13
View File
@@ -1,13 +1,35 @@
flake8==3.9.2
flake8-bugbear==21.4.3
flake8-comprehensions==3.3.0
flake8-docstrings==1.6.0
flake8-quotes==3.2.0
mypy==0.812
onnx==1.11.0
pydocstyle==5.1.1
pytest-xdist==2.2.1
pytest==6.1.2
retrying==1.3.3
tox==3.24.5
wheel==0.36.2
bandit
black
flake8
flake8-annotations-complexity
flake8-broken-line
flake8-bugbear
flake8-class-attributes-order
flake8-comprehensions
flake8-debugger
flake8-docstrings
flake8-eradicate
flake8-executable
flake8-expression-complexity
flake8-print
flake8-pytest-style
flake8-rst-docstrings
flake8-string-format
flake8-variables-names
flake8_builtins
flake8_coding
flake8_commas
flake8_pep3101
flake8_quotes
import-order
mypy
onnx
Pep8-naming
pydocstyle
pytest-xdist
pytest
radon
retrying
tox
types-pkg_resources
wheel
+58 -6
View File
@@ -1,15 +1,62 @@
[tox:tox]
envlist = py3
[testenv]
skipdist=True
skip_install=True
deps =
-rrequirements.txt
-rrequirements_test.txt
setenv =
OV_BACKEND = {env:OV_BACKEND:"CPU"}
PYTHONPATH = {env:PYTHONPATH}
OpenVINO_DIR = {env:OpenVINO_DIR}
passenv =
http_proxy
https_proxy
commands=
{envbindir}/python setup.py bdist_wheel
{envbindir}/pip install --no-index --pre --find-links=dist/ openvino
pytest --backend={env:OV_BACKEND} tests -v -k 'not _cuda' --ignore=tests/test_onnx/test_zoo_models.py --ignore=tests/test_utils --ignore=tests/test_inference_engine
pytest --backend={env:OV_BACKEND} tests_compatibility/test_ngraph -v -k 'not _cuda' --ignore=tests_compatibility/test_onnx/test_zoo_models.py
[testenv:zoo_models]
commands=
{envbindir}/python setup.py bdist_wheel
{envbindir}/pip install --no-index --pre --find-links=dist/ openvino
pytest --backend={env:OV_BACKEND} tests/test_onnx/test_zoo_models.py -v -n 4 --forked -k 'not _cuda' --model_zoo_xfail
[testenv:devenv]
envdir = devenv
usedevelop = True
deps = -rrequirements.txt
[flake8]
filename = *.py, *.pyx
# ignore:
# D100 - Missing docstring in public module
# D102 - Missing docstring in public method
# D103 - Missing docstring in public function
# D104 - Missing docstring in public package
# D105 - Missing docstring in magic method
# D107 - Missing docstring in __init__
# D412 - No blank lines allowed between a section header and its content
# F401 - module imported but unused
# W503 - line break before binary operator (prefer line breaks before op, not after)
ignore=D100,D102,D103,D104,D105,D107,D412,F401,W503
inline-quotes = double
filename = *.py
max-line-length = 160
ignore = E203
max-parameters-amount = 8
show_source = True
docstring-convention = google
enable-extensions = G
per-file-ignores =
*.pyx: E225, E226, E251, E999, E800, E265, E203, E266, E227, E211
tests/*: S101, T001
*__init__.py: E402, F403, F405, F405
# todo: will be fixed as part of 81803
tests/*: A001,C101,C812,C815,C816,C819,CCE001,D100,D101,D102,D103,D104,D105,D107,D212,E800,ECE001,N400,N802,N806,P101,P103,PT001,PT005,PT006,PT007,PT011,PT012,PT019,PT023,RST201,RST301,S001,T001,VNE001,VNE002,VNE003,W503
tests_compatibility/test_ngraph/*: A001,C101,C812,C815,C816,C819,CCE001,D100,D101,D102,D103,D104,D105,D107,D212,E800,ECE001,N400,N802,N806,P101,P103,PT001,PT005,PT006,PT007,PT011,PT012,PT019,PT023,RST201,RST301,S001,T001,VNE001,VNE002,VNE003,W503
src/compatibility/ngraph/*: A001,A002,C101,C812,C819,CCE001,E800,N803,N806,P101,RST201,RST202,RST203,RST206,RST301,T001,TAE002,VNE001,VNE003
# todo: will be fixed as part of 81803
src/openvino/*: A001,A002,C101,C812,C819,CCE001,E402,E800,N803,N806,P101,RST201,RST202,RST203,RST205,RST206,RST299,RST301,T001,TAE002,VNE001,VNE002,VNE003
[pydocstyle]
convention = google
@@ -20,4 +67,9 @@ disable_error_code = attr-defined
show_column_numbers = True
show_error_context = True
show_absolute_path = True
pretty = True
pretty = True
follow_imports=normal
disallow_untyped_defs = True
disallow_untyped_calls = True
check_untyped_defs = True
show_none_errors = True
@@ -1,16 +1,16 @@
[flake8]
# D104 - Missing docstring in public package
inline-quotes = double
filename = *.py, *.pyx
max-line-length = 160
ignore = E203
ignore = E203,D104
max-parameters-amount = 8
show_source = True
docstring-convention = google
enable-extensions = G
per-file-ignores =
*.pyx: E225, E226, E251, E999, E800, E265, E203, E266, E227, E211
tests/*: S101, T001
*__init__.py: F403, F405, F405
*__init__.py: F403, F405
[pydocstyle]
convention = google
@@ -334,23 +334,17 @@ class Core(CoreBase):
)
class ExtendedModel(CompiledModel):
"""CompiledModel that additionally holds Core object."""
def __init__(self, core: Core, net: CompiledModel):
super().__init__(net)
self.core = core # needs to store Core object for CPU plugin
def compile_model(model_path: str) -> CompiledModel:
"""Compact method to compile model with AUTO plugin.
:param model_path: Path to file with model.
:type model_path: str
:return: Extended version of `CompiledModel` that holds and keeps alive `Core` object.
:return: A compiled model.
:rtype: openvino.runtime.CompiledModel
"""
core = Core()
return ExtendedModel(core, core.compile_model(model_path, "AUTO"))
return core.compile_model(model_path, "AUTO")
class OVAny(OVAnyBase):
@@ -4,4 +4,5 @@
"""Generic utilities. Factor related functions out to separate files."""
from openvino.pyopenvino.util import numpy_to_c
from openvino.pyopenvino.util import clone_model
from openvino.pyopenvino.util import get_constant_from_source, replace_node, replace_output_update_name
@@ -147,7 +147,6 @@ void regclass_AsyncInferQueue(py::module m) {
if (jobs == 0) {
jobs = (size_t)Common::get_optimal_number_of_requests(model);
}
std::vector<InferRequestWrapper> requests;
std::queue<size_t> idle_handles;
std::vector<py::object> user_ids(jobs);
@@ -161,7 +160,6 @@ void regclass_AsyncInferQueue(py::module m) {
requests.push_back(request);
idle_handles.push(handle);
}
return new AsyncInferQueue(requests, idle_handles, user_ids);
}),
py::arg("model"),
@@ -212,71 +210,61 @@ void regclass_AsyncInferQueue(py::module m) {
:type inputs: dict[Union[int, str, openvino.runtime.ConstOutput] : openvino.runtime.Tensor]
:param userdata: Any data that will be passed to a callback
:rtype: None
GIL is released while waiting for the next available InferRequest.
)");
cls.def(
"is_ready",
[](AsyncInferQueue& self) {
return self._is_ready();
},
R"(
cls.def("is_ready",
&AsyncInferQueue::_is_ready,
R"(
One of 'flow control' functions.
Returns True if any free request in the pool, otherwise False.
Function releases GIL, other threads can work while this function waits.
GIL is released while running this function.
:return: If there is at least one free InferRequest in a pool, returns True.
:rtype: bool
)");
cls.def(
"wait_all",
[](AsyncInferQueue& self) {
return self.wait_all();
},
R"(
One of 'flow control' functions. Blocking call.
Waits for all InferRequests in a pool to finish scheduled work.
cls.def("wait_all",
&AsyncInferQueue::wait_all,
R"(
One of 'flow control' functions. Blocking call.
Waits for all InferRequests in a pool to finish scheduled work.
Function releases GIL, other threads can work while this function waits.
)");
GIL is released while running this function.
)");
cls.def(
"get_idle_request_id",
[](AsyncInferQueue& self) {
return self.get_idle_request_id();
},
R"(
Returns next free id of InferRequest from queue's pool.
Function waits for any request to complete and then returns this request's id.
cls.def("get_idle_request_id",
&AsyncInferQueue::get_idle_request_id,
R"(
Returns next free id of InferRequest from queue's pool.
Function waits for any request to complete and then returns this request's id.
Function releases GIL, other threads can work while this function waits.
GIL is released while running this function.
:rtype: int
)");
:rtype: int
)");
cls.def(
"set_callback",
[](AsyncInferQueue& self, py::function callback) {
self.set_custom_callbacks(callback);
},
R"(
Sets unified callback on all InferRequests from queue's pool.
The signature of such function should have two arguments, where
the first one is InferRequest object and the second one is userdata
connected to InferRequest from the AsyncInferQueue's pool.
cls.def("set_callback",
&AsyncInferQueue::set_custom_callbacks,
R"(
Sets unified callback on all InferRequests from queue's pool.
Signature of such function should have two arguments, where
first one is InferRequest object and second one is userdata
connected to InferRequest from the AsyncInferQueue's pool.
.. code-block:: python
.. code-block:: python
def f(request, userdata):
result = request.output_tensors[0]
print(result + userdata)
def f(request, userdata):
result = request.output_tensors[0]
print(result + userdata)
async_infer_queue.set_callback(f)
async_infer_queue.set_callback(f)
:param callback: Any Python defined function that matches callback's requirements.
:type callback: function
)");
:param callback: Any Python defined function that matches callback's requirements.
:type callback: function
)");
cls.def(
"__len__",
@@ -33,6 +33,7 @@ void regclass_CompiledModel(py::module m) {
[](ov::CompiledModel& self) {
return std::make_shared<InferRequestWrapper>(self.create_infer_request(), self.inputs(), self.outputs());
},
py::call_guard<py::gil_scoped_release>(),
R"(
Creates an inference request object used to infer the compiled model.
The created request has allocated input and output tensors.
@@ -47,7 +48,10 @@ void regclass_CompiledModel(py::module m) {
auto request = self.create_infer_request();
// Update inputs if there are any
Common::set_request_tensors(request, inputs);
request.infer();
{
py::gil_scoped_release release;
request.infer();
}
return Common::outputs_to_dict(self.outputs(), request);
},
py::arg("inputs"),
@@ -59,6 +63,8 @@ void regclass_CompiledModel(py::module m) {
It is advised to use a dedicated InferRequest class for performance,
optimizing workflows, and creating advanced pipelines.
GIL is released during the inference.
:param inputs: Data to set on input tensors.
:type inputs: Dict[Union[int, str, openvino.runtime.ConstOutput], openvino.runtime.Tensor]
:return: Dictionary of results from output tensors with ports as keys.
@@ -72,9 +78,12 @@ void regclass_CompiledModel(py::module m) {
self.export_model(_stream);
return py::bytes(_stream.str());
},
py::call_guard<py::gil_scoped_release>(),
R"(
Exports the compiled model to bytes/output stream.
GIL is released while running this function.
:return: Bytes object that contains this compiled model.
:rtype: bytes
@@ -99,7 +108,10 @@ void regclass_CompiledModel(py::module m) {
(std::string)(py::repr(model_stream)) + "` provided");
}
std::stringstream _stream;
self.export_model(_stream);
{
py::gil_scoped_release release;
self.export_model(_stream);
}
model_stream.attr("flush")();
model_stream.attr("write")(py::bytes(_stream.str()));
model_stream.attr("seek")(0); // Always rewind stream!
@@ -114,6 +126,8 @@ void regclass_CompiledModel(py::module m) {
Function performs flushing of the stream, writes to it, and then rewinds
the stream to the beginning (using seek(0)).
GIL is released while running this function.
:param model_stream: A stream object to which the model will be serialized.
:type model_stream: io.BytesIO
:rtype: None
@@ -165,6 +179,7 @@ void regclass_CompiledModel(py::module m) {
cls.def("get_runtime_model",
&ov::CompiledModel::get_runtime_model,
py::call_guard<py::gil_scoped_release>(),
R"(
Gets runtime model information from a device.
@@ -77,6 +77,7 @@ void regclass_Core(py::module m) {
const std::map<std::string, std::string>& properties) {
return self.compile_model(model, device_name, {properties.begin(), properties.end()});
},
py::call_guard<py::gil_scoped_release>(),
py::arg("model"),
py::arg("device_name"),
py::arg("config") = py::dict(),
@@ -85,6 +86,8 @@ void regclass_Core(py::module m) {
Users can create as many compiled models as they need, and use them simultaneously
(up to the limitation of the hardware resources).
GIL is released while running this function.
:param model: Model acquired from read_model function.
:type model: openvino.runtime.Model
:param device_name: Name of the device which will load the model.
@@ -102,6 +105,7 @@ void regclass_Core(py::module m) {
const std::map<std::string, std::string>& config) {
return self.compile_model(model, ov::AnyMap{config.begin(), config.end()});
},
py::call_guard<py::gil_scoped_release>(),
py::arg("model"),
py::arg("config") = py::dict(),
R"(
@@ -109,6 +113,8 @@ void regclass_Core(py::module m) {
selected by AUTO plugin. Users can create as many compiled models as they need, and use
them simultaneously (up to the limitation of the hardware resources).
GIL is released while running this function.
:param model: Model acquired from read_model function.
:type model: openvino.runtime.Model
:param properties: Optional dict of pairs: (property name, property value) relevant only for this load operation.
@@ -125,6 +131,7 @@ void regclass_Core(py::module m) {
const std::map<std::string, std::string>& config) {
return self.compile_model(model_path, device_name, {config.begin(), config.end()});
},
py::call_guard<py::gil_scoped_release>(),
py::arg("model_path"),
py::arg("device_name"),
py::arg("properties") = py::dict(),
@@ -133,6 +140,8 @@ void regclass_Core(py::module m) {
This can be more efficient than using read_model + compile_model(model_in_memory_object) flow,
especially for cases when caching is enabled and cached model is available.
GIL is released while running this function.
:param model_path: A path to a model in IR / ONNX / PDPD format.
:type model_path: str
:param device_name: Name of the device to load the model to.
@@ -148,6 +157,7 @@ void regclass_Core(py::module m) {
[](ov::Core& self, const std::string& model_path, const std::map<std::string, std::string>& properties) {
return self.compile_model(model_path, ov::AnyMap{properties.begin(), properties.end()});
},
py::call_guard<py::gil_scoped_release>(),
py::arg("model_path"),
py::arg("config") = py::dict(),
R"(
@@ -155,6 +165,8 @@ void regclass_Core(py::module m) {
This can be more efficient than using read_model + compile_model(model_in_memory_object) flow,
especially for cases when caching is enabled and cached model is available.
GIL is released while running this function.
:param model_path: A path to a model in IR / ONNX / PDPD format.
:type model_path: str
:param properties: Optional dict of pairs: (property name, property value) relevant only for this load operation.
@@ -178,25 +190,26 @@ void regclass_Core(py::module m) {
cls.def(
"read_model",
[](ov::Core& self, py::bytes model, py::bytes weights) {
std::string ir(model);
// works on view in order to omit copying bytes into string
py::buffer_info info(py::buffer(weights).request());
size_t bin_size = static_cast<size_t>(info.size);
ov::Tensor tensor(ov::element::Type_t::u8, {bin_size});
// if weights are not empty
if (bin_size) {
const uint8_t* bin = reinterpret_cast<const uint8_t*>(info.ptr);
ov::Tensor tensor(ov::element::Type_t::u8, {bin_size});
std::memcpy(tensor.data(), bin, bin_size);
return self.read_model(model, tensor);
}
// create empty tensor of type u8
ov::Tensor tensor(ov::element::Type_t::u8, {});
return self.read_model(model, tensor);
py::gil_scoped_release release;
return self.read_model(ir, tensor);
},
py::arg("model"),
py::arg("weights") = py::bytes(),
R"(
Reads models from IR / ONNX / PDPD formats.
GIL is released while running this function.
:param model: Bytes with model in IR / ONNX / PDPD format.
:type model: bytes
:param weights: Bytes with tensor's data.
@@ -208,11 +221,14 @@ void regclass_Core(py::module m) {
cls.def(
"read_model",
(std::shared_ptr<ov::Model>(ov::Core::*)(const std::string&, const std::string&) const) & ov::Core::read_model,
py::call_guard<py::gil_scoped_release>(),
py::arg("model"),
py::arg("weights") = "",
R"(
Reads models from IR / ONNX / PDPD formats.
GIL is released while running this function.
:param model: A path to a model in IR / ONNX / PDPD format.
:type model: str
:param weights: A path to a data file For IR format (*.bin): if path is empty,
@@ -228,11 +244,14 @@ void regclass_Core(py::module m) {
cls.def(
"read_model",
(std::shared_ptr<ov::Model>(ov::Core::*)(const std::string&, const ov::Tensor&) const) & ov::Core::read_model,
py::call_guard<py::gil_scoped_release>(),
py::arg("model"),
py::arg("weights"),
R"(
Reads models from IR / ONNX / PDPD formats.
GIL is released while running this function.
:param model: A string with model in IR / ONNX / PDPD format.
:type model: str
:param weights: Tensor with weights. Reading ONNX / PDPD models doesn't support
@@ -244,14 +263,19 @@ void regclass_Core(py::module m) {
cls.def(
"read_model",
[](ov::Core& self, py::object model, py::object weights) {
return self.read_model(py::str(model), py::str(weights));
[](ov::Core& self, py::object model_path, py::object weights_path) {
std::string model_path_cpp{py::str(model_path)};
std::string weights_path_cpp{py::str(weights_path)};
py::gil_scoped_release release;
return self.read_model(model_path_cpp, weights_path_cpp);
},
py::arg("model"),
py::arg("weights") = "",
R"(
Reads models from IR / ONNX / PDPD formats.
GIL is released while running this function.
:param model: A string with model in IR / ONNX / PDPD format.
:type model: str
:param weights: A path to a data file For IR format (*.bin): if path is empty,
@@ -273,12 +297,15 @@ void regclass_Core(py::module m) {
_stream << model_stream;
return self.import_model(_stream, device_name, {properties.begin(), properties.end()});
},
py::call_guard<py::gil_scoped_release>(),
py::arg("model_stream"),
py::arg("device_name"),
py::arg("properties") = py::none(),
R"(
Imports a compiled model from a previously exported one.
GIL is released while running this function.
:param model_stream: Input stream, containing a model previously exported, using export_model method.
:type model_stream: bytes
:param device_name: Name of device to which compiled model is imported.
@@ -319,6 +346,7 @@ void regclass_Core(py::module m) {
_stream << model_stream
.attr("read")() // alternative: model_stream.attr("get_value")()
.cast<std::string>();
py::gil_scoped_release release;
return self.import_model(_stream, device_name, {properties.begin(), properties.end()});
},
py::arg("model_stream"),
@@ -330,6 +358,8 @@ void regclass_Core(py::module m) {
Advanced version of `import_model`. It utilizes, streams from standard
Python library `io`.
GIL is released while running this function.
:param model_stream: Input stream, containing a model previously exported, using export_model method.
:type model_stream: io.BytesIO
@@ -419,12 +449,15 @@ void regclass_Core(py::module m) {
const std::map<std::string, std::string>& properties) {
return self.query_model(model, device_name, {properties.begin(), properties.end()});
},
py::call_guard<py::gil_scoped_release>(),
py::arg("model"),
py::arg("device_name"),
py::arg("properties") = py::dict(),
R"(
Query device if it supports specified model with specified properties.
GIL is released while running this function.
:param model: Model object to query.
:type model: openvino.runtime.Model
:param device_name: A name of a device to query.
@@ -468,9 +501,12 @@ void regclass_Core(py::module m) {
cls.def_property_readonly("available_devices",
&ov::Core::get_available_devices,
py::call_guard<py::gil_scoped_release>(),
R"(
Returns devices available for inference Core objects goes over all registered plugins.
GIL is released while running this function.
:returns: A list of devices. The devices are returned as: CPU, GPU.0, GPU.1, MYRIAD...
If there more than one device of specific type, they are enumerated with .# suffix.
Such enumerated device can later be used as a device name in all Core methods like:
@@ -164,9 +164,12 @@ void regclass_InferRequest(py::module m) {
// Update inputs if there are any
Common::set_request_tensors(self._request, inputs);
// Call Infer function
self._start_time = Time::now();
self._request.infer();
self._end_time = Time::now();
{
py::gil_scoped_release release;
self._start_time = Time::now();
self._request.infer();
self._end_time = Time::now();
}
return Common::outputs_to_dict(self._outputs, self._request);
},
py::arg("inputs"),
@@ -175,6 +178,8 @@ void regclass_InferRequest(py::module m) {
Blocks all methods of InferRequest while request is running.
Calling any method will lead to throwing exceptions.
GIL is released while running the inference.
:param inputs: Data to set on input tensors.
:type inputs: Dict[Union[int, str, openvino.runtime.ConstOutput], openvino.runtime.Tensor]
:return: Dictionary of results from output tensors with ports as keys.
@@ -203,8 +208,7 @@ void regclass_InferRequest(py::module m) {
Starts inference of specified input(s) in asynchronous mode.
Returns immediately. Inference starts also immediately.
This function releases the GIL, so another Python thread can
work while this function runs in the background.
GIL is released while running the inference.
Calling any method on this InferRequest while the request is
running will lead to throwing exceptions.
@@ -234,7 +238,7 @@ void regclass_InferRequest(py::module m) {
Waits for the result to become available.
Blocks until the result becomes available.
Function releases GIL, other threads can work while this function waits.
GIL is released while running this function.
)");
cls.def(
@@ -249,7 +253,7 @@ void regclass_InferRequest(py::module m) {
Blocks until specified timeout has elapsed or
the result becomes available, whichever comes first.
Function releases GIL, other threads can work while this function waits.
GIL is released while running this function.
:param timeout: Maximum duration in milliseconds (ms) of blocking call.
:type timeout: int
@@ -512,11 +516,14 @@ void regclass_InferRequest(py::module m) {
[](InferRequestWrapper& self) {
return self._request.get_profiling_info();
},
py::call_guard<py::gil_scoped_release>(),
R"(
Queries performance is measured per layer to get feedback on what
is the most time-consuming operation, not all plugins provide
meaningful data.
GIL is released while running this function.
:return: List of profiling information for operations in model.
:rtype: List[openvino.runtime.ProfilingInfo]
)");
@@ -526,9 +533,12 @@ void regclass_InferRequest(py::module m) {
[](InferRequestWrapper& self) {
return self._request.query_state();
},
py::call_guard<py::gil_scoped_release>(),
R"(
Gets state control interface for given infer request.
GIL is released while running this function.
:return: List of VariableState objects.
:rtype: List[openvino.runtime.VariableState]
)");
@@ -615,9 +625,12 @@ void regclass_InferRequest(py::module m) {
[](InferRequestWrapper& self) {
return self._request.get_profiling_info();
},
py::call_guard<py::gil_scoped_release>(),
R"(
Performance is measured per layer to get feedback on the most time-consuming operation.
Not all plugins provide meaningful data!
GIL is released while running this function.
:return: Inference time.
:rtype: List[openvino.runtime.ProfilingInfo]
+268 -269
View File
@@ -7,6 +7,7 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "openvino/core/graph_util.hpp"
#include "openvino/core/model.hpp" // ov::Model
#include "openvino/core/partial_shape.hpp"
#include "openvino/op/parameter.hpp" // ov::op::v0::Parameter
@@ -19,8 +20,6 @@
namespace py = pybind11;
static const char* CAPSULE_NAME = "openvino_function";
using PyRTMap = ov::RTMap;
PYBIND11_MAKE_OPAQUE(PyRTMap);
@@ -46,22 +45,22 @@ ov::SinkVector cast_to_sink_vector(const std::vector<std::shared_ptr<ov::Node>>&
}
void regclass_graph_Model(py::module m) {
py::class_<ov::Model, std::shared_ptr<ov::Model>> function(m, "Model", py::module_local());
function.doc() = "openvino.runtime.Model wraps ov::Model";
py::class_<ov::Model, std::shared_ptr<ov::Model>> model(m, "Model", py::module_local());
model.doc() = "openvino.runtime.Model wraps ov::Model";
function.def(py::init([](const ov::ResultVector& res,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& params,
const std::string& name) {
set_tensor_names(params);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(res, sinks, params, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("name"),
R"(
model.def(py::init([](const ov::ResultVector& res,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& params,
const std::string& name) {
set_tensor_names(params);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(res, sinks, params, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("name"),
R"(
Create user-defined Model which is a representation of a model.
:param results: List of results.
@@ -70,51 +69,51 @@ void regclass_graph_Model(py::module m) {
:type sinks: List[openvino.runtime.Node]
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(py::init([](const std::vector<std::shared_ptr<ov::Node>>& results,
const ov::ParameterVector& parameters,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(results, parameters, name);
}),
py::arg("results"),
py::arg("parameters"),
py::arg("name") = "",
R"(
model.def(py::init([](const std::vector<std::shared_ptr<ov::Node>>& results,
const ov::ParameterVector& parameters,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(results, parameters, name);
}),
py::arg("results"),
py::arg("parameters"),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model.
:param results: List of Nodes to be used as results.
:type results: List[openvino.runtime.Node]
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(py::init([](const std::shared_ptr<ov::Node>& result,
const ov::ParameterVector& parameters,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(result, parameters, name);
}),
py::arg("result"),
py::arg("parameters"),
py::arg("name") = "",
R"(
model.def(py::init([](const std::shared_ptr<ov::Node>& result,
const ov::ParameterVector& parameters,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(result, parameters, name);
}),
py::arg("result"),
py::arg("parameters"),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model.
:param result: Node to be used as result.
:type result: openvino.runtime.Node
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(
model.def(
py::init([](const ov::OutputVector& results, const ov::ParameterVector& parameters, const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(results, parameters, name);
@@ -129,47 +128,47 @@ void regclass_graph_Model(py::module m) {
:type results: List[openvino.runtime.Output]
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(py::init([](const ov::OutputVector& results,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& parameters,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(results, sinks, parameters, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("name") = "",
R"(
model.def(py::init([](const ov::OutputVector& results,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& parameters,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(results, sinks, parameters, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model
:param results: List of outputs.
:type results: List[openvino.runtime.Output]
:param sinks: List of Nodes to be used as Sinks (e.g. Assign ops).
:type sinks: List[openvino.runtime.Node]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(py::init([](const ov::ResultVector& results,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
model.def(py::init([](const ov::ResultVector& results,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model
:param results: List of results.
@@ -180,25 +179,25 @@ void regclass_graph_Model(py::module m) {
:type parameters: List[op.Parameter]
:param variables: List of variables.
:type variables: List[op.util.Variable]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(py::init([](const ov::OutputVector& results,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
model.def(py::init([](const ov::OutputVector& results,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model
:param results: List of results.
@@ -207,22 +206,22 @@ void regclass_graph_Model(py::module m) {
:type sinks: List[openvino.runtime.Node]
:param variables: List of variables.
:type variables: List[op.util.Variable]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(py::init([](const ov::ResultVector& results,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(results, parameters, variables, name);
}),
py::arg("results"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
model.def(py::init([](const ov::ResultVector& results,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(results, parameters, variables, name);
}),
py::arg("results"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model
:param results: List of results.
@@ -231,83 +230,105 @@ void regclass_graph_Model(py::module m) {
:type parameters: List[op.Parameter]
:param variables: List of variables.
:type variables: List[op.util.Variable]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def(py::init([](const ov::OutputVector& results,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(results, parameters, variables, name);
}),
py::arg("results"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
model.def(py::init([](const ov::OutputVector& results,
const ov::ParameterVector& parameters,
const ov::op::util::VariableVector& variables,
const std::string& name) {
set_tensor_names(parameters);
return std::make_shared<ov::Model>(results, parameters, variables, name);
}),
py::arg("results"),
py::arg("parameters"),
py::arg("variables"),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model
:param results: List of results.
:type results: List[openvino.runtime.Output]
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param name: String to set as function's friendly name.
:param name: String to set as model's friendly name.
:type name: str
)");
function.def("validate_nodes_and_infer_types", &ov::Model::validate_nodes_and_infer_types);
model.def("validate_nodes_and_infer_types", &ov::Model::validate_nodes_and_infer_types);
function.def(
model.def(
"reshape",
[](ov::Model& self, const ov::PartialShape& partial_shape) {
self.reshape(partial_shape);
},
py::call_guard<py::gil_scoped_release>(),
py::arg("partial_shape"),
R"(
Reshape model input.
GIL is released while running this function.
:param partial_shape: New shape.
:type partial_shape: openvino.runtime.PartialShape
:return : void
)");
function.def(
model.def(
"reshape",
[](ov::Model& self, const py::list& partial_shape) {
self.reshape(Common::partial_shape_from_list(partial_shape));
ov::PartialShape new_shape(Common::partial_shape_from_list(partial_shape));
py::gil_scoped_release release;
self.reshape(new_shape);
},
py::arg("partial_shape"),
R"(
Reshape model input.
GIL is released while running this function.
:param partial_shape: New shape.
:type partial_shape: list
:return : void
)");
function.def(
model.def(
"reshape",
[](ov::Model& self, const py::tuple& partial_shape) {
self.reshape(Common::partial_shape_from_list(partial_shape.cast<py::list>()));
ov::PartialShape new_shape(Common::partial_shape_from_list(partial_shape.cast<py::list>()));
py::gil_scoped_release release;
self.reshape(new_shape);
},
py::arg("partial_shape"),
R"(
Reshape model input.
GIL is released while running this function.
:param partial_shape: New shape.
:type partial_shape: tuple
:return : void
)");
function.def(
model.def(
"reshape",
[](ov::Model& self, const std::string& partial_shape) {
self.reshape(Common::partial_shape_from_str(partial_shape));
},
py::call_guard<py::gil_scoped_release>(),
py::arg("partial_shape"),
R"(
Reshape model input.
GIL is released while running this function.
:param partial_shape: New shape.
:type partial_shape: str
:return : void
)");
function.def(
model.def(
"reshape",
[](ov::Model& self, const py::dict& partial_shapes) {
std::map<ov::Output<ov::Node>, ov::PartialShape> new_shapes;
@@ -338,6 +359,7 @@ void regclass_graph_Model(py::module m) {
}
new_shapes.insert(new_shape);
}
py::gil_scoped_release release;
self.reshape(new_shapes);
},
py::arg("partial_shapes"),
@@ -369,38 +391,42 @@ void regclass_graph_Model(py::module m) {
'1..10' - to define bounded dimension
'..10' or '1..' to define dimension with only lower or only upper limit
Reshape model input.
GIL is released while running this function.
:param partial_shapes: New shapes.
:type partial_shapes: Dict[keys, values]
)");
function.def("get_output_size",
&ov::Model::get_output_size,
R"(
Return the number of outputs for the function.
model.def("get_output_size",
&ov::Model::get_output_size,
R"(
Return the number of outputs for the model.
:return: Number of outputs.
:rtype: int
)");
function.def("get_ops",
&ov::Model::get_ops,
R"(
Return ops used in the function.
model.def("get_ops",
&ov::Model::get_ops,
R"(
Return ops used in the model.
:return: List of Nodes representing ops used in function.
:return: List of Nodes representing ops used in model.
:rtype: List[openvino.runtime.Node]
)");
function.def("get_ordered_ops",
&ov::Model::get_ordered_ops,
R"(
Return ops used in the function in topological order.
model.def("get_ordered_ops",
&ov::Model::get_ordered_ops,
R"(
Return ops used in the model in topological order.
:return: List of sorted Nodes representing ops used in function.
:return: List of sorted Nodes representing ops used in model.
:rtype: List[openvino.runtime.Node]
)");
function.def("get_output_op",
&ov::Model::get_output_op,
py::arg("index"),
R"(
model.def("get_output_op",
&ov::Model::get_output_op,
py::arg("index"),
R"(
Return the op that generates output i
:param index: output index
@@ -408,10 +434,10 @@ void regclass_graph_Model(py::module m) {
:return: Node object that generates output i
:rtype: openvino.runtime.Node
)");
function.def("get_output_element_type",
&ov::Model::get_output_element_type,
py::arg("index"),
R"(
model.def("get_output_element_type",
&ov::Model::get_output_element_type,
py::arg("index"),
R"(
Return the element type of output i
:param index: output index
@@ -419,10 +445,10 @@ void regclass_graph_Model(py::module m) {
:return: Type object of output i
:rtype: openvino.runtime.Type
)");
function.def("get_output_shape",
&ov::Model::get_output_shape,
py::arg("index"),
R"(
model.def("get_output_shape",
&ov::Model::get_output_shape,
py::arg("index"),
R"(
Return the shape of element i
:param index: element index
@@ -430,10 +456,10 @@ void regclass_graph_Model(py::module m) {
:return: Shape object of element i
:rtype: openvino.runtime.Shape
)");
function.def("get_output_partial_shape",
&ov::Model::get_output_partial_shape,
py::arg("index"),
R"(
model.def("get_output_partial_shape",
&ov::Model::get_output_partial_shape,
py::arg("index"),
R"(
Return the partial shape of element i
:param index: element index
@@ -441,34 +467,34 @@ void regclass_graph_Model(py::module m) {
:return: PartialShape object of element i
:rtype: openvino.runtime.PartialShape
)");
function.def("get_parameters",
&ov::Model::get_parameters,
R"(
Return the function parameters.
model.def("get_parameters",
&ov::Model::get_parameters,
R"(
Return the model parameters.
:return: ParameterVector containing function parameters.
:return: ParameterVector containing model parameters.
:rtype: ParameterVector
)");
function.def("get_results",
&ov::Model::get_results,
R"(
Return a list of function outputs.
model.def("get_results",
&ov::Model::get_results,
R"(
Return a list of model outputs.
:return: ResultVector containing function parameters.
:return: ResultVector containing model parameters.
:rtype: ResultVector
)");
function.def("get_result",
&ov::Model::get_result,
R"(
model.def("get_result",
&ov::Model::get_result,
R"(
Return single result.
:return: Node object representing result.
:rtype: openvino.runtime.Node
)");
function.def("get_result_index",
(int64_t(ov::Model::*)(const ov::Output<ov::Node>&) const) & ov::Model::get_result_index,
py::arg("value"),
R"(
model.def("get_result_index",
(int64_t(ov::Model::*)(const ov::Output<ov::Node>&) const) & ov::Model::get_result_index,
py::arg("value"),
R"(
Return index of result.
Return -1 if `value` not matched.
@@ -478,10 +504,10 @@ void regclass_graph_Model(py::module m) {
:return: Index for value referencing it.
:rtype: int
)");
function.def("get_result_index",
(int64_t(ov::Model::*)(const ov::Output<const ov::Node>&) const) & ov::Model::get_result_index,
py::arg("value"),
R"(
model.def("get_result_index",
(int64_t(ov::Model::*)(const ov::Output<const ov::Node>&) const) & ov::Model::get_result_index,
py::arg("value"),
R"(
Return index of result.
Return -1 if `value` not matched.
@@ -492,81 +518,77 @@ void regclass_graph_Model(py::module m) {
:rtype: int
)");
function.def("get_name",
&ov::Model::get_name,
R"(
Get the unique name of the function.
model.def("get_name",
&ov::Model::get_name,
R"(
Get the unique name of the model.
:return: String with a name of the function.
:return: String with a name of the model.
:rtype: str
)");
function.def("get_friendly_name",
&ov::Model::get_friendly_name,
R"(
Gets the friendly name for a function. If no
model.def("get_friendly_name",
&ov::Model::get_friendly_name,
R"(
Gets the friendly name for a model. If no
friendly name has been set via set_friendly_name
then the function's unique name is returned.
then the model's unique name is returned.
:return: String with a friendly name of the function.
:return: String with a friendly name of the model.
:rtype: str
)");
function.def("set_friendly_name",
&ov::Model::set_friendly_name,
py::arg("name"),
R"(
Sets a friendly name for a function. This does
not overwrite the unique name of the function and
model.def("set_friendly_name",
&ov::Model::set_friendly_name,
py::arg("name"),
R"(
Sets a friendly name for a model. This does
not overwrite the unique name of the model and
is retrieved via get_friendly_name(). Used mainly
for debugging.
:param name: String to set as the friendly name.
:type name: str
)");
function.def("is_dynamic",
&ov::Model::is_dynamic,
R"(
Returns true if any of the op's defined in the function
model.def("is_dynamic",
&ov::Model::is_dynamic,
R"(
Returns true if any of the op's defined in the model
contains partial shape.
:rtype: bool
)");
function.def("input", (ov::Output<ov::Node>(ov::Model::*)()) & ov::Model::input);
model.def("input", (ov::Output<ov::Node>(ov::Model::*)()) & ov::Model::input);
function.def("input", (ov::Output<ov::Node>(ov::Model::*)(size_t)) & ov::Model::input, py::arg("index"));
model.def("input", (ov::Output<ov::Node>(ov::Model::*)(size_t)) & ov::Model::input, py::arg("index"));
function.def("input",
(ov::Output<ov::Node>(ov::Model::*)(const std::string&)) & ov::Model::input,
py::arg("tensor_name"));
model.def("input",
(ov::Output<ov::Node>(ov::Model::*)(const std::string&)) & ov::Model::input,
py::arg("tensor_name"));
function.def("input", (ov::Output<const ov::Node>(ov::Model::*)() const) & ov::Model::input);
model.def("input", (ov::Output<const ov::Node>(ov::Model::*)() const) & ov::Model::input);
function.def("input",
(ov::Output<const ov::Node>(ov::Model::*)(size_t) const) & ov::Model::input,
py::arg("index"));
model.def("input", (ov::Output<const ov::Node>(ov::Model::*)(size_t) const) & ov::Model::input, py::arg("index"));
function.def("input",
(ov::Output<const ov::Node>(ov::Model::*)(const std::string&) const) & ov::Model::input,
py::arg("tensor_name"));
model.def("input",
(ov::Output<const ov::Node>(ov::Model::*)(const std::string&) const) & ov::Model::input,
py::arg("tensor_name"));
function.def("output", (ov::Output<ov::Node>(ov::Model::*)()) & ov::Model::output);
model.def("output", (ov::Output<ov::Node>(ov::Model::*)()) & ov::Model::output);
function.def("output", (ov::Output<ov::Node>(ov::Model::*)(size_t)) & ov::Model::output, py::arg("index"));
model.def("output", (ov::Output<ov::Node>(ov::Model::*)(size_t)) & ov::Model::output, py::arg("index"));
function.def("output",
(ov::Output<ov::Node>(ov::Model::*)(const std::string&)) & ov::Model::output,
py::arg("tensor_name"));
model.def("output",
(ov::Output<ov::Node>(ov::Model::*)(const std::string&)) & ov::Model::output,
py::arg("tensor_name"));
function.def("output", (ov::Output<const ov::Node>(ov::Model::*)() const) & ov::Model::output);
model.def("output", (ov::Output<const ov::Node>(ov::Model::*)() const) & ov::Model::output);
function.def("output",
(ov::Output<const ov::Node>(ov::Model::*)(size_t) const) & ov::Model::output,
py::arg("index"));
model.def("output", (ov::Output<const ov::Node>(ov::Model::*)(size_t) const) & ov::Model::output, py::arg("index"));
function.def("output",
(ov::Output<const ov::Node>(ov::Model::*)(const std::string&) const) & ov::Model::output,
py::arg("tensor_name"));
model.def("output",
(ov::Output<const ov::Node>(ov::Model::*)(const std::string&) const) & ov::Model::output,
py::arg("tensor_name"));
function.def(
model.def(
"add_outputs",
[](ov::Model& self, py::handle& outputs) {
int i = 0;
@@ -606,15 +628,15 @@ void regclass_graph_Model(py::module m) {
},
py::arg("outputs"));
function.def("replace_parameter",
&ov::Model::replace_parameter,
py::arg("parameter_index"),
py::arg("parameter"),
R"(
Replace the `parameter_index` parameter of the function with `parameter`
model.def("replace_parameter",
&ov::Model::replace_parameter,
py::arg("parameter_index"),
py::arg("parameter"),
R"(
Replace the `parameter_index` parameter of the model with `parameter`
All users of the `parameter_index` parameter are redirected to `parameter` , and the
`parameter_index` entry in the function parameter list is replaced with `parameter`
`parameter_index` entry in the model parameter list is replaced with `parameter`
:param parameter_index: The index of the parameter to replace.
:type parameter_index: int
@@ -622,7 +644,7 @@ void regclass_graph_Model(py::module m) {
:type parameter: op.Parameter
)");
function.def(
model.def(
"get_parameter_index",
(int64_t(ov::Model::*)(const std::shared_ptr<ov::op::v0::Parameter>&) const) & ov::Model::get_parameter_index,
py::arg("parameter"),
@@ -637,7 +659,7 @@ void regclass_graph_Model(py::module m) {
:rtype: int
)");
function.def(
model.def(
"evaluate",
[](ov::Model& self,
ov::TensorVector& output_tensors,
@@ -649,20 +671,31 @@ void regclass_graph_Model(py::module m) {
py::arg("input_tensors"),
py::arg("evaluation_context") = PyRTMap(),
R"(
Evaluate the function on inputs, putting results in outputs
Evaluate the model on inputs, putting results in outputs
:param output_tensors: Tensors for the outputs to compute. One for each result
:type output_tensors: List[openvino.runtime.Tensor]
:param input_tensors: Tensors for the inputs. One for each inputs.
:type input_tensors: List[openvino.runtime.Tensor]
:param evaluation_context: Storage of additional settings and attributes that can be used
when evaluating the function. This additional information can be
when evaluating the model. This additional information can be
shared across nodes.
:type evaluation_context: openvino.runtime.RTMap
:rtype: bool
)");
function.def("__repr__", [](const ov::Model& self) {
model.def(
"clone",
[](ov::Model& self) {
return ov::clone_model(self);
},
R"(
Return a copy of self.
:return: A copy of self.
:rtype: openvino.runtime.Model
)");
model.def("__repr__", [](const ov::Model& self) {
std::string class_name = py::cast(self).get_type().attr("__name__").cast<std::string>();
auto inputs_str = Common::docs::container_to_string(self.inputs(), ",\n");
@@ -672,42 +705,8 @@ void regclass_graph_Model(py::module m) {
outputs_str + "\n]>";
});
function.def_static("from_capsule", [](py::object* capsule) {
// get the underlying PyObject* which is a PyCapsule pointer
auto* pybind_capsule_ptr = capsule->ptr();
// extract the pointer stored in the PyCapsule under the name CAPSULE_NAME
auto* capsule_ptr = PyCapsule_GetPointer(pybind_capsule_ptr, CAPSULE_NAME);
auto* ngraph_function = static_cast<std::shared_ptr<ov::Model>*>(capsule_ptr);
if (ngraph_function && *ngraph_function) {
return *ngraph_function;
} else {
throw std::runtime_error("The provided capsule does not contain an ov::Model");
}
});
function.def_static("to_capsule", [](std::shared_ptr<ov::Model>& ngraph_function) {
// create a shared pointer on the heap before putting it in the capsule
// this secures the lifetime of the object transferred by the capsule
auto* sp_copy = new std::shared_ptr<ov::Model>(ngraph_function);
// a destructor callback that will delete the heap allocated shared_ptr
// when the capsule is destructed
auto sp_deleter = [](PyObject* capsule) {
auto* capsule_ptr = PyCapsule_GetPointer(capsule, CAPSULE_NAME);
auto* function_sp = static_cast<std::shared_ptr<ov::Model>*>(capsule_ptr);
if (function_sp) {
delete function_sp;
}
};
// put the shared_ptr in a new capsule under the same name as in "from_capsule"
auto pybind_capsule = py::capsule(sp_copy, CAPSULE_NAME, sp_deleter);
return pybind_capsule;
});
function.def_property_readonly("inputs", (std::vector<ov::Output<ov::Node>>(ov::Model::*)()) & ov::Model::inputs);
function.def_property_readonly("outputs", (std::vector<ov::Output<ov::Node>>(ov::Model::*)()) & ov::Model::outputs);
function.def_property_readonly("name", &ov::Model::get_name);
function.def_property("friendly_name", &ov::Model::get_friendly_name, &ov::Model::set_friendly_name);
model.def_property_readonly("inputs", (std::vector<ov::Output<ov::Node>>(ov::Model::*)()) & ov::Model::inputs);
model.def_property_readonly("outputs", (std::vector<ov::Output<ov::Node>>(ov::Model::*)()) & ov::Model::outputs);
model.def_property_readonly("name", &ov::Model::get_name);
model.def_property("friendly_name", &ov::Model::get_friendly_name, &ov::Model::set_friendly_name);
}
@@ -18,8 +18,6 @@
namespace py = pybind11;
static const char* CAPSULE_NAME = "ngraph_partial_shape";
void regclass_graph_PartialShape(py::module m) {
py::class_<ov::PartialShape, std::shared_ptr<ov::PartialShape>> shape(m, "PartialShape");
shape.doc() = "openvino.runtime.PartialShape wraps ov::PartialShape";
@@ -193,18 +191,4 @@ void regclass_graph_PartialShape(py::module m) {
shape.def("__repr__", [](const ov::PartialShape& self) -> std::string {
return "<PartialShape: " + py::cast(self).attr("__str__")().cast<std::string>() + ">";
});
shape.def_static("from_capsule", [](py::object* capsule) {
// get the underlying PyObject* which is a PyCapsule pointer
auto* pybind_capsule_ptr = capsule->ptr();
// extract the pointer stored in the PyCapsule under the name CAPSULE_NAME
auto* capsule_ptr = PyCapsule_GetPointer(pybind_capsule_ptr, CAPSULE_NAME);
auto* ngraph_pShape = static_cast<std::shared_ptr<ov::PartialShape>*>(capsule_ptr);
if (ngraph_pShape && *ngraph_pShape) {
return *ngraph_pShape;
} else {
throw std::runtime_error("The provided capsule does not contain an ov::PartialShape");
}
});
}
@@ -480,7 +480,7 @@ void regclass_graph_PrePostProcessor(py::module m) {
},
py::arg("output_index"));
proc.def("build", &ov::preprocess::PrePostProcessor::build);
proc.def("build", &ov::preprocess::PrePostProcessor::build, py::call_guard<py::gil_scoped_release>());
proc.def("__str__", [](const ov::preprocess::PrePostProcessor& self) -> std::string {
std::stringstream ss;
@@ -36,6 +36,20 @@ void regmodule_graph_util(py::module m) {
from the resulting bound, otherwise Null.
:rtype: openvino.runtime.op.Constant or openvino.runtime.Node
)");
mod.def(
"clone_model",
[](ov::Model& model) {
return ov::clone_model(model);
},
py::arg("model"),
R"(
Creates a copy of a model object.
:param model: Model to copy.
:type model: openvino.runtime.Model
:return: A copy of Model.
:rtype: openvino.runtime.Model
)");
mod.def("replace_output_update_name", &ov::replace_output_update_name, py::arg("output"), py::arg("target_output"));
+58
View File
@@ -8,6 +8,8 @@ import numpy as np
import tests
from pathlib import Path
from sys import platform
from openvino.runtime import Core
def image_path():
@@ -29,6 +31,62 @@ def read_image():
return image
def get_model_with_template_extension():
core = Core()
ir = bytes(b"""<net name="Activation" version="10">
<layers>
<layer name="in1" type="Parameter" id="0" version="opset1">
<data shape="1,3,22,22" element_type="f32"/>
<output>
<port id="0" precision="FP32" names="in_data">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</output>
</layer>
<layer name="activation" id="1" type="Identity" version="extension">
<input>
<port id="1" precision="FP32">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</input>
<output>
<port id="2" precision="FP32" names="out_data">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</output>
</layer>
<layer name="output" type="Result" id="2" version="opset1">
<input>
<port id="0" precision="FP32">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</input>
</layer>
</layers>
<edges>
<edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
<edge from-layer="1" from-port="2" to-layer="2" to-port="0"/>
</edges>
</net>""")
if platform == "win32":
core.add_extension(library_path="openvino_template_extension.dll")
else:
core.add_extension(library_path="libopenvino_template_extension.so")
return core, core.read_model(ir)
def model_path(is_myriad=False):
path_to_repo = os.environ["MODELS_PATH"]
if not is_myriad:
@@ -5,7 +5,7 @@ import os
import pytest
import numpy as np
from ..conftest import model_path, read_image
from ..conftest import model_path, read_image, get_model_with_template_extension
from openvino.runtime import Model, ConstOutput, Shape
from openvino.runtime import Core, Tensor
@@ -340,3 +340,12 @@ def test_direct_infer(device):
assert np.argmax(res[comp_model.outputs[0]]) == 2
ref = comp_model.infer_new_request({"data": tensor})
assert np.array_equal(ref[comp_model.outputs[0]], res[comp_model.outputs[0]])
def test_compiled_model_after_core_destroyed(device):
core, model = get_model_with_template_extension()
compiled = core.compile_model(model, device)
del core
del model
# check compiled and infer request can work properly after core object is destroyed
compiled([np.random.normal(size=list(input.shape)) for input in compiled.inputs])
@@ -11,7 +11,8 @@ import openvino.runtime.opset8 as ov
from openvino.runtime import Model, Core, CompiledModel, Tensor, PartialShape, Extension,\
tensor_from_file, compile_model
from ..conftest import model_path, model_onnx_path, plugins_path, read_image
from ..conftest import model_path, model_onnx_path, plugins_path, read_image, \
get_model_with_template_extension
test_net_xml, test_net_bin = model_path()
@@ -254,60 +255,7 @@ def test_unregister_plugin(device):
@pytest.mark.template_extension
def test_add_extension_template_extension(device):
ir = bytes(b"""<net name="Activation" version="10">
<layers>
<layer name="in1" type="Parameter" id="0" version="opset1">
<data shape="1,3,22,22" element_type="f32"/>
<output>
<port id="0" precision="FP32" names="in_data">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</output>
</layer>
<layer name="activation" id="1" type="Identity" version="extension">
<input>
<port id="1" precision="FP32">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</input>
<output>
<port id="2" precision="FP32" names="out_data">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</output>
</layer>
<layer name="output" type="Result" id="2" version="opset1">
<input>
<port id="0" precision="FP32">
<dim>1</dim>
<dim>3</dim>
<dim>22</dim>
<dim>22</dim>
</port>
</input>
</layer>
</layers>
<edges>
<edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
<edge from-layer="1" from-port="2" to-layer="2" to-port="0"/>
</edges>
</net>""")
core = Core()
if platform == "win32":
core.add_extension(library_path="openvino_template_extension.dll")
else:
core.add_extension(library_path="libopenvino_template_extension.so")
model = core.read_model(model=ir)
core, model = get_model_with_template_extension()
assert isinstance(model, Model)
before_reshape = PartialShape([1, 3, 22, 22])
@@ -315,6 +263,8 @@ def test_add_extension_template_extension(device):
new_shapes = {"in_data": after_reshape}
assert model.input().partial_shape == before_reshape
model.reshape(new_shapes)
# compile to check objects can be destroyed
# in order core -> model -> compiled
compiled = core.compile_model(model, device)
assert compiled.input().partial_shape == after_reshape
@@ -0,0 +1,206 @@
# Copyright (C) 2018-2022 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import time
import pytest
import os
import io
from threading import Thread
import numpy as np
from openvino.runtime import Core, Model, AsyncInferQueue, PartialShape, Layout, opset8 as ops, serialize
from openvino.preprocess import PrePostProcessor
# check if func releases the GIL and doens't increment reference counters of args while GIL is released
def check_gil_released_safe(func, args=[]): # noqa: B006
global gil_released
gil_released = False
def detect_gil():
global gil_released
# while sleeping main thread acquires GIL and runs func, which will release GIL
time.sleep(0.000001)
# increment reference counting of args while running func
args_ = args # noqa: F841 'assigned to but never used'
gil_released = True
thread = Thread(target=detect_gil)
thread.start()
func(*args)
if not gil_released:
pytest.xfail(reason="Depend on condition race")
thread.join()
device = os.environ.get("TEST_DEVICE") if os.environ.get("TEST_DEVICE") else "CPU"
core = Core()
core.set_property({"PERF_COUNT": "YES"})
param = ops.parameter([224, 224])
model = Model(ops.relu(param), [param])
compiled = core.compile_model(model, device)
infer_queue = AsyncInferQueue(compiled, 1)
user_stream = io.BytesIO()
# AsyncInferQueue
def test_gil_released_async_infer_queue_start_async():
infer_queue.start_async()
check_gil_released_safe(infer_queue.start_async)
def test_gil_released_async_infer_queue_is_ready():
infer_queue.start_async()
check_gil_released_safe(infer_queue.is_ready)
def test_gil_released_async_infer_queue_wait_all():
infer_queue.start_async()
check_gil_released_safe(infer_queue.wait_all)
def test_gil_released_async_infer_queue_get_idle_request_id():
infer_queue.start_async()
check_gil_released_safe(infer_queue.get_idle_request_id)
# CompiledModel
def test_gil_released_create_infer_request():
check_gil_released_safe(compiled.create_infer_request)
def test_gil_released_infer_new_request():
check_gil_released_safe(compiled)
def test_gil_released_export():
check_gil_released_safe(compiled.export_model)
def test_gil_released_export_advanced():
check_gil_released_safe(compiled.export_model, [user_stream])
def test_gil_released_get_runtime_model():
check_gil_released_safe(compiled.get_runtime_model)
# Core
def test_compile_model(device):
check_gil_released_safe(core.compile_model, [model, device])
def test_read_model_from_bytes():
ir = bytes(b"""<net name="relu_model" version="11">
<layers>
<layer id="0" name="x" type="Parameter" version="opset1">
<data element_type="f32" shape="10"/>
<output>
<port id="0" precision="FP32">
<dim>10</dim>
</port>
</output>
</layer>
<layer id="1" name="relu" type="ReLU" version="opset1">
<input>
<port id="0">
<dim>10</dim>
</port>
</input>
<output>
<port id="1" precision="FP32">
<dim>10</dim>
</port>
</output>
</layer>
<layer id="2" name="result" type="Result" version="opset1">
<input>
<port id="0">
<dim>10</dim>
</port>
</input>
</layer>
</layers>
<edges>
<edge from-layer="0" from-port="0" to-layer="1" to-port="0"/>
<edge from-layer="1" from-port="1" to-layer="2" to-port="0"/>
</edges>
</net>""")
check_gil_released_safe(core.read_model, [ir])
def test_read_model_from_path():
from pathlib import Path
model_path = "relu.xml"
bin_path = "relu.bin"
serialize(model, model_path, bin_path)
check_gil_released_safe(core.read_model, [Path(model_path)])
os.remove(model_path)
os.remove(bin_path)
def test_import_model(device):
check_gil_released_safe(core.import_model, [user_stream, device])
def test_query_model(device):
check_gil_released_safe(core.query_model, [model, device])
def test_get_available_devices(device):
check_gil_released_safe(getattr, [core, "available_devices"])
# InferRequest
request = compiled.create_infer_request()
def test_infer():
data = [np.random.normal(size=list(compiled.input().shape))]
check_gil_released_safe(request.infer, [data])
def test_start_async():
data = [np.random.normal(size=list(compiled.input().shape))]
check_gil_released_safe(request.start_async, [data])
request.wait()
def test_wait():
data = [np.random.normal(size=list(compiled.input().shape))]
request.start_async(data)
check_gil_released_safe(request.wait)
def test_wait_for():
data = [np.random.normal(size=list(compiled.input().shape))]
request.start_async(data)
check_gil_released_safe(request.wait_for, [1])
request.wait()
def test_get_profiling_info():
check_gil_released_safe(request.get_profiling_info)
def test_query_state():
check_gil_released_safe(request.query_state)
# Preprocessing
def test_pre_post_process_build():
p = PrePostProcessor(model)
p.input().model().set_layout(Layout("NC"))
check_gil_released_safe(p.build)
def test_model_reshape():
check_gil_released_safe(model.reshape, [PartialShape([128, 128])])
check_gil_released_safe(model.reshape, [[164, 164]])
check_gil_released_safe(model.reshape, [(178, 178)])
check_gil_released_safe(model.reshape, ["194, 194"])
check_gil_released_safe(model.reshape, [{0: [224, 224]}])
@@ -327,6 +327,30 @@ def test_set_argument():
assert np.allclose(data1 + data2, output)
def test_clone_model():
# Create an original model
shape = [2, 2]
parameter_a = ops.parameter(shape, dtype=np.float32, name="A")
parameter_b = ops.parameter(shape, dtype=np.float32, name="B")
model_original = ov.Model(parameter_a + parameter_b, [parameter_a, parameter_b])
# Make copies of it
model_copy1 = ov.utils.clone_model(model_original)
model_copy2 = model_original.clone()
# Make changes to the copied models' inputs
model_copy1.reshape({"A": [3, 3], "B": [3, 3]})
model_copy2.reshape({"A": [3, 3], "B": [3, 3]})
original_model_shapes = [single_input.get_shape() for single_input in model_original.inputs]
model_copy1_shapes = [single_input.get_shape() for single_input in model_copy1.inputs]
model_copy2_shapes = [single_input.get_shape() for single_input in model_copy2.inputs]
assert original_model_shapes != model_copy1_shapes
assert original_model_shapes != model_copy2_shapes
assert model_copy1_shapes == model_copy2_shapes
def test_result():
node = np.array([[11, 10], [1, 8], [3, 4]], dtype=np.float32)
result = run_op_node([node], ops.result)
-75
View File
@@ -1,75 +0,0 @@
[tox]
envlist = py3
[testenv]
skipdist=True
skip_install=True
deps =
-rrequirements.txt
-rrequirements_test.txt
setenv =
NGRAPH_BACKEND = {env:NGRAPH_BACKEND:"CPU"}
PYTHONPATH = {env:PYTHONPATH}
OpenVINO_DIR = {env:OpenVINO_DIR}
passenv =
http_proxy
https_proxy
commands=
{envbindir}/python setup.py bdist_wheel
{envbindir}/pip install --no-index --pre --find-links=dist/ openvino
flake8 {posargs:src/ setup.py} --exclude=src/compatibility/openvino
flake8 --ignore=D100,D101,D102,D103,D104,D105,D107,D212,W503 tests/ tests_compatibility/ --exclude=tests_compatibility/test_inference_engine # ignore lack of docs in tests
mypy --config-file=tox.ini {posargs:src/} --exclude=src/compatibility/openvino
pytest --backend={env:NGRAPH_BACKEND} tests -v -k 'not _cuda' --ignore=tests/test_onnx/test_zoo_models.py --ignore=tests/test_utils --ignore=tests/test_inference_engine
pytest --backend={env:NGRAPH_BACKEND} tests_compatibility/test_ngraph -v -k 'not _cuda' --ignore=tests_compatibility/test_onnx/test_zoo_models.py
[testenv:zoo_models]
commands=
{envbindir}/python setup.py bdist_wheel
{envbindir}/pip install --no-index --pre --find-links=dist/ openvino
pytest --backend={env:NGRAPH_BACKEND} tests/test_onnx/test_zoo_models.py -v -n 4 --forked -k 'not _cuda' --model_zoo_xfail
[testenv:devenv]
envdir = devenv
usedevelop = True
deps = -rrequirements.txt
[flake8]
inline-quotes = "
max-line-length=110
max-complexity=7
# ignore:
# D100 - Missing docstring in public module
# D104 - Missing docstring in public package
# D105 - Missing docstring in magic method
# D107 - Missing docstring in __init__
# D412 - No blank lines allowed between a section header and its content
# F401 - module imported but unused
# W503 - line break before binary operator (prefer line breaks before op, not after)
ignore=D100,D104,D105,D107,D410,D411,D412,F401,W503
[mypy]
ignore_missing_imports=True
follow_imports=normal
disallow_untyped_defs = True
disallow_untyped_calls = True
check_untyped_defs = True
show_error_context = True
show_column_numbers = True
show_none_errors = True
# put custom per-file options here in sections that map their names into filenames, e.g. gta_workflow/filename.py is
# [mypy-ngraph/filename]
[mypy-test.*]
disallow_untyped_defs = False
[isort]
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
line_length=100
default_section=FIRSTPARTY
sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
known_third_party=openvino
+203 -211
View File
@@ -22,118 +22,118 @@ from setuptools.command.build_ext import build_ext
from setuptools.command.build_clib import build_clib
from setuptools.command.install import install
WHEEL_LIBS_INSTALL_DIR = os.path.join('openvino', 'libs')
WHEEL_LIBS_PACKAGE = 'openvino.libs'
PYTHON_VERSION = f'python{sys.version_info.major}.{sys.version_info.minor}'
WHEEL_LIBS_INSTALL_DIR = os.path.join("openvino", "libs")
WHEEL_LIBS_PACKAGE = "openvino.libs"
PYTHON_VERSION = f"python{sys.version_info.major}.{sys.version_info.minor}"
LIBS_DIR = 'bin' if platform.system() == 'Windows' else 'lib'
CONFIG = 'Release' if platform.system() in {'Windows' , 'Darwin'} else ''
LIBS_DIR = "bin" if platform.system() == "Windows" else "lib"
CONFIG = "Release" if platform.system() in {"Windows", "Darwin"} else ""
machine = platform.machine()
if machine == 'x86_64' or machine == 'AMD64':
ARCH = 'intel64'
elif machine == 'X86':
ARCH = 'ia32'
elif machine == 'arm':
ARCH = 'arm'
elif machine == 'aarch64':
ARCH = 'arm64'
if machine == "x86_64" or machine == "AMD64":
ARCH = "intel64"
elif machine == "X86":
ARCH = "ia32"
elif machine == "arm":
ARCH = "arm"
elif machine == "aarch64":
ARCH = "arm64"
# The following variables can be defined in environment or .env file
SCRIPT_DIR = Path(__file__).resolve().parents[0]
CMAKE_BUILD_DIR = os.getenv('CMAKE_BUILD_DIR', '.')
OV_RUNTIME_LIBS_DIR = os.getenv('OV_RUNTIME_LIBS_DIR', f'runtime/{LIBS_DIR}/{ARCH}/{CONFIG}')
TBB_LIBS_DIR = os.getenv('TBB_LIBS_DIR', f'runtime/3rdparty/tbb/{LIBS_DIR}')
PY_PACKAGES_DIR = os.getenv('PY_PACKAGES_DIR', f'python/{PYTHON_VERSION}')
LIBS_RPATH = '$ORIGIN' if sys.platform == 'linux' else '@loader_path'
CMAKE_BUILD_DIR = os.getenv("CMAKE_BUILD_DIR", ".")
OV_RUNTIME_LIBS_DIR = os.getenv("OV_RUNTIME_LIBS_DIR", f"runtime/{LIBS_DIR}/{ARCH}/{CONFIG}")
TBB_LIBS_DIR = os.getenv("TBB_LIBS_DIR", f"runtime/3rdparty/tbb/{LIBS_DIR}")
PY_PACKAGES_DIR = os.getenv("PY_PACKAGES_DIR", f"python/{PYTHON_VERSION}")
LIBS_RPATH = "$ORIGIN" if sys.platform == "linux" else "@loader_path"
LIB_INSTALL_CFG = {
'ie_libs': {
'name': 'core',
'prefix': 'libs.core',
'install_dir': OV_RUNTIME_LIBS_DIR,
'rpath': LIBS_RPATH,
"ie_libs": {
"name": "core",
"prefix": "libs.core",
"install_dir": OV_RUNTIME_LIBS_DIR,
"rpath": LIBS_RPATH,
},
'hetero_plugin': {
'name': 'hetero',
'prefix': 'libs.core',
'install_dir': OV_RUNTIME_LIBS_DIR,
'rpath': LIBS_RPATH,
"hetero_plugin": {
"name": "hetero",
"prefix": "libs.core",
"install_dir": OV_RUNTIME_LIBS_DIR,
"rpath": LIBS_RPATH,
},
'gpu_plugin': {
'name': 'gpu',
'prefix': 'libs.core',
'install_dir': OV_RUNTIME_LIBS_DIR,
'rpath': LIBS_RPATH,
"gpu_plugin": {
"name": "gpu",
"prefix": "libs.core",
"install_dir": OV_RUNTIME_LIBS_DIR,
"rpath": LIBS_RPATH,
},
'cpu_plugin': {
'name': 'cpu',
'prefix': 'libs.core',
'install_dir': OV_RUNTIME_LIBS_DIR,
'rpath': LIBS_RPATH,
"cpu_plugin": {
"name": "cpu",
"prefix": "libs.core",
"install_dir": OV_RUNTIME_LIBS_DIR,
"rpath": LIBS_RPATH,
},
'multi_plugin': {
'name': 'multi',
'prefix': 'libs.core',
'install_dir': OV_RUNTIME_LIBS_DIR,
'rpath': LIBS_RPATH,
"multi_plugin": {
"name": "multi",
"prefix": "libs.core",
"install_dir": OV_RUNTIME_LIBS_DIR,
"rpath": LIBS_RPATH,
},
'batch_plugin': {
'name': 'batch',
'prefix': 'libs.core',
'install_dir': OV_RUNTIME_LIBS_DIR,
"batch_plugin": {
"name": "batch",
"prefix": "libs.core",
"install_dir": OV_RUNTIME_LIBS_DIR,
},
'tbb_libs': {
'name': 'tbb',
'prefix': 'libs.tbb',
'install_dir': TBB_LIBS_DIR,
'rpath': LIBS_RPATH,
"tbb_libs": {
"name": "tbb",
"prefix": "libs.tbb",
"install_dir": TBB_LIBS_DIR,
"rpath": LIBS_RPATH,
},
}
PY_INSTALL_CFG = {
'ie_py': {
'name': PYTHON_VERSION,
'prefix': 'site-packages',
'install_dir': PY_PACKAGES_DIR,
"ie_py": {
"name": PYTHON_VERSION,
"prefix": "site-packages",
"install_dir": PY_PACKAGES_DIR,
},
'ngraph_py': {
'name': f'pyngraph_{PYTHON_VERSION}',
'prefix': 'site-packages',
'install_dir': PY_PACKAGES_DIR,
"ngraph_py": {
"name": f"pyngraph_{PYTHON_VERSION}",
"prefix": "site-packages",
"install_dir": PY_PACKAGES_DIR,
},
'pyopenvino' : {
'name': f'pyopenvino_{PYTHON_VERSION}',
'prefix': 'site-packages',
'install_dir': PY_PACKAGES_DIR,
"pyopenvino": {
"name": f"pyopenvino_{PYTHON_VERSION}",
"prefix": "site-packages",
"install_dir": PY_PACKAGES_DIR,
},
}
class PrebuiltExtension(Extension):
"""Initialize Extension"""
"""Initialize Extension."""
def __init__(self, name, sources, *args, **kwargs):
if len(sources) != 1:
nln = '\n'
raise DistutilsSetupError(f'PrebuiltExtension can accept only one source, but got: {nln}{nln.join(sources)}')
nln = "\n"
raise DistutilsSetupError(f"PrebuiltExtension can accept only one source, but got: {nln}{nln.join(sources)}")
super().__init__(name, sources, *args, **kwargs)
class CustomBuild(build):
"""Custom implementation of build_clib"""
"""Custom implementation of build_clib."""
cmake_build_types = ['Release', 'Debug', 'RelWithDebInfo', 'MinSizeRel']
cmake_build_types = ["Release", "Debug", "RelWithDebInfo", "MinSizeRel"]
user_options = [
('config=', None, 'Build configuration [{types}].'.format(types='|'.join(cmake_build_types))),
('jobs=', None, 'Specifies the number of jobs to use with make.'),
('cmake-args=', None, 'Additional options to be passed to CMake.'),
("config=", None, "Build configuration [{types}].".format(types="|".join(cmake_build_types))),
("jobs=", None, "Specifies the number of jobs to use with make."),
("cmake-args=", None, "Additional options to be passed to CMake."),
]
def initialize_options(self):
"""Set default values for all the options that this command supports."""
super().initialize_options()
self.build_base = 'build'
self.build_base = "build"
self.config = None
self.jobs = None
self.cmake_args = None
@@ -144,52 +144,52 @@ class CustomBuild(build):
if not self.config:
if self.debug:
self.config = 'Debug'
self.config = "Debug"
else:
self.announce('Set default value for CMAKE_BUILD_TYPE = Release.', level=4)
self.config = 'Release'
self.announce("Set default value for CMAKE_BUILD_TYPE = Release.", level=4)
self.config = "Release"
else:
build_types = [item.lower() for item in self.cmake_build_types]
try:
i = build_types.index(str(self.config).lower())
self.config = self.cmake_build_types[i]
self.debug = True if 'Debug' == self.config else False
self.debug = True if "Debug" == self.config else False
except ValueError:
self.announce('Unsupported CMAKE_BUILD_TYPE value: ' + self.config, level=4)
self.announce('Supported values: {types}'.format(types=', '.join(self.cmake_build_types)), level=4)
self.announce("Unsupported CMAKE_BUILD_TYPE value: " + self.config, level=4)
self.announce("Supported values: {types}".format(types=", ".join(self.cmake_build_types)), level=4)
sys.exit(1)
if self.jobs is None and os.getenv('MAX_JOBS') is not None:
self.jobs = os.getenv('MAX_JOBS')
if self.jobs is None and os.getenv("MAX_JOBS") is not None:
self.jobs = os.getenv("MAX_JOBS")
self.jobs = multiprocessing.cpu_count() if self.jobs is None else int(self.jobs)
def run(self):
global CMAKE_BUILD_DIR
self.jobs = multiprocessing.cpu_count()
plat_specifier = '.{0}-{1}.{2}'.format(self.plat_name, *sys.version_info[:2])
self.build_temp = os.path.join(self.build_base, 'temp' + plat_specifier, self.config)
plat_specifier = ".{0}-{1}.{2}".format(self.plat_name, *sys.version_info[:2])
self.build_temp = os.path.join(self.build_base, "temp" + plat_specifier, self.config)
# if setup.py is directly called use CMake to build product
if CMAKE_BUILD_DIR == '.':
if CMAKE_BUILD_DIR == ".":
# set path to the root of OpenVINO CMakeList file
openvino_root_dir = Path(__file__).resolve().parents[4]
self.announce(f'Configuring cmake project: {openvino_root_dir}', level=3)
self.spawn(['cmake', '-H' + str(openvino_root_dir), '-B' + self.build_temp,
'-DCMAKE_BUILD_TYPE={type}'.format(type=self.config),
'-DENABLE_PYTHON=ON',
'-DENABLE_OV_ONNX_FRONTEND=ON'])
self.announce(f"Configuring cmake project: {openvino_root_dir}", level=3)
self.spawn(["cmake", "-H" + str(openvino_root_dir), "-B" + self.build_temp,
"-DCMAKE_BUILD_TYPE={type}".format(type=self.config),
"-DENABLE_PYTHON=ON",
"-DENABLE_OV_ONNX_FRONTEND=ON"])
self.announce('Building binaries', level=3)
self.spawn(['cmake', '--build', self.build_temp,
'--config', self.config, '-j', str(self.jobs)])
self.announce("Building binaries", level=3)
self.spawn(["cmake", "--build", self.build_temp,
"--config", self.config, "-j", str(self.jobs)])
CMAKE_BUILD_DIR = self.build_temp
self.run_command('build_clib')
self.run_command("build_clib")
build.run(self)
# Copy extra package_data content filtered by find_packages
dst = Path(self.build_lib)
src = Path(get_package_dir(PY_INSTALL_CFG))
exclude = ignore_patterns('*ez_setup*', '*__pycache__*', '*.egg-info*')
for path in src.glob('**/*'):
exclude = ignore_patterns("*ez_setup*", "*__pycache__*", "*.egg-info*")
for path in src.glob("**/*"):
if path.is_dir() or exclude(str(path)):
continue
path_rel = path.relative_to(src)
@@ -198,7 +198,7 @@ class CustomBuild(build):
class PrepareLibs(build_clib):
"""Prepare prebuilt libraries"""
"""Prepare prebuilt libraries."""
def run(self):
self.configure(LIB_INSTALL_CFG)
@@ -208,30 +208,27 @@ class PrepareLibs(build_clib):
def configure(self, install_cfg):
"""Collect prebuilt libraries. Install them to the temp directories, set rpath."""
for comp, comp_data in install_cfg.items():
install_prefix = comp_data.get('prefix')
install_dir = comp_data.get('install_dir')
install_prefix = comp_data.get("prefix")
install_dir = comp_data.get("install_dir")
if install_dir and not os.path.isabs(install_dir):
install_dir = os.path.join(install_prefix, install_dir)
self.announce(f'Installing {comp}', level=3)
self.spawn(['cmake', '--install', CMAKE_BUILD_DIR, '--prefix', install_prefix, '--component', comp_data.get('name')])
self.announce(f"Installing {comp}", level=3)
self.spawn(["cmake", "--install", CMAKE_BUILD_DIR, "--prefix", install_prefix, "--component", comp_data.get("name")])
# set rpath if applicable
if sys.platform != 'win32' and comp_data.get('rpath'):
file_types = ['.so'] if sys.platform == 'linux' else ['.dylib', '.so']
for path in filter(lambda p: any(item in file_types for item in p.suffixes), Path(install_dir).glob('*')):
set_rpath(comp_data['rpath'], os.path.realpath(path))
if sys.platform != "win32" and comp_data.get("rpath"):
file_types = [".so"] if sys.platform == "linux" else [".dylib", ".so"]
for path in filter(lambda p: any(item in file_types for item in p.suffixes), Path(install_dir).glob("*")):
set_rpath(comp_data["rpath"], os.path.realpath(path))
def generate_package(self, src_dirs):
"""
Collect package data files from preinstalled dirs and
put all runtime libraries to the subpackage
"""
"""Collect package data files from preinstalled dirs and put all runtime libraries to the subpackage."""
# additional blacklist filter, just to fix cmake install issues
blacklist = ['.lib', '.pdb', '_debug.dll', '_debug.dylib']
blacklist = [".lib", ".pdb", "_debug.dll", "_debug.dylib"]
package_dir = os.path.join(get_package_dir(PY_INSTALL_CFG), WHEEL_LIBS_INSTALL_DIR)
for src_dir in src_dirs:
local_base_dir = Path(src_dir)
for file_path in local_base_dir.rglob('*'):
for file_path in local_base_dir.rglob("*"):
file_name = os.path.basename(file_path)
if file_path.is_file() and not any(file_name.endswith(ext) for ext in blacklist):
dst_file = os.path.join(package_dir, os.path.relpath(file_path, local_base_dir))
@@ -239,51 +236,51 @@ class PrepareLibs(build_clib):
copyfile(file_path, dst_file)
if Path(package_dir).exists():
self.announce(f'Adding {WHEEL_LIBS_PACKAGE} package', level=3)
self.announce(f"Adding {WHEEL_LIBS_PACKAGE} package", level=3)
packages.append(WHEEL_LIBS_PACKAGE)
package_data.update({WHEEL_LIBS_PACKAGE: ['*']})
package_data.update({WHEEL_LIBS_PACKAGE: ["*"]})
class CopyExt(build_ext):
"""Copy extension files to the build directory"""
"""Copy extension files to the build directory."""
def run(self):
if len(self.extensions) == 1:
self.run_command('build_clib')
self.run_command("build_clib")
self.extensions = []
self.extensions = find_prebuilt_extensions(get_dir_list(PY_INSTALL_CFG))
for extension in self.extensions:
if not isinstance(extension, PrebuiltExtension):
raise DistutilsSetupError(f'copy_ext can accept PrebuiltExtension only, but got {extension.name}')
raise DistutilsSetupError(f"copy_ext can accept PrebuiltExtension only, but got {extension.name}")
src = extension.sources[0]
dst = self.get_ext_fullpath(extension.name)
os.makedirs(os.path.dirname(dst), exist_ok=True)
# setting relative path to find dlls
if sys.platform != 'win32':
if sys.platform != "win32":
rpath = os.path.relpath(get_package_dir(PY_INSTALL_CFG), os.path.dirname(src))
if sys.platform == 'linux':
rpath = os.path.join('$ORIGIN', rpath, WHEEL_LIBS_INSTALL_DIR)
elif sys.platform == 'darwin':
rpath = os.path.join('@loader_path', rpath, WHEEL_LIBS_INSTALL_DIR)
if sys.platform == "linux":
rpath = os.path.join("$ORIGIN", rpath, WHEEL_LIBS_INSTALL_DIR)
elif sys.platform == "darwin":
rpath = os.path.join("@loader_path", rpath, WHEEL_LIBS_INSTALL_DIR)
set_rpath(rpath, os.path.realpath(src))
copy_file(src, dst, verbose=self.verbose, dry_run=self.dry_run)
class CustomInstall(install):
"""Enable build_clib during the installation"""
"""Enable build_clib during the installation."""
def run(self):
self.run_command('build')
self.run_command("build")
install.run(self)
class CustomClean(clean):
"""Clean up staging directories"""
"""Clean up staging directories."""
def clean(self, install_cfg):
for comp, comp_data in install_cfg.items():
install_prefix = comp_data.get('prefix')
self.announce(f'Cleaning {comp}: {install_prefix}', level=3)
install_prefix = comp_data.get("prefix")
self.announce(f"Cleaning {comp}: {install_prefix}", level=3)
if os.path.exists(install_prefix):
rmtree(install_prefix)
@@ -294,14 +291,12 @@ class CustomClean(clean):
def ignore_patterns(*patterns):
"""
Filter names by given patterns
"""
"""Filter names by given patterns."""
return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns)
def is_tool(name):
"""Check if the command-line tool is available"""
"""Check if the command-line tool is available."""
try:
devnull = subprocess.DEVNULL
subprocess.Popen([name], stdout=devnull, stderr=devnull).communicate() # nosec
@@ -312,101 +307,101 @@ def is_tool(name):
def remove_rpath(file_path):
"""
Remove rpath from binaries
"""Remove rpath from binaries.
:param file_path: binary path
:type file_path: pathlib.Path
"""
if sys.platform == 'darwin':
if sys.platform == "darwin":
cmd = (
f'otool -l {file_path} ' # noqa: P103
f'| grep LC_RPATH -A3 '
f'| grep -o "path.*" '
f'| cut -d " " -f2 '
f'| xargs -I{{}} install_name_tool -delete_rpath {{}} {file_path}'
f"otool -l {file_path} " # noqa: P103
f"| grep LC_RPATH -A3 "
f"| grep -o 'path.*' "
f"| cut -d ' ' -f2 "
f"| xargs -I{{}} install_name_tool -delete_rpath {{}} {file_path}"
)
if os.WEXITSTATUS(os.system(cmd)) != 0: # nosec
sys.exit(f'Could not remove rpath for {file_path}')
sys.exit(f"Could not remove rpath for {file_path}")
else:
sys.exit(f'Unsupported platform: {sys.platform}')
sys.exit(f"Unsupported platform: {sys.platform}")
def set_rpath(rpath, executable):
"""Setting rpath for linux and macOS libraries"""
print(f'Setting rpath {rpath} for {executable}') # noqa: T001
"""Setting rpath for linux and macOS libraries."""
print(f"Setting rpath {rpath} for {executable}") # noqa: T001
cmd = []
rpath_tool = ''
rpath_tool = ""
if sys.platform == 'linux':
with open(os.path.realpath(executable), 'rb') as file:
if file.read(1) != b'\x7f':
log.warn(f'WARNING: {executable}: missed ELF header')
if sys.platform == "linux":
with open(os.path.realpath(executable), "rb") as file:
if file.read(1) != b"\x7f":
log.warn(f"WARNING: {executable}: missed ELF header")
return
rpath_tool = 'patchelf'
cmd = [rpath_tool, '--set-rpath', rpath, executable]
elif sys.platform == 'darwin':
rpath_tool = 'install_name_tool'
cmd = [rpath_tool, '-add_rpath', rpath, executable]
rpath_tool = "patchelf"
cmd = [rpath_tool, "--set-rpath", rpath, executable]
elif sys.platform == "darwin":
rpath_tool = "install_name_tool"
cmd = [rpath_tool, "-add_rpath", rpath, executable]
else:
sys.exit(f'Unsupported platform: {sys.platform}')
sys.exit(f"Unsupported platform: {sys.platform}")
if is_tool(rpath_tool):
if sys.platform == 'darwin':
if sys.platform == "darwin":
remove_rpath(executable)
ret_info = subprocess.run(cmd, check=True, shell=False) # nosec
if ret_info.returncode != 0:
sys.exit(f'Could not set rpath: {rpath} for {executable}')
sys.exit(f"Could not set rpath: {rpath} for {executable}")
else:
sys.exit(f'Could not found {rpath_tool} on the system, ' f'please make sure that this tool is installed')
sys.exit(f"Could not found {rpath_tool} on the system, " f"please make sure that this tool is installed")
def find_prebuilt_extensions(search_dirs):
"""collect prebuilt python extensions"""
"""Collect prebuilt python extensions."""
extensions = []
ext_pattern = ''
if sys.platform == 'linux':
ext_pattern = '**/*.so'
elif sys.platform == 'win32':
ext_pattern = '**/*.pyd'
elif sys.platform == 'darwin':
ext_pattern = '**/*.so'
ext_pattern = ""
if sys.platform == "linux":
ext_pattern = "**/*.so"
elif sys.platform == "win32":
ext_pattern = "**/*.pyd"
elif sys.platform == "darwin":
ext_pattern = "**/*.so"
for base_dir in search_dirs:
for path in Path(base_dir).glob(ext_pattern):
if path.match('openvino/libs/*'):
if path.match("openvino/libs/*"):
continue
relpath = path.relative_to(base_dir)
if relpath.parent != '.':
if relpath.parent != ".":
package_names = str(relpath.parent).split(os.path.sep)
else:
package_names = []
package_names.append(path.name.split('.', 1)[0])
name = '.'.join(package_names)
package_names.append(path.name.split(".", 1)[0])
name = ".".join(package_names)
extensions.append(PrebuiltExtension(name, sources=[str(path)]))
if not extensions:
extensions.append(PrebuiltExtension('openvino', sources=[str('setup.py')]))
extensions.append(PrebuiltExtension("openvino", sources=[str("setup.py")]))
return extensions
def get_description(desc_file_path):
"""read description from README.md"""
with open(desc_file_path, 'r', encoding='utf-8') as fstream:
"""Read description from README.md."""
with open(desc_file_path, "r", encoding="utf-8") as fstream:
description = fstream.read()
return description
def get_dependencies(requirements_file_path):
"""read dependencies from requirements.txt"""
with open(requirements_file_path, 'r', encoding='utf-8') as fstream:
"""Read dependencies from requirements.txt."""
with open(requirements_file_path, "r", encoding="utf-8") as fstream:
dependencies = fstream.read()
return dependencies
def get_dir_list(install_cfg):
"""collect all available directories with libs or python packages"""
"""Collect all available directories with libs or python packages."""
dirs = []
for comp_info in install_cfg.values():
cfg_prefix = comp_info.get('prefix')
cfg_dir = comp_info.get('install_dir')
cfg_prefix = comp_info.get("prefix")
cfg_dir = comp_info.get("install_dir")
if cfg_dir:
if not os.path.isabs(cfg_dir):
cfg_dir = os.path.join(cfg_prefix, cfg_dir)
@@ -416,11 +411,8 @@ def get_dir_list(install_cfg):
def get_package_dir(install_cfg):
"""
Get python package path based on config
All the packages should be located in one directory
"""
py_package_path = ''
"""Get python package path based on config. All the packages should be located in one directory."""
py_package_path = ""
dirs = get_dir_list(install_cfg)
if len(dirs) != 0:
# setup.py support only one package directory, all modules should be located there
@@ -429,62 +421,62 @@ def get_package_dir(install_cfg):
def concat_files(output_file, input_files):
with open(output_file, 'w', encoding='utf-8') as outfile:
with open(output_file, "w", encoding="utf-8") as outfile:
for filename in input_files:
with open(filename, 'r', encoding='utf-8') as infile:
with open(filename, "r", encoding="utf-8") as infile:
content = infile.read()
outfile.write(content)
return output_file
platforms = ['linux', 'win32', 'darwin']
platforms = ["linux", "win32", "darwin"]
if not any(pl in sys.platform for pl in platforms):
sys.exit(f'Unsupported platform: {sys.platform}, expected: linux, win32, darwin')
sys.exit(f"Unsupported platform: {sys.platform}, expected: linux, win32, darwin")
# copy license file into the build directory
package_license = os.getenv('WHEEL_LICENSE', SCRIPT_DIR.parents[3] / 'LICENSE')
package_license = os.getenv("WHEEL_LICENSE", SCRIPT_DIR.parents[3] / "LICENSE")
if os.path.exists(package_license):
copyfile(package_license, 'LICENSE')
copyfile(package_license, "LICENSE")
packages = find_namespace_packages(get_package_dir(PY_INSTALL_CFG))
package_data: typing.Dict[str, list] = {}
pkg_name = os.getenv('WHEEL_PACKAGE_NAME', 'openvino')
ext_modules = find_prebuilt_extensions(get_dir_list(PY_INSTALL_CFG)) if pkg_name == 'openvino' else []
pkg_name = os.getenv("WHEEL_PACKAGE_NAME", "openvino")
ext_modules = find_prebuilt_extensions(get_dir_list(PY_INSTALL_CFG)) if pkg_name == "openvino" else []
description_md = SCRIPT_DIR.parents[3] / 'docs' / 'install_guides' / 'pypi-openvino-rt.md'
md_files = [description_md, SCRIPT_DIR.parents[3] / 'docs' / 'install_guides' / 'pre-release-note.md']
docs_url = 'https://docs.openvino.ai/latest/index.html'
description_md = SCRIPT_DIR.parents[3] / "docs" / "install_guides" / "pypi-openvino-rt.md"
md_files = [description_md, SCRIPT_DIR.parents[3] / "docs" / "install_guides" / "pre-release-note.md"]
docs_url = "https://docs.openvino.ai/latest/index.html"
if(os.getenv('CI_BUILD_DEV_TAG')):
output = Path.cwd() / 'build' / 'pypi-openvino-rt.md'
if(os.getenv("CI_BUILD_DEV_TAG")):
output = Path.cwd() / "build" / "pypi-openvino-rt.md"
output.parent.mkdir(exist_ok=True)
description_md = concat_files(output, md_files)
docs_url = 'https://docs.openvino.ai/nightly/index.html'
docs_url = "https://docs.openvino.ai/nightly/index.html"
setup(
version=os.getenv('WHEEL_VERSION', '0.0.0'),
build=os.getenv('WHEEL_BUILD', '000'),
author_email=os.getenv('WHEEL_AUTHOR_EMAIL', 'openvino_pushbot@intel.com'),
version=os.getenv("WHEEL_VERSION", "0.0.0"),
build=os.getenv("WHEEL_BUILD", "000"),
author_email=os.getenv("WHEEL_AUTHOR_EMAIL", "openvino_pushbot@intel.com"),
name=pkg_name,
license=os.getenv('WHEEL_LICENCE_TYPE', 'OSI Approved :: Apache Software License'),
author=os.getenv('WHEEL_AUTHOR', 'Intel(R) Corporation'),
description=os.getenv('WHEEL_DESC', 'OpenVINO(TM) Runtime'),
install_requires=get_dependencies(os.getenv('WHEEL_REQUIREMENTS', SCRIPT_DIR.parents[0] / 'requirements.txt')),
long_description=get_description(os.getenv('WHEEL_OVERVIEW', description_md)),
long_description_content_type='text/markdown',
download_url=os.getenv('WHEEL_DOWNLOAD_URL', 'https://github.com/openvinotoolkit/openvino/tags'),
url=os.getenv('WHEEL_URL', docs_url),
license=os.getenv("WHEEL_LICENCE_TYPE", "OSI Approved :: Apache Software License"),
author=os.getenv("WHEEL_AUTHOR", "Intel(R) Corporation"),
description=os.getenv("WHEEL_DESC", "OpenVINO(TM) Runtime"),
install_requires=get_dependencies(os.getenv("WHEEL_REQUIREMENTS", SCRIPT_DIR.parents[0] / "requirements.txt")),
long_description=get_description(os.getenv("WHEEL_OVERVIEW", description_md)),
long_description_content_type="text/markdown",
download_url=os.getenv("WHEEL_DOWNLOAD_URL", "https://github.com/openvinotoolkit/openvino/tags"),
url=os.getenv("WHEEL_URL", docs_url),
cmdclass={
'build': CustomBuild,
'install': CustomInstall,
'build_clib': PrepareLibs,
'build_ext': CopyExt,
'clean': CustomClean,
"build": CustomBuild,
"install": CustomInstall,
"build_clib": PrepareLibs,
"build_ext": CopyExt,
"clean": CustomClean,
},
ext_modules=ext_modules,
packages=packages,
package_dir={'': get_package_dir(PY_INSTALL_CFG)},
package_dir={"": get_package_dir(PY_INSTALL_CFG)},
package_data=package_data,
zip_safe=False,
)
+38 -53
View File
@@ -2,30 +2,26 @@
# SPDX-License-Identifier: Apache-2.0
#
function(set_ie_threading_interface_for TARGET_NAME)
macro(ext_message TRACE_LEVEL)
if (TRACE_LEVEL STREQUAL FATAL_ERROR)
if(InferenceEngine_FIND_REQUIRED)
message(FATAL_ERROR "${ARGN}")
elseif(NOT InferenceEngine_FIND_QUIETLY)
message(WARNING "${ARGN}")
endif()
return()
elseif(NOT InferenceEngine_FIND_QUIETLY)
message(${TRACE_LEVEL} "${ARGN}")
endif ()
endmacro()
macro(ov_find_tbb)
if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO" AND NOT TBB_FOUND)
find_package(TBB COMPONENTS tbb tbbmalloc)
if (THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO" AND NOT TBB_FOUND)
if(IEDevScripts_DIR)
# try to find TBB via custom scripts if have not found by default
if(NOT TBB_FOUND AND IEDevScripts_DIR)
# remove invalid TBB_DIR=TBB_DIR-NOTFOUND from cache
unset(TBB_DIR CACHE)
unset(TBB_DIR)
# use our custom scripts for old TBB versions
# which are exposed via `export TBBROOT=<tbbroot>`
# see https://github.com/openvinotoolkit/openvino/pull/1288
find_package(TBB COMPONENTS tbb tbbmalloc
PATHS IEDevScripts_DIR
PATHS ${IEDevScripts_DIR}
NO_CMAKE_FIND_ROOT_PATH
NO_DEFAULT_PATH)
else()
find_dependency(TBB COMPONENTS tbb tbbmalloc)
endif()
# oneTBB does not define TBB_IMPORTED_TARGETS
# WA for oneTBB: it does not define TBB_IMPORTED_TARGETS
if(TBB_FOUND AND NOT TBB_IMPORTED_TARGETS)
foreach(target TBB::tbb TBB::tbbmalloc)
if(TARGET ${target})
@@ -33,15 +29,23 @@ function(set_ie_threading_interface_for TARGET_NAME)
endif()
endforeach()
endif()
# set variables to parent scope to prevent multiple invocations of find_package(TBB)
# at the same CMakeLists.txt; invocations in different directories are allowed
set(TBB_FOUND ${TBB_FOUND} PARENT_SCOPE)
set(TBB_IMPORTED_TARGETS ${TBB_IMPORTED_TARGETS} PARENT_SCOPE)
set(TBB_VERSION ${TBB_VERSION} PARENT_SCOPE)
if (NOT TBB_FOUND)
set(THREADING "SEQ" PARENT_SCOPE)
ext_message(WARNING "TBB was not found by the configured TBB_DIR/TBBROOT path.\
SEQ method will be used.")
message(WARNING "TBB was not found by the configured TBB_DIR/TBBROOT path.\
SEQ method will be used.")
endif ()
endif()
endmacro()
function(set_ie_threading_interface_for TARGET_NAME)
# find TBB
ov_find_tbb()
get_target_property(target_type ${TARGET_NAME} TYPE)
@@ -59,32 +63,11 @@ function(set_ie_threading_interface_for TARGET_NAME)
# TODO: why TBB propogates its headers to inference_engine?
set(LINK_TYPE "PRIVATE")
else()
ext_message(WARNING "Unknown target type")
message(WARNING "Unknown target type")
endif()
function(ie_target_link_libraries TARGET_NAME LINK_TYPE)
if(CMAKE_VERSION VERSION_LESS "3.12.0")
if(NOT target_type STREQUAL "OBJECT_LIBRARY")
target_link_libraries(${TARGET_NAME} ${LINK_TYPE} ${ARGN})
else()
# Object library may not link to anything.
# To add interface include definitions and compile options explicitly.
foreach(ITEM IN LISTS ARGN)
if(TARGET ${ITEM})
get_target_property(compile_options ${ITEM} INTERFACE_COMPILE_OPTIONS)
if (compile_options)
target_compile_options(${TARGET_NAME} ${LINK_TYPE} ${compile_options})
endif()
get_target_property(compile_definitions ${ITEM} INTERFACE_COMPILE_DEFINITIONS)
if (compile_definitions)
target_compile_definitions(${TARGET_NAME} ${LINK_TYPE} ${compile_definitions})
endif()
endif()
endforeach()
endif()
else()
target_link_libraries(${TARGET_NAME} ${LINK_TYPE} ${ARGN})
endif()
target_link_libraries(${TARGET_NAME} ${LINK_TYPE} ${ARGN})
# include directories as SYSTEM
foreach(library IN LISTS ARGN)
@@ -92,8 +75,11 @@ function(set_ie_threading_interface_for TARGET_NAME)
get_target_property(include_directories ${library} INTERFACE_INCLUDE_DIRECTORIES)
if(include_directories)
foreach(include_directory IN LISTS include_directories)
target_include_directories(${TARGET_NAME} SYSTEM BEFORE
${LINK_TYPE} $<BUILD_INTERFACE:${include_directory}>)
# cannot include /usr/include headers as SYSTEM
if(NOT "${include_directory}" MATCHES "^/usr.*$")
target_include_directories(${TARGET_NAME} SYSTEM BEFORE
${LINK_TYPE} $<BUILD_INTERFACE:${include_directory}>)
endif()
endforeach()
endif()
endif()
@@ -108,8 +94,8 @@ function(set_ie_threading_interface_for TARGET_NAME)
ie_target_link_libraries(${TARGET_NAME} ${LINK_TYPE} ${TBB_IMPORTED_TARGETS})
else ()
set(THREADING "SEQ" PARENT_SCOPE)
ext_message(WARNING "TBB was not found by the configured TBB_DIR path.\
SEQ method will be used for ${TARGET_NAME}")
message(WARNING "TBB was not found by the configured TBB_DIR path.\
SEQ method will be used for ${TARGET_NAME}")
endif ()
elseif (THREADING STREQUAL "OMP")
if (WIN32)
@@ -133,19 +119,19 @@ function(set_ie_threading_interface_for TARGET_NAME)
if (NOT OMP_LIBRARIES_RELEASE)
find_library(OMP_LIBRARIES_RELEASE ${omp_lib_name} ${lib_rel_path} NO_DEFAULT_PATH)
ext_message(STATUS "OMP Release lib: ${OMP_LIBRARIES_RELEASE}")
message(STATUS "OMP Release lib: ${OMP_LIBRARIES_RELEASE}")
if (NOT LINUX)
find_library(OMP_LIBRARIES_DEBUG ${omp_lib_name} ${lib_dbg_path} NO_DEFAULT_PATH)
if (OMP_LIBRARIES_DEBUG)
ext_message(STATUS "OMP Debug lib: ${OMP_LIBRARIES_DEBUG}")
message(STATUS "OMP Debug lib: ${OMP_LIBRARIES_DEBUG}")
else ()
ext_message(WARNING "OMP Debug binaries are missed.")
message(WARNING "OMP Debug binaries are missed.")
endif ()
endif ()
endif ()
if (NOT OMP_LIBRARIES_RELEASE)
ext_message(WARNING "Intel OpenMP not found. Intel OpenMP support will be disabled. ${IE_THREAD_DEFINE} is defined")
message(WARNING "Intel OpenMP not found. Intel OpenMP support will be disabled. ${IE_THREAD_DEFINE} is defined")
set(THREADING "SEQ" PARENT_SCOPE)
else ()
set(IE_THREAD_DEFINE "IE_THREAD_OMP")
@@ -174,7 +160,6 @@ function(set_ie_threading_interface_for TARGET_NAME)
ie_target_link_libraries(${TARGET_NAME} ${LINK_TYPE} ${OMP_LIBRARIES_RELEASE})
endif ()
endif ()
endif ()
target_compile_definitions(${TARGET_NAME} ${LINK_TYPE} -DIE_THREAD=${IE_THREAD_DEFINE})
+88 -22
View File
@@ -2,6 +2,11 @@
# SPDX-License-Identifier: Apache-2.0
#
include(cmake/ie_parallel.cmake)
# pre-find TBB: need to provide TBB_IMPORTED_TARGETS used for installation
ov_find_tbb()
if(ENABLE_TBBBIND_2_5)
# try to find prebuilt version of tbbbind_2_5
find_package(TBBBIND_2_5 QUIET)
@@ -12,6 +17,8 @@ if(ENABLE_TBBBIND_2_5)
if(NOT BUILD_SHARED_LIBS)
set(install_tbbbind ON)
endif()
else()
message(WARNING "Static tbbbind_2_5 package is not found")
endif()
endif()
@@ -28,34 +35,93 @@ if(install_tbbbind)
list(APPEND PATH_VARS "IE_TBBBIND_DIR")
endif()
# install only downloaded TBB, system one is not installed
if(THREADING MATCHES "^(TBB|TBB_AUTO)$" AND TBBROOT MATCHES ${TEMP})
# install only downloaded | custom TBB, system one is not installed
# - downloaded TBB should be a part of all packages
# - custom TBB provided by users, needs to be a part of wheel packages
# - TODO: system TBB also needs to be a part of wheel packages
if(THREADING MATCHES "^(TBB|TBB_AUTO)$" AND
(TBB MATCHES ${TEMP} OR DEFINED ENV{TBBROOT} OR ENABLE_SYSTEM_TBB))
ie_cpack_add_component(tbb REQUIRED)
ie_cpack_add_component(tbb_dev REQUIRED)
list(APPEND core_components tbb)
list(APPEND core_dev_components tbb_dev)
install(DIRECTORY "${TBB}/lib"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb)
# Windows only
if(EXISTS "${TBB}/bin")
install(DIRECTORY "${TBB}/bin"
if(TBB MATCHES ${TEMP})
set(tbb_downloaded ON)
elseif(DEFINED ENV{TBB})
set(tbb_custom ON)
endif()
if(tbb_custom OR ENABLE_SYSTEM_TBB)
# since the setup.py for pip installs tbb component
# explicitly, it's OK to put EXCLUDE_FROM_ALL to such component
# to ignore from IRC distribution
set(exclude_from_all EXCLUDE_FROM_ALL)
endif()
if(ENABLE_SYSTEM_TBB)
# need to take locations of actual libraries and install them
foreach(tbb_lib IN LISTS TBB_IMPORTED_TARGETS)
get_target_property(tbb_loc ${tbb_lib} IMPORTED_LOCATION_RELEASE)
# depending on the TBB, tbb_loc can be in form:
# - libtbb.so.x.y
# - libtbb.so.x
# - libtbb.so
# We need to install such files
get_filename_component(name_we "${tbb_loc}" NAME_WE)
get_filename_component(dir "${tbb_loc}" DIRECTORY)
file(GLOB tbb_files "${dir}/${name_we}.*")
foreach(tbb_file IN LISTS tbb_files)
if(tbb_file MATCHES "^.*\.${CMAKE_SHARED_LIBRARY_SUFFIX}(\.[0-9]+)*$")
install(FILES "${tbb_file}"
DESTINATION runtime/3rdparty/tbb/lib
COMPONENT tbb ${exclude_from_all})
endif()
endforeach()
endforeach()
else()
if(WIN32)
install(DIRECTORY "${TBB}/bin"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb ${exclude_from_all})
elseif(tbb_custom OR tbb_downloaded)
install(DIRECTORY "${TBB}/lib"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb ${exclude_from_all}
FILES_MATCHING
# install only versioned shared libraries
REGEX "^.*\.${CMAKE_SHARED_LIBRARY_SUFFIX}(\.[0-9]+)*$")
endif()
endif()
# development files are needed only for 'tbb_downloaded' case
# which we are going to distribute
if(tbb_downloaded)
ie_cpack_add_component(tbb_dev REQUIRED)
list(APPEND core_dev_components tbb_dev)
install(FILES "${TBB}/LICENSE"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb)
endif()
install(FILES "${TBB}/LICENSE"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb)
set(IE_TBB_DIR_INSTALL "3rdparty/tbb/cmake")
install(FILES "${TBB}/cmake/TBBConfig.cmake"
"${TBB}/cmake/TBBConfigVersion.cmake"
DESTINATION runtime/${IE_TBB_DIR_INSTALL}
COMPONENT tbb_dev)
install(DIRECTORY "${TBB}/include"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb_dev)
set(IE_TBB_DIR_INSTALL "3rdparty/tbb/cmake")
install(FILES "${TBB}/cmake/TBBConfig.cmake"
"${TBB}/cmake/TBBConfigVersion.cmake"
DESTINATION runtime/${IE_TBB_DIR_INSTALL}
COMPONENT tbb_dev)
install(DIRECTORY "${TBB}/include"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb_dev)
if(WIN32)
# .lib files are needed only for Windows
install(DIRECTORY "${TBB}/lib"
DESTINATION runtime/3rdparty/tbb
COMPONENT tbb)
endif()
endif()
unset(tbb_downloaded)
unset(tbb_custom)
unset(exclude_from_all)
endif()
# install tbbbind for static OpenVINO case
@@ -33,6 +33,8 @@ target_include_directories(${TARGET_NAME}_obj PRIVATE $<BUILD_INTERFACE:${PUBLIC
add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME}_obj)
ie_mark_target_as_cc(${TARGET_NAME}_obj)
if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(${TARGET_NAME}_obj PUBLIC OPENVINO_STATIC_LIBRARY)
endif()
@@ -0,0 +1,45 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
/**
* @brief Defines openvino domains for tracing
* @file itt.hpp
*/
#pragma once
#include <openvino/cc/selective_build.h>
#include <openvino/itt.hpp>
#include <openvino/cc/ngraph/itt.hpp>
namespace ngraph {
namespace pass {
namespace low_precision {
namespace itt {
namespace domains {
OV_ITT_DOMAIN(LowPrecisionTransformations);
} // namespace domains
} // namespace itt
} // namespace low_precision
} // namespace pass
} // namespace ngraph
/*
* RUN_ON_FUNCTION_SCOPE macro allows to disable the run_on_function pass
* MATCHER_SCOPE macro allows to disable the MatcherPass if matcher isn't applied
* INTERNAL_OP_SCOPE macro allows to disable parts of internal nGraph operations if they are not used
*/
#if defined(SELECTIVE_BUILD_ANALYZER)
#define INTERNAL_OP_SCOPE(region) OV_SCOPE(internal_op, region)
#elif defined(SELECTIVE_BUILD)
#define INTERNAL_OP_SCOPE(region) MATCHER_SCOPE_(internal_op, region)
#else
#define INTERNAL_OP_SCOPE(region)
#endif
@@ -15,6 +15,7 @@
#include "low_precision/common/ie_lpt_exception.hpp"
#include "low_precision/network_helper.hpp"
#include "itt.hpp"
namespace ngraph {
namespace pass {
@@ -93,6 +94,7 @@ std::shared_ptr<opset1::Subtract> fuseWithSubtract(const std::shared_ptr<Node>&
} // namespace
AddTransformation::AddTransformation(const Params& params) : EltwiseBaseTransformation(params) {
MATCHER_SCOPE(AddTransformation);
auto matcher = ngraph::pattern::wrap_type<opset1::Add>();
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
@@ -103,7 +105,7 @@ AddTransformation::AddTransformation(const Params& params) : EltwiseBaseTransfor
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "AddTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
@@ -9,6 +9,7 @@
#include "low_precision/propagate_through_precision_preserved.hpp"
#include "low_precision/rt_info/intervals_alignment_attribute.hpp"
#include "low_precision/rt_info/attribute_parameters.hpp"
#include "itt.hpp"
using namespace ngraph;
using namespace ngraph::pass::low_precision;
@@ -17,6 +18,7 @@ ngraph::pass::low_precision::AlignQuantizationIntervals::AlignQuantizationInterv
: defaultPrecisions(defaultPrecisions) {}
bool ngraph::pass::low_precision::AlignQuantizationIntervals::run_on_model(const std::shared_ptr<ngraph::Function>& f) {
RUN_ON_FUNCTION_SCOPE(AlignQuantizationIntervals);
ngraph::pass::Manager manager;
manager.set_per_pass_validation(false);
std::shared_ptr<ngraph::pass::GraphRewrite> intervalsAlignment = manager.register_pass<ngraph::pass::GraphRewrite>();
@@ -10,6 +10,7 @@
#include "low_precision/rt_info/per_tensor_quantization_attribute.hpp"
#include "low_precision/update_shared_precision_preserved.hpp"
#include "low_precision/rt_info/attribute_parameters.hpp"
#include "itt.hpp"
using namespace ngraph;
using namespace ngraph::pass::low_precision;
@@ -18,6 +19,7 @@ ngraph::pass::low_precision::AlignQuantizationParameters::AlignQuantizationParam
: defaultPrecisions(defaultPrecisions) {}
bool ngraph::pass::low_precision::AlignQuantizationParameters::run_on_model(const std::shared_ptr<ngraph::Function>& f) {
RUN_ON_FUNCTION_SCOPE(AlignQuantizationParameters);
ngraph::pass::Manager manager;
manager.set_per_pass_validation(false);
std::shared_ptr<ngraph::pass::GraphRewrite> propagation = manager.register_pass<ngraph::pass::GraphRewrite>();
@@ -11,6 +11,7 @@
#include <ngraph/pattern/op/or.hpp>
#include <openvino/op/util/assign_base.hpp>
#include "low_precision/fake_quantize.hpp"
#include "itt.hpp"
namespace ngraph {
namespace pass {
@@ -18,6 +19,7 @@ namespace low_precision {
AssignAndReadValueTransformation::AssignAndReadValueTransformation(const std::shared_ptr<ngraph::Function> function, const Params& params) :
LayerTransformation(params), function(function) {
MATCHER_SCOPE(AssignAndReadValueTransformation);
auto assign3 = pattern::wrap_type<opset3::Assign>({ pattern::wrap_type<opset1::Multiply>() });
auto assign6 = pattern::wrap_type<opset6::Assign>({ pattern::wrap_type<opset1::Multiply>() });
@@ -42,7 +44,7 @@ AssignAndReadValueTransformation::AssignAndReadValueTransformation(const std::sh
auto m = std::make_shared<ngraph::pattern::Matcher>(
std::make_shared<pattern::op::Or>(OutputVector{ assign3, assign6 }),
"AssignAndReadValueTransformation");
matcher_name);
this->register_matcher(m, callback);
}
@@ -11,12 +11,14 @@
#include "low_precision/network_helper.hpp"
#include "low_precision/rt_info/precision_preserved_attribute.hpp"
#include "itt.hpp"
namespace ngraph {
namespace pass {
namespace low_precision {
AvgPoolTransformation::AvgPoolTransformation(const Params& params) : LayerTransformation(params) {
MATCHER_SCOPE(AvgPoolTransformation);
auto matcher = pattern::wrap_type<opset1::AvgPool>({ pattern::wrap_type<opset1::Multiply>() });
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
@@ -27,7 +29,7 @@ AvgPoolTransformation::AvgPoolTransformation(const Params& params) : LayerTransf
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "AvgPoolTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
@@ -9,12 +9,14 @@
#include <ngraph/pattern/op/wrap_type.hpp>
#include "low_precision/network_helper.hpp"
#include "itt.hpp"
namespace ngraph {
namespace pass {
namespace low_precision {
ClampTransformation::ClampTransformation(const Params& params) : LayerTransformation(params) {
MATCHER_SCOPE(ClampTransformation);
auto matcher = pattern::wrap_type<opset1::Clamp>({ pattern::wrap_type<opset1::Multiply>() });
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
@@ -25,7 +27,7 @@ ClampTransformation::ClampTransformation(const Params& params) : LayerTransforma
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "ClampTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
@@ -15,12 +15,14 @@
#include "low_precision/common/fake_quantize_dequantization.hpp"
#include "low_precision/common/ie_lpt_exception.hpp"
#include "low_precision/network_helper.hpp"
#include "itt.hpp"
namespace ngraph {
namespace pass {
namespace low_precision {
ConcatTransformation::ConcatTransformation(const Params& params) : LayerTransformation(params) {
MATCHER_SCOPE(ConcatTransformation);
auto matcher = ngraph::pattern::wrap_type<opset1::Concat>();
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
@@ -32,7 +34,7 @@ ConcatTransformation::ConcatTransformation(const Params& params) : LayerTransfor
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "ConcatTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
@@ -14,12 +14,14 @@
#include <ngraph/pattern/op/wrap_type.hpp>
#include "low_precision/common/ie_lpt_exception.hpp"
#include "low_precision/network_helper.hpp"
#include "itt.hpp"
namespace ngraph {
namespace pass {
namespace low_precision {
ConvertTransformation::ConvertTransformation(const Params& params) : LayerTransformation(params) {
MATCHER_SCOPE(ConvertTransformation);
auto matcher = pattern::wrap_type<opset1::Convert>();
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
@@ -30,7 +32,7 @@ ConvertTransformation::ConvertTransformation(const Params& params) : LayerTransf
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "ConvertTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
@@ -11,6 +11,7 @@
#include <ngraph/pattern/op/wrap_type.hpp>
#include <transformations/rt_info/disable_constant_folding.hpp>
#include "low_precision/network_helper.hpp"
#include "itt.hpp"
using namespace ngraph;
@@ -35,6 +36,7 @@ using namespace ngraph;
// Multiply
//
ngraph::pass::low_precision::ConvertSubtractConstant::ConvertSubtractConstant(const std::vector<ngraph::element::Type>& constantPrecisions) {
MATCHER_SCOPE(ConvertSubtractConstant);
auto weightsConstantWrapper = ngraph::pattern::wrap_type<opset1::Constant>(pattern::consumers_count(1));
auto weightsConvertWrapper = ngraph::pattern::wrap_type<opset1::Convert>({ weightsConstantWrapper }, pattern::consumers_count(1));
auto subtractConstantWrapper = ngraph::pattern::wrap_type<opset1::Constant>(pattern::consumers_count(1));
@@ -91,6 +93,6 @@ ngraph::pass::low_precision::ConvertSubtractConstant::ConvertSubtractConstant(co
return true;
};
auto m = std::make_shared<ngraph::pattern::Matcher>(multiplyWrapper, "ConvertSubtractConstant");
auto m = std::make_shared<ngraph::pattern::Matcher>(multiplyWrapper, matcher_name);
this->register_matcher(m, callback);
}
@@ -14,12 +14,14 @@
#include <ngraph/pattern/op/or.hpp>
#include "low_precision/network_helper.hpp"
#include <transformations/rt_info/disable_constant_folding.hpp>
#include "itt.hpp"
namespace ngraph {
namespace pass {
namespace low_precision {
ConvolutionTransformation::ConvolutionTransformation(const Params& params) : WeightableLayerTransformation(params) {
MATCHER_SCOPE(ConvolutionTransformation);
auto matcher = ngraph::pattern::wrap_type<opset1::Convolution>({
ngraph::pattern::wrap_type<opset1::Multiply>(),
std::make_shared<pattern::op::Or>(OutputVector {
@@ -37,7 +39,7 @@ ConvolutionTransformation::ConvolutionTransformation(const Params& params) : Wei
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "ConvolutionTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
@@ -14,12 +14,14 @@
#include <ngraph/pattern/op/or.hpp>
#include "low_precision/network_helper.hpp"
#include <transformations/rt_info/disable_constant_folding.hpp>
#include "itt.hpp"
namespace ngraph {
namespace pass {
namespace low_precision {
ConvolutionBackpropDataTransformation::ConvolutionBackpropDataTransformation(const Params& params) : WeightableLayerTransformation(params) {
MATCHER_SCOPE(ConvolutionBackpropDataTransformation);
auto matcher = std::make_shared<pattern::op::Or>(OutputVector{
pattern::wrap_type<opset1::ConvolutionBackpropData>({
pattern::wrap_type<opset1::Multiply>(),
@@ -49,7 +51,7 @@ ConvolutionBackpropDataTransformation::ConvolutionBackpropDataTransformation(con
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "ConvolutionBackpropDataTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
@@ -7,12 +7,14 @@
#include <memory>
#include <ngraph/pattern/op/wrap_type.hpp>
#include "low_precision/network_helper.hpp"
#include "itt.hpp"
using namespace ngraph;
using namespace ngraph::pass;
using namespace ngraph::pass::low_precision;
DepthToSpaceTransformation::DepthToSpaceTransformation(const Params& params) : TransparentBaseTransformation(params) {
MATCHER_SCOPE(DepthToSpaceTransformation);
auto matcher = pattern::wrap_type<opset1::DepthToSpace>({ pattern::wrap_type<opset1::Multiply>() });
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
@@ -23,7 +25,7 @@ DepthToSpaceTransformation::DepthToSpaceTransformation(const Params& params) : T
return transform(*context, m);
};
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, "DepthToSpaceTransformation");
auto m = std::make_shared<ngraph::pattern::Matcher>(matcher, matcher_name);
this->register_matcher(m, callback);
}
Loaded 100 of 339 files, more files were not shown because too many files have changed in this diff. Show more