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

This commit is contained in:
Ilya Lavrenov committed 2022-01-13 16:01:38 +03:00
commit 2267703a55
308 files changed
+12983 -5113

No files matched your search

+17
View File
@@ -1,3 +1,10 @@
resources:
repositories:
- repository: openvino_contrib
type: github
endpoint: openvinotoolkit
name: openvinotoolkit/openvino_contrib
jobs:
- job: Lin
# About 150% of total time
@@ -12,6 +19,7 @@ jobs:
VSTS_HTTP_TIMEOUT: 200
BUILD_TYPE: Release
REPO_DIR: $(Build.Repository.LocalPath)
OPENVINO_CONTRIB_REPO_DIR: $(REPO_DIR)/../openvino_contrib
WORK_DIR: $(Pipeline.Workspace)/_w
BUILD_DIR: $(WORK_DIR)/build
BUILD_SAMPLES_DIR: $(WORK_DIR)/build_samples
@@ -51,9 +59,17 @@ jobs:
submodules: recursive
path: openvino
- checkout: openvino_contrib
clean: true
lfs: false
submodules: recursive
path: openvino_contrib
- script: |
set -e
$(REPO_DIR)/install_build_dependencies.sh
# Move jdk into contrib
sudo apt --assume-yes install openjdk-11-jdk
# Speed up build
wget https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-linux.zip
unzip ninja-linux.zip
@@ -70,6 +86,7 @@ jobs:
-DENABLE_FASTER_BUILD=ON
-DENABLE_STRICT_DEPENDENCIES=OFF
-DENABLE_REQUIREMENTS_INSTALL=OFF
-DIE_EXTRA_MODULES=$(OPENVINO_CONTRIB_REPO_DIR)/modules
$(REPO_DIR)
workingDirectory: $(BUILD_DIR)
+3 -3
View File
@@ -23,10 +23,10 @@ jobs:
- job: Win
strategy:
matrix:
Dynamic:
CMAKE_BUILD_SHARED_LIBS: 'ON'
Static:
CMAKE_BUILD_SHARED_LIBS: 'OFF'
# Dynamic:
# CMAKE_BUILD_SHARED_LIBS: 'ON'
maxParallel: 2
# About 150% of total time
@@ -133,7 +133,7 @@ jobs:
- script: |
set PATH=$(WORK_DIR)\ninja-win;%PATH%
call "$(MSVS_VARS_PATH)" && $(CMAKE_CMD) -G "Ninja Multi-Config" -DENABLE_ONEDNN_FOR_GPU=OFF -DENABLE_WHEEL=ON -DENABLE_INTEL_GNA=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_INTEL_GPU=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_GAPI_PREPROCESSING=$(CMAKE_BUILD_SHARED_LIBS) -DBUILD_SHARED_LIBS=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_REQUIREMENTS_INSTALL=OFF -DENABLE_FASTER_BUILD=ON -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DENABLE_TESTS=ON -DENABLE_STRICT_DEPENDENCIES=OFF -DENABLE_PYTHON=ON -DPYTHON_EXECUTABLE="C:\hostedtoolcache\windows\Python\3.7.6\x64\python.exe" -DPYTHON_INCLUDE_DIR="C:\hostedtoolcache\windows\Python\3.7.6\x64\include" -DPYTHON_LIBRARY="C:\hostedtoolcache\windows\Python\3.7.6\x64\libs\python37.lib" -DIE_EXTRA_MODULES=$(OPENVINO_CONTRIB_REPO_DIR)\modules -DCMAKE_C_COMPILER:PATH="$(MSVC_COMPILER_PATH)" -DCMAKE_CXX_COMPILER:PATH="$(MSVC_COMPILER_PATH)" $(REPO_DIR)
call "$(MSVS_VARS_PATH)" && $(CMAKE_CMD) -G "Ninja Multi-Config" -DENABLE_WHEEL=ON -DENABLE_INTEL_GNA=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_INTEL_GPU=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_GAPI_PREPROCESSING=$(CMAKE_BUILD_SHARED_LIBS) -DBUILD_SHARED_LIBS=$(CMAKE_BUILD_SHARED_LIBS) -DENABLE_REQUIREMENTS_INSTALL=OFF -DENABLE_FASTER_BUILD=ON -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DENABLE_TESTS=ON -DENABLE_STRICT_DEPENDENCIES=OFF -DENABLE_PYTHON=ON -DPYTHON_EXECUTABLE="C:\hostedtoolcache\windows\Python\3.7.6\x64\python.exe" -DPYTHON_INCLUDE_DIR="C:\hostedtoolcache\windows\Python\3.7.6\x64\include" -DPYTHON_LIBRARY="C:\hostedtoolcache\windows\Python\3.7.6\x64\libs\python37.lib" -DIE_EXTRA_MODULES=$(OPENVINO_CONTRIB_REPO_DIR)\modules -DCMAKE_C_COMPILER:PATH="$(MSVC_COMPILER_PATH)" -DCMAKE_CXX_COMPILER:PATH="$(MSVC_COMPILER_PATH)" $(REPO_DIR)
workingDirectory: $(BUILD_DIR)
displayName: 'CMake'
@@ -90,7 +90,7 @@ unset(protobuf_installed CACHE)
# [LINK_LIBRARIES <lib1 lib2 ...>])
#
macro(ov_add_frontend)
set(options LINKABLE_FRONTEND PROTOBUF_LITE SKIP_NCC_STYLE SKIP_INSTALL)
set(options LINKABLE_FRONTEND SHUTDOWN_PROTOBUF PROTOBUF_LITE SKIP_NCC_STYLE SKIP_INSTALL)
set(oneValueArgs NAME FILEDESCRIPTION)
set(multiValueArgs LINK_LIBRARIES PROTO_FILES)
cmake_parse_arguments(OV_FRONTEND "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -150,6 +150,11 @@ macro(ov_add_frontend)
add_library(openvino::frontend::${OV_FRONTEND_NAME} ALIAS ${TARGET_NAME})
endif()
# Shutdown protobuf when unloading the front dynamic library
if(ENABLE_SHUTDOWN_PROTOBUF AND OV_FRONTEND_SHUTDOWN_PROTOBUF AND BUILD_SHARED_LIBS)
target_link_libraries(${TARGET_NAME} PRIVATE ov_protobuf_shutdown)
endif()
if(NOT BUILD_SHARED_LIBS)
# override default function names
target_compile_definitions(${TARGET_NAME} PRIVATE
@@ -7,7 +7,7 @@ Namespace: '^([a-z\d_]+|InferenceEngine)$'
NamespaceAlias: '^([a-z\d_]+|InferenceEngine)$'
UnionName: '[A-Z][\w]+$'
TemplateTemplateParameter: '[A-Z][\w]+'
NamespaceReference: '^([a-z\d_]+|InferenceEngine)$'
NamespaceReference: '^([a-z\d_]+|InferenceEngine|GPUContextParams)$'
TemplateNonTypeParameter: '^\w*$'
ClassTemplate: '^([A-Z][\w]+|element_type_traits)$'
TemplateTypeParameter: '^\w*$'
@@ -72,12 +72,12 @@ CxxNullPointerLiteralExpression: '^.*$'
CxxThisExpression: '^.*$'
CxxThrowExpression: '^.*$'
CxxNewExpression: '^.*$'
CxxDeleteExpression: 'XXXX'
CxxDeleteExpression: '^.*$'
CxxUnaryExpression: '^.*$'
PackExpansionExpression: '^.*$'
SizeOfPackExpression: '^.*$'
LambdaExpression: '^.*$'
ObjectBoolLiteralExpression: 'XXXX'
ObjectBoolLiteralExpression: '^.*$'
ObjectSelfExpression: 'XXXX'
UnexposedStatement: 'XXXX'
LabelStatement: 'XXXX'
+2
View File
@@ -154,6 +154,8 @@ ie_option(ENABLE_OV_IR_FRONTEND "Enable IR FrontEnd" ON)
ie_dependent_option(ENABLE_OV_TF_FRONTEND "Enable TensorFlow FrontEnd" ON "protoc_available" OFF)
ie_dependent_option(ENABLE_SYSTEM_PROTOBUF "Use system protobuf" OFF
"ENABLE_OV_ONNX_FRONTEND OR ENABLE_OV_PADDLE_FRONTEND OR ENABLE_OV_TF_FRONTEND;BUILD_SHARED_LIBS" OFF)
ie_dependent_option(ENABLE_SHUTDOWN_PROTOBUF "Shutdown protobuf when unload the frontend shared libraries" ON
"ENABLE_OV_ONNX_FRONTEND OR ENABLE_OV_PADDLE_FRONTEND OR ENABLE_OV_TF_FRONTEND;BUILD_SHARED_LIBS" OFF)
ie_dependent_option(ENABLE_OV_CORE_UNIT_TESTS "Enables OpenVINO core unit tests" ON "ENABLE_TESTS;NOT ANDROID" OFF)
ie_dependent_option(ENABLE_OV_CORE_BACKEND_UNIT_TESTS "Control the building of unit tests using backends" ON
"ENABLE_OV_CORE_UNIT_TESTS" OFF)
@@ -285,7 +285,7 @@ available from the Inference Engine API. For example, the part of performance co
As result all operations (except not quantized `SoftMax` at the end of the model) in OpenVINO™ CPU plugin are inferred in low precision. Note, please, in the result model there are `FakeQuantize` operations in FP32 but the plugin responsibility is fuse these operations with previous operations. OpenVINO™ CPU plugin achieves maximum optimized inference for all operations by fusing INT8 `Convolution` with FP32 output with `FakeQuantize` operation with FP32 input and INT8 output. In this case OpenVINO™ CPU plugin uses INT8 and FP32 vectorized instructions but reports about one INT8 kernel usage for inference, which is the most optimized for this case.
## Mixed precision
If LPT input model operation output has `fp16` precision then dequantization computations still occurs in `fp32` precision. This approach is used to avoid accuracy loss in `fp16` arithmetic computations. Note, the latest dequantization operation output has `fp16` precision.
If LPT input model operation output has `fp16` precision then dequantization computations still occurs in `fp32` precision. This approach is used to avoid accuracy loss in `fp16` arithmetic computations. The ultimate output of the dequantization operation will have the `fp16` precision, as expected.
## Customization
Low Precision Transformations can be customizable. Build-in customization options:
@@ -626,4 +626,12 @@ The issue "SyntaxError: 'yield' inside list comprehension" might occur during co
The following workarounds are suggested to resolve this issue:
1. Use Python 3.6/3.7 to convert MXNet\* models on Windows
2. Update MXNet: pip install mxnet=1.7.0.post2
Note that you might have conflicts between previously installed PyPI dependencies.
Note that you might have conflicts between previously installed PyPI dependencies.m
#### 105. What does the message "The IR preparation was executed by the legacy MO path. ..." mean? <a name="question-105"></a>
For the models in ONNX* format, there are two available paths of IR conversion.
The old one is handled by the old Python* implementation, while the new one uses new C++ frontends.
Starting from the 2022.1 version, the default IR conversion path for ONNX models is processed using the new ONNX frontend.
Certain features, such as `--extensions` and `--transformations_config`, are not yet supported on the new frontends.
The IR conversion falls back to the old path if a user does not select any expected path of conversion explicitly (by `--use_new_frontend` or `--use_legacy_frontend` MO arguments) and unsupported pre-defined scenario is detected on the new frontend path.
@@ -290,6 +290,7 @@ Some TensorFlow\* operations do not match to any Inference Engine layer, but are
| Round | |
| Pow | |
| Rsqrt | |
| ScatterNd | |
| Select | |
| SelectV2 | |
| Shape | |
+46
View File
@@ -16,6 +16,7 @@ var wapSection = 'openvinotoolkit';
})();
$(document).ready(function() {
createVersions();
init_col_sections();
init_switchers();
handleSwitcherParam();
@@ -26,6 +27,51 @@ $(document).ready(function() {
}
});
function getCurrentVersion() {
var protocol = window.location.protocol + "//";
var index = window.location.href.indexOf(protocol);
var link = window.location.href.slice(index + protocol.length).split('/');
var wordAfterDomain = link[1];
if (wordAfterDomain === 'cn') {
wordAfterDomain = link[2];
}
if (["index.html", "404.html", "", "latest"].indexOf(wordAfterDomain) >= 0) {
/*
* If this landing page, 404 or domain.com we should get first version
* */
return versions[0].version;
}
return encodeURI(wordAfterDomain);
}
function createVersions() {
var versions;
var currentVersion = getCurrentVersion()
try {
versions = JSON.parse(data);
}
catch(err) {
console.log(err);
versions = [];
}
var versionBtn = $('#version-selector');
versionBtn.text(currentVersion);
versionBtn.width((currentVersion.length * 10) + 'px');
var versionsContainer = $('[aria-labelledby="version-selector"]');
versions.forEach(item => {
var link = $('<a class="dropdown-item" href="#">' + item.version + '</a>');
if (item.version === currentVersion) {
link.addClass('font-weight-bold');
}
versionsContainer.append(link);
})
var downloadBtn = $('#download-zip-btn');
downloadBtn.attr('href', '/archives/' + currentVersion + '.zip')
}
function addTableSort() {
var tables = $('table.table');
+1 -9
View File
@@ -81,16 +81,8 @@ html_theme_options = {
}
html_context = {
'current_version': 'nightly',
'current_language': 'English',
'languages': (('English', '/latest'), ('Chinese', '/cn/latest')),
'versions': (('Latest', '/latest'), ('nightly', '/nightly'), ('2021.4', '/2021.4'),
('2021.3', '/2021.3'), ('2021.2', '/2021.2'), ('2021.1', '/2021.1'),
('2020.4', '/2020.4'), ('2020.3', '/2020.3'), ('2020.2', '/2020.1'),
('2020.1', '/2020.1'), ('2019_R3.1', '/2019_R3.1'), ('2019_R3', '/2019_R3'),
('2019_R2', '/2019_R2'), ('2019_R1.1', '/2019_R1.1'), ('2019_R1.01', '/2019_R1.01'),
('2019_R1', '/2019_R1'), ('2018_R5', '/2018_R5'),),
'download_docs_url': '/archives/2021.4.zip'
'languages': (('English', '/latest'), ('Chinese', '/cn/latest'))
}
repositories = {
@@ -6,9 +6,7 @@
</button>
<div class="dropdown-menu" aria-labelledby="download-options">
<a class="dropdown-item" href="#" onclick="window.print()">.pdf</a>
{% if download_docs_url %}
<a class="dropdown-item" href="{{download_docs_url}}">.zip</a>
{% endif %}
<a id="download-zip-btn" class="dropdown-item" href="#">.zip</a>
</div>
</div>
</div>
@@ -24,6 +24,7 @@
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-barchart-background@1.3.0/build/Plugin.Barchart.Background.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-deferred@1"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.1/papaparse.min.js"></script>
<script src="/assets/versions_raw.js"></script>
{% endblock %}
{%- block content %}
@@ -1,15 +1,6 @@
{# Add version selector #}
{% if versions and current_version %}
<div class="dropdown sst-dropdown sst-dropdown-navbar">
<button class="btn sst-btn dropdown-toggle" type="button" id="version-selector" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{current_version}}</button>
<button class="btn sst-btn dropdown-toggle" type="button" id="version-selector" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="version-selector">
{% for slug, url in versions%}
{% if slug == current_version %}
<a class="dropdown-item font-weight-bold" href="{{ url }}/{{ pagename }}.html">{{ slug }}</a>
{% else %}
<a class="dropdown-item" href="{{ url }}/{{ pagename }}.html">{{ slug }}</a>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
+534 -1
View File
@@ -78,6 +78,7 @@
#include "backend.hpp"
#include "ngraph/ops.hpp"
#include "ngraph/runtime/reference/convert_color_nv12.hpp"
using namespace ngraph;
using namespace std;
@@ -827,7 +828,6 @@ InfoForNMS5 get_info_for_nms5_eval(const std::shared_ptr<op::v5::NonMaxSuppressi
return result;
}
} // namespace nms_v5
template <element::Type_t ET>
@@ -866,6 +866,519 @@ bool evaluate(const shared_ptr<op::v5::NonMaxSuppression>& op,
return true;
}
namespace nms_v4 {
using V4BoxEncoding = op::v4::NonMaxSuppression::BoxEncodingType;
struct InfoForNMS4 {
int64_t max_output_boxes_per_class;
float iou_threshold;
float score_threshold;
float soft_nms_sigma;
Shape out_shape;
Shape boxes_shape;
Shape scores_shape;
std::vector<float> boxes_data;
std::vector<float> scores_data;
size_t out_shape_size;
bool sort_result_descending;
ngraph::element::Type output_type;
};
constexpr size_t boxes_port = 0;
constexpr size_t scores_port = 1;
PartialShape infer_selected_indices_shape(const std::vector<std::shared_ptr<HostTensor>>& inputs,
int64_t max_output_boxes_per_class) {
const auto boxes_ps = inputs[boxes_port]->get_partial_shape();
const auto scores_ps = inputs[scores_port]->get_partial_shape();
// NonMaxSuppression produces triplets
// that have the following format: [batch_index, class_index, box_index]
PartialShape result = {Dimension::dynamic(), 3};
if (boxes_ps.rank().is_static() && scores_ps.rank().is_static()) {
const auto num_boxes_boxes = boxes_ps[1];
if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static()) {
const auto num_boxes = num_boxes_boxes.get_length();
const auto num_classes = scores_ps[1].get_length();
result[0] = std::min(num_boxes, max_output_boxes_per_class) * num_classes * scores_ps[0].get_length();
}
}
return result;
}
void normalize_corner(float* boxes, const Shape& boxes_shape) {
size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
for (size_t i = 0; i < total_num_of_boxes; ++i) {
float* current_box = boxes + 4 * i;
float y1 = current_box[0];
float x1 = current_box[1];
float y2 = current_box[2];
float x2 = current_box[3];
float ymin = std::min(y1, y2);
float ymax = std::max(y1, y2);
float xmin = std::min(x1, x2);
float xmax = std::max(x1, x2);
current_box[0] = ymin;
current_box[1] = xmin;
current_box[2] = ymax;
current_box[3] = xmax;
}
}
void normalize_center(float* boxes, const Shape& boxes_shape) {
size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
for (size_t i = 0; i < total_num_of_boxes; ++i) {
float* current_box = boxes + 4 * i;
float x_center = current_box[0];
float y_center = current_box[1];
float width = current_box[2];
float height = current_box[3];
float y1 = y_center - height / 2.0;
float x1 = x_center - width / 2.0;
float y2 = y_center + height / 2.0;
float x2 = x_center + width / 2.0;
current_box[0] = y1;
current_box[1] = x1;
current_box[2] = y2;
current_box[3] = x2;
}
}
void normalize_box_encoding(float* boxes, const Shape& boxes_shape, const V4BoxEncoding box_encoding) {
if (box_encoding == V4BoxEncoding::CORNER) {
normalize_corner(boxes, boxes_shape);
} else {
normalize_center(boxes, boxes_shape);
}
}
std::vector<float> prepare_boxes_data(const std::shared_ptr<HostTensor>& boxes,
const Shape& boxes_shape,
const V4BoxEncoding box_encoding) {
auto result = get_floats(boxes, boxes_shape);
normalize_box_encoding(result.data(), boxes_shape, box_encoding);
return result;
}
std::vector<float> prepare_scores_data(const std::shared_ptr<HostTensor>& scores, const Shape& scores_shape) {
auto result = get_floats(scores, scores_shape);
return result;
}
InfoForNMS4 get_info_for_nms4_eval(const std::shared_ptr<op::v4::NonMaxSuppression>& nms4,
const std::vector<std::shared_ptr<HostTensor>>& inputs) {
InfoForNMS4 result;
result.max_output_boxes_per_class = inputs.size() > 2 ? get_integers(inputs[2], Shape({}))[0] : 0;
result.iou_threshold = inputs.size() > 3 ? get_floats(inputs[3], Shape({}))[0] : 0.0f;
result.score_threshold = inputs.size() > 4 ? get_floats(inputs[4], Shape({}))[0] : 0.0f;
result.soft_nms_sigma = inputs.size() > 5 ? get_floats(inputs[5], Shape({}))[0] : 0.0f;
auto selected_indices_shape = infer_selected_indices_shape(inputs, result.max_output_boxes_per_class);
result.out_shape = selected_indices_shape.to_shape();
result.boxes_shape = inputs[boxes_port]->get_shape();
result.scores_shape = inputs[scores_port]->get_shape();
result.boxes_data = prepare_boxes_data(inputs[boxes_port], result.boxes_shape, nms4->get_box_encoding());
result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape);
result.out_shape_size = shape_size(result.out_shape);
result.sort_result_descending = nms4->get_sort_result_descending();
result.output_type = nms4->get_output_type();
return result;
}
} // namespace nms_v4
template <element::Type_t ET>
bool evaluate(const shared_ptr<op::v4::NonMaxSuppression>& op,
const HostTensorVector& outputs,
const HostTensorVector& inputs) {
auto info = nms_v4::get_info_for_nms4_eval(op, inputs);
std::vector<int64_t> selected_indices(info.out_shape_size);
std::vector<float> selected_scores(info.out_shape_size);
int64_t valid_outputs = 0;
runtime::reference::non_max_suppression(info.boxes_data.data(),
info.boxes_shape,
info.scores_data.data(),
info.scores_shape,
info.max_output_boxes_per_class,
info.iou_threshold,
info.score_threshold,
info.soft_nms_sigma,
selected_indices.data(),
info.out_shape,
selected_scores.data(),
info.out_shape,
&valid_outputs,
info.sort_result_descending);
auto selected_scores_type = (inputs.size() < 4) ? element::f32 : inputs[3]->get_element_type();
runtime::reference::nms5_postprocessing(outputs,
info.output_type,
selected_indices,
selected_scores,
valid_outputs,
selected_scores_type);
return true;
}
namespace nms_v3 {
using V3BoxEncoding = op::v3::NonMaxSuppression::BoxEncodingType;
struct InfoForNMS3 {
int64_t max_output_boxes_per_class;
float iou_threshold;
float score_threshold;
float soft_nms_sigma;
Shape out_shape;
Shape boxes_shape;
Shape scores_shape;
std::vector<float> boxes_data;
std::vector<float> scores_data;
size_t out_shape_size;
bool sort_result_descending;
ngraph::element::Type output_type;
};
constexpr size_t boxes_port = 0;
constexpr size_t scores_port = 1;
PartialShape infer_selected_indices_shape(const std::vector<std::shared_ptr<HostTensor>>& inputs,
int64_t max_output_boxes_per_class) {
const auto boxes_ps = inputs[boxes_port]->get_partial_shape();
const auto scores_ps = inputs[scores_port]->get_partial_shape();
// NonMaxSuppression produces triplets
// that have the following format: [batch_index, class_index, box_index]
PartialShape result = {Dimension::dynamic(), 3};
if (boxes_ps.rank().is_static() && scores_ps.rank().is_static()) {
const auto num_boxes_boxes = boxes_ps[1];
if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static()) {
const auto num_boxes = num_boxes_boxes.get_length();
const auto num_classes = scores_ps[1].get_length();
result[0] = std::min(num_boxes, max_output_boxes_per_class * num_classes);
}
}
return result;
}
void normalize_corner(float* boxes, const Shape& boxes_shape) {
size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
for (size_t i = 0; i < total_num_of_boxes; ++i) {
float* current_box = boxes + 4 * i;
float y1 = current_box[0];
float x1 = current_box[1];
float y2 = current_box[2];
float x2 = current_box[3];
float ymin = std::min(y1, y2);
float ymax = std::max(y1, y2);
float xmin = std::min(x1, x2);
float xmax = std::max(x1, x2);
current_box[0] = ymin;
current_box[1] = xmin;
current_box[2] = ymax;
current_box[3] = xmax;
}
}
void normalize_center(float* boxes, const Shape& boxes_shape) {
size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
for (size_t i = 0; i < total_num_of_boxes; ++i) {
float* current_box = boxes + 4 * i;
float x_center = current_box[0];
float y_center = current_box[1];
float width = current_box[2];
float height = current_box[3];
float y1 = y_center - height / 2.0;
float x1 = x_center - width / 2.0;
float y2 = y_center + height / 2.0;
float x2 = x_center + width / 2.0;
current_box[0] = y1;
current_box[1] = x1;
current_box[2] = y2;
current_box[3] = x2;
}
}
void normalize_box_encoding(float* boxes, const Shape& boxes_shape, const V3BoxEncoding box_encoding) {
if (box_encoding == V3BoxEncoding::CORNER) {
normalize_corner(boxes, boxes_shape);
} else {
normalize_center(boxes, boxes_shape);
}
}
std::vector<float> prepare_boxes_data(const std::shared_ptr<HostTensor>& boxes,
const Shape& boxes_shape,
const V3BoxEncoding box_encoding) {
auto result = get_floats(boxes, boxes_shape);
normalize_box_encoding(result.data(), boxes_shape, box_encoding);
return result;
}
std::vector<float> prepare_scores_data(const std::shared_ptr<HostTensor>& scores, const Shape& scores_shape) {
auto result = get_floats(scores, scores_shape);
return result;
}
InfoForNMS3 get_info_for_nms3_eval(const std::shared_ptr<op::v3::NonMaxSuppression>& nms3,
const std::vector<std::shared_ptr<HostTensor>>& inputs) {
InfoForNMS3 result;
result.max_output_boxes_per_class = inputs.size() > 2 ? get_integers(inputs[2], Shape({}))[0] : 0;
result.iou_threshold = inputs.size() > 3 ? get_floats(inputs[3], Shape({}))[0] : 0.0f;
result.score_threshold = inputs.size() > 4 ? get_floats(inputs[4], Shape({}))[0] : 0.0f;
result.soft_nms_sigma = inputs.size() > 5 ? get_floats(inputs[5], Shape({}))[0] : 0.0f;
auto selected_indices_shape = infer_selected_indices_shape(inputs, result.max_output_boxes_per_class);
result.out_shape = selected_indices_shape.to_shape();
result.boxes_shape = inputs[boxes_port]->get_shape();
result.scores_shape = inputs[scores_port]->get_shape();
result.boxes_data = prepare_boxes_data(inputs[boxes_port], result.boxes_shape, nms3->get_box_encoding());
result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape);
result.out_shape_size = shape_size(result.out_shape);
result.sort_result_descending = nms3->get_sort_result_descending();
result.output_type = nms3->get_output_type();
return result;
}
} // namespace nms_v3
template <element::Type_t ET>
bool evaluate(const shared_ptr<op::v3::NonMaxSuppression>& op,
const HostTensorVector& outputs,
const HostTensorVector& inputs) {
auto info = nms_v3::get_info_for_nms3_eval(op, inputs);
std::vector<int64_t> selected_indices(info.out_shape_size);
std::vector<float> selected_scores(info.out_shape_size);
int64_t valid_outputs = 0;
runtime::reference::non_max_suppression(info.boxes_data.data(),
info.boxes_shape,
info.scores_data.data(),
info.scores_shape,
info.max_output_boxes_per_class,
info.iou_threshold,
info.score_threshold,
info.soft_nms_sigma,
selected_indices.data(),
info.out_shape,
selected_scores.data(),
info.out_shape,
&valid_outputs,
info.sort_result_descending);
auto selected_scores_type = (inputs.size() < 4) ? element::f32 : inputs[3]->get_element_type();
runtime::reference::nms5_postprocessing(outputs,
info.output_type,
selected_indices,
selected_scores,
valid_outputs,
selected_scores_type);
return true;
}
namespace nms_v1 {
using V1BoxEncoding = op::v1::NonMaxSuppression::BoxEncodingType;
struct InfoForNMS1 {
int64_t max_output_boxes_per_class;
float iou_threshold;
float score_threshold;
float soft_nms_sigma;
Shape out_shape;
Shape boxes_shape;
Shape scores_shape;
std::vector<float> boxes_data;
std::vector<float> scores_data;
size_t out_shape_size;
bool sort_result_descending;
ngraph::element::Type output_type;
};
constexpr size_t boxes_port = 0;
constexpr size_t scores_port = 1;
PartialShape infer_selected_indices_shape(const std::vector<std::shared_ptr<HostTensor>>& inputs,
int64_t max_output_boxes_per_class) {
const auto boxes_ps = inputs[boxes_port]->get_partial_shape();
const auto scores_ps = inputs[scores_port]->get_partial_shape();
// NonMaxSuppression produces triplets
// that have the following format: [batch_index, class_index, box_index]
PartialShape result = {Dimension::dynamic(), 3};
if (boxes_ps.rank().is_static() && scores_ps.rank().is_static()) {
const auto num_boxes_boxes = boxes_ps[1];
if (num_boxes_boxes.is_static() && scores_ps[0].is_static() && scores_ps[1].is_static()) {
const auto num_boxes = num_boxes_boxes.get_length();
const auto num_classes = scores_ps[1].get_length();
result[0] = std::min(num_boxes, max_output_boxes_per_class * num_classes);
}
}
return result;
}
void normalize_corner(float* boxes, const Shape& boxes_shape) {
size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
for (size_t i = 0; i < total_num_of_boxes; ++i) {
float* current_box = boxes + 4 * i;
float y1 = current_box[0];
float x1 = current_box[1];
float y2 = current_box[2];
float x2 = current_box[3];
float ymin = std::min(y1, y2);
float ymax = std::max(y1, y2);
float xmin = std::min(x1, x2);
float xmax = std::max(x1, x2);
current_box[0] = ymin;
current_box[1] = xmin;
current_box[2] = ymax;
current_box[3] = xmax;
}
}
void normalize_center(float* boxes, const Shape& boxes_shape) {
size_t total_num_of_boxes = shape_size(boxes_shape) / 4;
for (size_t i = 0; i < total_num_of_boxes; ++i) {
float* current_box = boxes + 4 * i;
float x_center = current_box[0];
float y_center = current_box[1];
float width = current_box[2];
float height = current_box[3];
float y1 = y_center - height / 2.0;
float x1 = x_center - width / 2.0;
float y2 = y_center + height / 2.0;
float x2 = x_center + width / 2.0;
current_box[0] = y1;
current_box[1] = x1;
current_box[2] = y2;
current_box[3] = x2;
}
}
void normalize_box_encoding(float* boxes, const Shape& boxes_shape, const V1BoxEncoding box_encoding) {
if (box_encoding == V1BoxEncoding::CORNER) {
normalize_corner(boxes, boxes_shape);
} else {
normalize_center(boxes, boxes_shape);
}
}
std::vector<float> prepare_boxes_data(const std::shared_ptr<HostTensor>& boxes,
const Shape& boxes_shape,
const V1BoxEncoding box_encoding) {
auto result = get_floats(boxes, boxes_shape);
normalize_box_encoding(result.data(), boxes_shape, box_encoding);
return result;
}
std::vector<float> prepare_scores_data(const std::shared_ptr<HostTensor>& scores, const Shape& scores_shape) {
auto result = get_floats(scores, scores_shape);
return result;
}
InfoForNMS1 get_info_for_nms1_eval(const std::shared_ptr<op::v1::NonMaxSuppression>& nms1,
const std::vector<std::shared_ptr<HostTensor>>& inputs) {
InfoForNMS1 result;
result.max_output_boxes_per_class = inputs.size() > 2 ? get_integers(inputs[2], Shape({}))[0] : 0;
result.iou_threshold = inputs.size() > 3 ? get_floats(inputs[3], Shape({}))[0] : 0.0f;
result.score_threshold = inputs.size() > 4 ? get_floats(inputs[4], Shape({}))[0] : 0.0f;
result.soft_nms_sigma = inputs.size() > 5 ? get_floats(inputs[5], Shape({}))[0] : 0.0f;
auto selected_indices_shape = infer_selected_indices_shape(inputs, result.max_output_boxes_per_class);
result.out_shape = selected_indices_shape.to_shape();
result.boxes_shape = inputs[boxes_port]->get_shape();
result.scores_shape = inputs[scores_port]->get_shape();
result.boxes_data = prepare_boxes_data(inputs[boxes_port], result.boxes_shape, nms1->get_box_encoding());
result.scores_data = prepare_scores_data(inputs[scores_port], result.scores_shape);
result.out_shape_size = shape_size(result.out_shape);
result.sort_result_descending = nms1->get_sort_result_descending();
result.output_type = ov::element::i64;
return result;
}
} // namespace nms_v1
template <element::Type_t ET>
bool evaluate(const shared_ptr<op::v1::NonMaxSuppression>& op,
const HostTensorVector& outputs,
const HostTensorVector& inputs) {
auto info = nms_v1::get_info_for_nms1_eval(op, inputs);
std::vector<int64_t> selected_indices(info.out_shape_size);
std::vector<float> selected_scores(info.out_shape_size);
int64_t valid_outputs = 0;
runtime::reference::non_max_suppression(info.boxes_data.data(),
info.boxes_shape,
info.scores_data.data(),
info.scores_shape,
info.max_output_boxes_per_class,
info.iou_threshold,
info.score_threshold,
info.soft_nms_sigma,
selected_indices.data(),
info.out_shape,
selected_scores.data(),
info.out_shape,
&valid_outputs,
info.sort_result_descending);
auto selected_scores_type = (inputs.size() < 4) ? element::f32 : inputs[3]->get_element_type();
runtime::reference::nms5_postprocessing(outputs,
info.output_type,
selected_indices,
selected_scores,
valid_outputs,
selected_scores_type);
return true;
}
namespace matrix_nms_v8 {
using SortResultType = op::v8::MatrixNms::SortResultType;
struct InfoForNMS {
@@ -2761,6 +3274,26 @@ bool evaluate(const shared_ptr<op::v8::Gather>& op, const HostTensorVector& outp
return true;
}
template <ov::element::Type_t ET>
inline bool evaluate(const shared_ptr<op::v8::NV12toRGB>& op,
const HostTensorVector& outputs,
const HostTensorVector& inputs) {
return runtime::reference::color_convert_nv12<ET>(op,
outputs,
inputs,
ov::op::util::ConvertColorNV12Base::ColorConversion::NV12_TO_RGB);
}
template <ov::element::Type_t ET>
inline bool evaluate(const shared_ptr<op::v8::NV12toBGR>& op,
const HostTensorVector& outputs,
const HostTensorVector& inputs) {
return runtime::reference::color_convert_nv12<ET>(op,
outputs,
inputs,
ov::op::util::ConvertColorNV12Base::ColorConversion::NV12_TO_BGR);
}
template <typename T>
bool evaluate_node(std::shared_ptr<Node> node, const HostTensorVector& outputs, const HostTensorVector& inputs) {
auto element_type = node->get_output_element_type(0);
@@ -53,6 +53,7 @@ NGRAPH_OP(LogicalXor, op::v1)
NGRAPH_OP(LogicalNot, op::v1)
NGRAPH_OP(MaxPool, op::v1)
NGRAPH_OP(Mod, op::v1)
NGRAPH_OP(NonMaxSuppression, op::v1)
NGRAPH_OP(OneHot, op::v1)
NGRAPH_OP(Pad, op::v1)
NGRAPH_OP(Split, op::v1)
@@ -66,12 +67,14 @@ NGRAPH_OP(EmbeddingBagPackedSum, ngraph::op::v3)
NGRAPH_OP(ExtractImagePatches, op::v3)
NGRAPH_OP(EmbeddingSegmentsSum, ngraph::op::v3)
NGRAPH_OP(GRUCell, ngraph::op::v3)
NGRAPH_OP(NonMaxSuppression, op::v3)
NGRAPH_OP(NonZero, op::v3)
NGRAPH_OP(ScatterNDUpdate, op::v3)
NGRAPH_OP(ShapeOf, op::v3)
NGRAPH_OP(CTCLoss, op::v4)
NGRAPH_OP(LSTMCell, op::v4)
NGRAPH_OP(NonMaxSuppression, op::v4)
NGRAPH_OP(Proposal, op::v4)
NGRAPH_OP(BatchNormInference, op::v5)
@@ -110,6 +113,8 @@ NGRAPH_OP(DeformableConvolution, ngraph::op::v8)
NGRAPH_OP(If, ngraph::op::v8)
NGRAPH_OP(GatherND, op::v8)
NGRAPH_OP(DetectionOutput, op::v8)
NGRAPH_OP(NV12toRGB, op::v8)
NGRAPH_OP(NV12toBGR, op::v8)
NGRAPH_OP(Sigmoid, op::v0)
NGRAPH_OP(Tanh, op::v0)
File diff suppressed because it is too large. Load diff
@@ -106,6 +106,12 @@ std::vector<std::string> disabledTestPatterns() {
R"(.*ReferenceMulticlassNmsTest.*esiType=i64.*evoType=i64.*)",
// CVS-64096
R"(.*ReferenceNonMaxSuppressionTest.*esiType=i32.*evoType=i32.*)",
// CVS-64081
R"(.*ReferenceNonMaxSuppression4Test.*esiType=i32.*)",
// CVS-64067
R"(.*ReferenceNonMaxSuppression3Test.*esiType=i32.*)",
// CVS-64034
R"(.*ReferenceNonMaxSuppression1Test.*esiType=i32.*)",
// CVS-64102
R"(.*ReferenceExperimentalPGGLayerTest.*iType=bf16.*stride_x=(32|64).*)",
// CVS-72215
@@ -858,6 +858,28 @@ static RefPreprocessParams set_shape_custom_crop() {
return res;
}
static RefPreprocessParams set_shape_with_resize() {
RefPreprocessParams res("set_shape_with_resize");
res.function = []() {
auto f = create_simple_function(element::f32, PartialShape{1, 3, 1, 1});
auto p = PrePostProcessor(f);
p.input().tensor().set_shape({1, 2, 2, 3}).set_layout("NHWC");
p.input().preprocess().resize(ResizeAlgorithm::RESIZE_LINEAR);
p.input().model().set_layout("NCHW");
p.build();
return f;
};
auto input_size = 1 * 2 * 2 * 3;
std::vector<float> input_values(input_size);
std::iota(input_values.begin(), input_values.end(), 0);
res.inputs.emplace_back(element::f32, Shape{1, 2, 2, 3}, std::vector<float> {1, 2, 3,
1, 2, 3,
1, 2, 3,
1, 2, 3});
res.expected.emplace_back(Shape{1, 3, 1, 1}, element::f32, std::vector<float>{ 1, 2, 3});
return res;
}
static RefPreprocessParams postprocess_2_inputs_basic() {
RefPreprocessParams res("postprocess_2_inputs_basic");
res.function = []() {
@@ -1133,6 +1155,7 @@ std::vector<RefPreprocessParams> allPreprocessTests() {
convert_color_i420_to_bgr_three_planes(),
convert_color_i420_single_plane(),
set_shape_custom_crop(),
set_shape_with_resize(),
postprocess_2_inputs_basic(),
post_convert_layout_by_dims(),
post_convert_layout_by_dims_multi(),
+28 -17
View File
@@ -11,6 +11,7 @@
#include <vector>
// clang-format off
#include "openvino/openvino.hpp"
#include "openvino/pass/serialize.hpp"
#include "gna/gna_config.hpp"
@@ -173,10 +174,8 @@ int main(int argc, char* argv[]) {
ov::runtime::Core core;
if (FLAGS_d.find("CPU") != std::string::npos && !FLAGS_l.empty()) {
// CPU (MKLDNN) extensions is loaded as a shared library and passed as a
// pointer to base extension
const auto extension_ptr = std::make_shared<InferenceEngine::Extension>(FLAGS_l);
core.add_extension(extension_ptr);
// CPU (MKLDNN) extensions is loaded as a shared library
core.add_extension(FLAGS_l);
slog::info << "CPU (MKLDNN) extensions is loaded " << FLAGS_l << slog::endl;
}
@@ -193,6 +192,21 @@ int main(int argc, char* argv[]) {
slog::info << "GPU extensions is loaded " << ext << slog::endl;
}
if (FLAGS_hint.empty()) {
for (auto& device : devices) {
std::vector<std::string> supported_config_keys =
core.get_metric(device, METRIC_KEY(SUPPORTED_CONFIG_KEYS));
if (std::find(supported_config_keys.begin(),
supported_config_keys.end(),
CONFIG_KEY(PERFORMANCE_HINT)) != supported_config_keys.end()) {
slog::warn << "-hint default value is determined as" << CONFIG_VALUE(THROUGHPUT)
<< " automatically for " << device
<< " device. For more detailed information look at README." << slog::endl;
FLAGS_hint = CONFIG_VALUE(THROUGHPUT);
}
}
}
slog::info << "OpenVINO: " << ov::get_openvino_version() << slog::endl;
slog::info << "Device info: " << slog::endl;
slog::info << core.get_versions(device_name) << slog::endl;
@@ -517,7 +531,7 @@ int main(int argc, char* argv[]) {
next_step();
auto startTime = Time::now();
std::ifstream modelStream(FLAGS_m);
std::ifstream modelStream(FLAGS_m, std::ios_base::binary | std::ios_base::in);
if (!modelStream.is_open()) {
throw std::runtime_error("Cannot open model file " + FLAGS_m);
}
@@ -562,19 +576,16 @@ int main(int argc, char* argv[]) {
// ----------------- 8. Querying optimal runtime parameters
// -----------------------------------------------------
next_step();
// output of the actual settings that the device selected based on the hint
if (!ov_perf_hint.empty()) {
for (const auto& device : devices) {
std::vector<std::string> supported_config_keys =
core.get_metric(device, METRIC_KEY(SUPPORTED_CONFIG_KEYS));
slog::info << "Device: " << device << slog::endl;
for (const auto& cfg : supported_config_keys) {
try {
slog::info << " {" << cfg << " , " << compiledModel.get_config(cfg).as<std::string>();
} catch (...) {
};
// output of the actual settings that the device selected
for (const auto& device : devices) {
std::vector<std::string> supported_config_keys = core.get_metric(device, METRIC_KEY(SUPPORTED_CONFIG_KEYS));
slog::info << "Device: " << device << slog::endl;
for (const auto& cfg : supported_config_keys) {
try {
slog::info << " {" << cfg << " , " << compiledModel.get_config(cfg).as<std::string>();
slog::info << " }" << slog::endl;
}
} catch (...) {
};
}
}
@@ -13,7 +13,6 @@
#include <string>
#include <vector>
#include "inference_engine.hpp"
#include "openvino/openvino.hpp"
// clang-format on
@@ -31,17 +30,6 @@ void readInputFilesArguments(std::vector<std::string>& files, const std::string&
*/
void parseInputFilesArguments(std::vector<std::string>& files);
void processPrecision(InferenceEngine::CNNNetwork& network,
const std::string& ip,
const std::string& op,
const std::string& iop);
void processLayout(InferenceEngine::CNNNetwork& network,
const std::string& il,
const std::string& ol,
const std::string& iol);
void printInputAndOutputsInfo(const InferenceEngine::CNNNetwork& network);
void printInputAndOutputsInfo(const ov::Model& network);
void configurePrePostProcessing(std::shared_ptr<ov::Model>& function,
@@ -55,7 +43,6 @@ void configurePrePostProcessing(std::shared_ptr<ov::Model>& function,
const std::string& oml,
const std::string& ioml);
//--- API 2.0 -------------------------------------------------------------------------
void printInputAndOutputsInfo(const ov::Model& network);
void printInputAndOutputsInfoShort(const ov::Model& network);
void processPrecision(const ov::Model& network, const std::string& ip, const std::string& op, const std::string& iop);
@@ -17,14 +17,12 @@
#include <limits>
#include <list>
#include <map>
#include <openvino/openvino.hpp>
#include <random>
#include <string>
#include <utility>
#include <vector>
// clang-format off
#include "inference_engine.hpp"
#include "openvino/openvino.hpp"
#include "slog.hpp"
// clang-format on
@@ -124,16 +122,6 @@ inline std::string fileExt(const std::string& filename) {
return filename.substr(pos + 1);
}
inline slog::LogStream& operator<<(slog::LogStream& os, const InferenceEngine::Version& version) {
os << version.description << " version ......... ";
os << IE_VERSION_MAJOR << "." << IE_VERSION_MINOR << "." << IE_VERSION_PATCH << slog::endl;
os << "Build ........... ";
os << version.buildNumber << slog::endl;
return os;
}
inline slog::LogStream& operator<<(slog::LogStream& os, const ov::Version& version) {
os << version.description << " version ......... ";
os << OPENVINO_VERSION_MAJOR << "." << OPENVINO_VERSION_MINOR << "." << OPENVINO_VERSION_PATCH << slog::endl;
@@ -144,16 +132,6 @@ inline slog::LogStream& operator<<(slog::LogStream& os, const ov::Version& versi
return os;
}
inline slog::LogStream& operator<<(slog::LogStream& os,
const std::map<std::string, InferenceEngine::Version>& versions) {
for (auto&& version : versions) {
os << version.first << slog::endl;
os << version.second << slog::endl;
}
return os;
}
inline slog::LogStream& operator<<(slog::LogStream& os, const std::map<std::string, ov::Version>& versions) {
for (auto&& version : versions) {
os << version.first << slog::endl;
@@ -621,49 +599,6 @@ static UNUSED void printPerformanceCounts(const std::map<std::string, ov::runtim
std::cout.flags(fmt);
}
// static UNUSED void printPerformanceCounts(InferenceEngine::InferRequest request,
// std::ostream& stream,
// std::string deviceName,
// bool bshowHeader = true) {
// auto performanceMap = request.GetPerformanceCounts();
// printPerformanceCounts(performanceMap, stream, deviceName, bshowHeader);
//}
inline std::map<std::string, std::string> getMapFullDevicesNames(InferenceEngine::Core& ie,
std::vector<std::string> devices) {
std::map<std::string, std::string> devicesMap;
InferenceEngine::Parameter p;
for (std::string& deviceName : devices) {
if (deviceName != "") {
try {
p = ie.GetMetric(deviceName, METRIC_KEY(FULL_DEVICE_NAME));
devicesMap.insert(std::pair<std::string, std::string>(deviceName, p.as<std::string>()));
} catch (InferenceEngine::Exception&) {
}
}
}
return devicesMap;
}
inline std::string getFullDeviceName(std::map<std::string, std::string>& devicesMap, std::string device) {
std::map<std::string, std::string>::iterator it = devicesMap.find(device);
if (it != devicesMap.end()) {
return it->second;
} else {
return "";
}
}
inline std::string getFullDeviceName(InferenceEngine::Core& ie, std::string device) {
InferenceEngine::Parameter p;
try {
p = ie.GetMetric(device, METRIC_KEY(FULL_DEVICE_NAME));
return p.as<std::string>();
} catch (InferenceEngine::Exception&) {
return "";
}
}
/**
* @brief This class represents an object that is found by an object detection net
*/
@@ -1019,97 +954,6 @@ static UNUSED void addRectangles(unsigned char* data,
}
}
inline std::size_t getTensorWidth(const InferenceEngine::TensorDesc& desc) {
const auto& layout = desc.getLayout();
const auto& dims = desc.getDims();
const auto& size = dims.size();
if ((size >= 2) && (layout == InferenceEngine::Layout::NCHW || layout == InferenceEngine::Layout::NHWC ||
layout == InferenceEngine::Layout::NCDHW || layout == InferenceEngine::Layout::NDHWC ||
layout == InferenceEngine::Layout::OIHW || layout == InferenceEngine::Layout::GOIHW ||
layout == InferenceEngine::Layout::OIDHW || layout == InferenceEngine::Layout::GOIDHW ||
layout == InferenceEngine::Layout::CHW || layout == InferenceEngine::Layout::HW)) {
// Regardless of layout, dimensions are stored in fixed order
return dims.back();
} else {
IE_THROW() << "Tensor does not have width dimension";
}
return 0;
}
inline std::size_t getTensorHeight(const InferenceEngine::TensorDesc& desc) {
const auto& layout = desc.getLayout();
const auto& dims = desc.getDims();
const auto& size = dims.size();
if ((size >= 2) && (layout == InferenceEngine::Layout::NCHW || layout == InferenceEngine::Layout::NHWC ||
layout == InferenceEngine::Layout::NCDHW || layout == InferenceEngine::Layout::NDHWC ||
layout == InferenceEngine::Layout::OIHW || layout == InferenceEngine::Layout::GOIHW ||
layout == InferenceEngine::Layout::OIDHW || layout == InferenceEngine::Layout::GOIDHW ||
layout == InferenceEngine::Layout::CHW || layout == InferenceEngine::Layout::HW)) {
// Regardless of layout, dimensions are stored in fixed order
return dims.at(size - 2);
} else {
IE_THROW() << "Tensor does not have height dimension";
}
return 0;
}
inline std::size_t getTensorChannels(const InferenceEngine::TensorDesc& desc) {
const auto& layout = desc.getLayout();
if (layout == InferenceEngine::Layout::NCHW || layout == InferenceEngine::Layout::NHWC ||
layout == InferenceEngine::Layout::NCDHW || layout == InferenceEngine::Layout::NDHWC ||
layout == InferenceEngine::Layout::C || layout == InferenceEngine::Layout::CHW ||
layout == InferenceEngine::Layout::NC || layout == InferenceEngine::Layout::CN) {
// Regardless of layout, dimensions are stored in fixed order
const auto& dims = desc.getDims();
switch (desc.getLayoutByDims(dims)) {
case InferenceEngine::Layout::C:
return dims.at(0);
case InferenceEngine::Layout::NC:
return dims.at(1);
case InferenceEngine::Layout::CHW:
return dims.at(0);
case InferenceEngine::Layout::NCHW:
return dims.at(1);
case InferenceEngine::Layout::NCDHW:
return dims.at(1);
case InferenceEngine::Layout::SCALAR: // [[fallthrough]]
case InferenceEngine::Layout::BLOCKED: // [[fallthrough]]
default:
IE_THROW() << "Tensor does not have channels dimension";
}
} else {
IE_THROW() << "Tensor does not have channels dimension";
}
return 0;
}
inline std::size_t getTensorBatch(const InferenceEngine::TensorDesc& desc) {
const auto& layout = desc.getLayout();
if (layout == InferenceEngine::Layout::NCHW || layout == InferenceEngine::Layout::NHWC ||
layout == InferenceEngine::Layout::NCDHW || layout == InferenceEngine::Layout::NDHWC ||
layout == InferenceEngine::Layout::NC || layout == InferenceEngine::Layout::CN) {
// Regardless of layout, dimensions are stored in fixed order
const auto& dims = desc.getDims();
switch (desc.getLayoutByDims(dims)) {
case InferenceEngine::Layout::NC:
return dims.at(0);
case InferenceEngine::Layout::NCHW:
return dims.at(0);
case InferenceEngine::Layout::NCDHW:
return dims.at(0);
case InferenceEngine::Layout::CHW: // [[fallthrough]]
case InferenceEngine::Layout::C: // [[fallthrough]]
case InferenceEngine::Layout::SCALAR: // [[fallthrough]]
case InferenceEngine::Layout::BLOCKED: // [[fallthrough]]
default:
IE_THROW() << "Tensor does not have channels dimension";
}
} else {
IE_THROW() << "Tensor does not have channels dimension";
}
return 0;
}
inline void showAvailableDevices() {
ov::runtime::Core core;
std::vector<std::string> devices = core.get_available_devices();
@@ -1132,13 +976,12 @@ inline void showAvailableDevices() {
*/
std::map<std::string, std::string> parseConfig(const std::string& configName, char comment = '#');
//--- API 2.0 --------------------------------------------------------------------------------------
inline std::string getFullDeviceName(ov::runtime::Core& core, std::string device) {
InferenceEngine::Parameter p;
ov::Any p;
try {
p = core.get_metric(device, METRIC_KEY(FULL_DEVICE_NAME));
return p.as<std::string>();
} catch (InferenceEngine::Exception&) {
} catch (ov::Exception&) {
return "";
}
}
@@ -174,29 +174,6 @@ InferenceEngine::Precision getPrecision(const std::string& value) {
return getPrecision(value, supported_precisions);
}
void setPrecisions(const InferenceEngine::CNNNetwork& network, const std::string& iop) {
const auto user_precisions_map = parseArgMap(iop);
auto inputs = network.getInputsInfo();
auto outputs = network.getOutputsInfo();
for (auto&& item : user_precisions_map) {
const auto& layer_name = item.first;
const auto& user_precision = item.second;
const auto input = inputs.find(layer_name);
const auto output = outputs.find(layer_name);
if (input != inputs.end()) {
input->second->setPrecision(getPrecision(user_precision));
} else if (output != outputs.end()) {
output->second->setPrecision(getPrecision(user_precision));
} else {
throw std::logic_error(layer_name + " is not an input neither output");
}
}
}
using supported_type_t = std::unordered_map<std::string, ov::element::Type>;
ov::element::Type getType(std::string value, const supported_type_t& supported_precisions) {
std::transform(value.begin(), value.end(), value.begin(), ::toupper);
@@ -225,29 +202,6 @@ ov::element::Type getType(const std::string& value) {
} // namespace
void processPrecision(InferenceEngine::CNNNetwork& network,
const std::string& ip,
const std::string& op,
const std::string& iop) {
if (!ip.empty()) {
const auto user_precision = getPrecision(ip);
for (auto&& layer : network.getInputsInfo()) {
layer.second->setPrecision(user_precision);
}
}
if (!op.empty()) {
auto user_precision = getPrecision(op);
for (auto&& layer : network.getOutputsInfo()) {
layer.second->setPrecision(user_precision);
}
}
if (!iop.empty()) {
setPrecisions(network, iop);
}
}
namespace {
using supported_layouts_t = std::unordered_map<std::string, InferenceEngine::Layout>;
using matchLayoutToDims_t = std::unordered_map<size_t, size_t>;
@@ -295,79 +249,8 @@ bool isMatchLayoutToDims(InferenceEngine::Layout layout, size_t dimension) {
return dimension == dims->second;
}
void setLayouts(const InferenceEngine::CNNNetwork& network, const std::string iol) {
const auto user_layouts_map = parseArgMap(iol);
auto inputs = network.getInputsInfo();
auto outputs = network.getOutputsInfo();
for (auto&& item : user_layouts_map) {
const auto& layer_name = item.first;
const auto& user_layout = getLayout(item.second);
const auto input = inputs.find(layer_name);
const auto output = outputs.find(layer_name);
if (input != inputs.end()) {
if (!isMatchLayoutToDims(user_layout, input->second->getTensorDesc().getDims().size())) {
throw std::logic_error(item.second + " layout is not applicable to " + layer_name);
}
input->second->setLayout(user_layout);
} else if (output != outputs.end()) {
if (!isMatchLayoutToDims(user_layout, output->second->getTensorDesc().getDims().size())) {
throw std::logic_error(item.second + " layout is not applicable to " + layer_name);
}
output->second->setLayout(user_layout);
} else {
throw std::logic_error(layer_name + " is not an input neither output");
}
}
}
} // namespace
void processLayout(InferenceEngine::CNNNetwork& network,
const std::string& il,
const std::string& ol,
const std::string& iol) {
if (!il.empty()) {
const auto layout = getLayout(il);
for (auto&& layer : network.getInputsInfo()) {
if (isMatchLayoutToDims(layout, layer.second->getTensorDesc().getDims().size())) {
layer.second->setLayout(layout);
}
}
}
if (!ol.empty()) {
const auto layout = getLayout(ol);
for (auto&& layer : network.getOutputsInfo()) {
if (isMatchLayoutToDims(layout, layer.second->getTensorDesc().getDims().size())) {
layer.second->setLayout(layout);
}
}
}
if (!iol.empty()) {
setLayouts(network, iol);
}
}
void printInputAndOutputsInfo(const InferenceEngine::CNNNetwork& network) {
std::cout << "Network inputs:" << std::endl;
for (auto&& layer : network.getInputsInfo()) {
std::cout << " " << layer.first << " : " << layer.second->getPrecision() << " / "
<< layer.second->getLayout() << std::endl;
}
std::cout << "Network outputs:" << std::endl;
for (auto&& layer : network.getOutputsInfo()) {
std::cout << " " << layer.first << " : " << layer.second->getPrecision() << " / "
<< layer.second->getLayout() << std::endl;
}
}
//--- API 2.0 -------------------------------------------------------------------------------------
void printInputAndOutputsInfoShort(const ov::Model& network) {
std::cout << "Network inputs:" << std::endl;
for (auto&& param : network.get_parameters()) {
+2 -5
View File
@@ -2,21 +2,18 @@
// SPDX-License-Identifier: Apache-2.0
//
#include <format_reader_ptr.h>
#include <inference_engine.hpp>
#include <memory>
#include <string>
#include <vector>
// clang-format off
#include "ngraph/ngraph.hpp"
#include "openvino/openvino.hpp"
#include "ngraph/ngraph.hpp"
#include "format_reader_ptr.h"
#include "samples/args_helper.hpp"
#include "samples/common.hpp"
#include "samples/slog.hpp"
#include "format_reader_ptr.h"
// clang-format on
// thickness of a line (in pixels) to be used for bounding boxes
@@ -30,6 +30,7 @@ if sys.platform == "win32":
from openvino.pyopenvino.offline_transformations_pybind import apply_moc_transformations
from openvino.pyopenvino.offline_transformations_pybind import apply_moc_legacy_transformations
from openvino.pyopenvino.offline_transformations_pybind import apply_pot_transformations
from openvino.pyopenvino.offline_transformations_pybind import apply_low_latency_transformation
from openvino.pyopenvino.offline_transformations_pybind import apply_pruning_transformation
@@ -13,6 +13,7 @@
#include <pruning.hpp>
#include <transformations/common_optimizations/compress_float_constants.hpp>
#include <transformations/common_optimizations/mark_precision_sensitive_subgraphs.hpp>
#include <transformations/common_optimizations/moc_legacy_transformations.hpp>
#include <transformations/common_optimizations/moc_transformations.hpp>
#include <transformations/serialize.hpp>
@@ -49,6 +50,16 @@ void regmodule_offline_transformations(py::module m) {
py::arg("function"),
py::arg("cf"));
m_offline_transformations.def(
"apply_moc_legacy_transformations",
[](std::shared_ptr<ov::Model> function, const std::vector<std::string>& params_with_custom_types) {
ov::pass::Manager manager;
manager.register_pass<ov::pass::MOCLegacyTransformations>(params_with_custom_types);
manager.run_passes(function);
},
py::arg("function"),
py::arg("params_with_custom_types"));
m_offline_transformations.def(
"apply_pot_transformations",
[](std::shared_ptr<ov::Model> function, std::string device) {
@@ -78,23 +78,25 @@ void regclass_graph_Output(py::module m, std::string typestring)
)");
output.def("get_shape",
&ov::Output<VT>::get_shape,
py::return_value_policy::copy,
R"(
The shape of the output referred to by this output handle.
Returns
----------
get_shape : Shape
Shape of the output.
Copy of Shape of the output.
)");
output.def("get_partial_shape",
&ov::Output<VT>::get_partial_shape,
py::return_value_policy::copy,
R"(
The partial shape of the output referred to by this output handle.
Returns
----------
get_partial_shape : PartialShape
PartialShape of the output.
Copy of PartialShape of the output.
)");
output.def("get_target_inputs",
&ov::Output<VT>::get_target_inputs,
@@ -137,8 +139,8 @@ void regclass_graph_Output(py::module m, std::string typestring)
output.def_property_readonly("any_name", &ov::Output<VT>::get_any_name);
output.def_property_readonly("names", &ov::Output<VT>::get_names);
output.def_property_readonly("element_type", &ov::Output<VT>::get_element_type);
output.def_property_readonly("shape", &ov::Output<VT>::get_shape);
output.def_property_readonly("partial_shape", &ov::Output<VT>::get_partial_shape);
output.def_property_readonly("shape", &ov::Output<VT>::get_shape, py::return_value_policy::copy);
output.def_property_readonly("partial_shape", &ov::Output<VT>::get_partial_shape, py::return_value_policy::copy);
output.def_property_readonly("target_inputs", &ov::Output<VT>::get_target_inputs);
output.def_property_readonly("tensor", &ov::Output<VT>::get_tensor);
output.def_property_readonly("rt_info",
@@ -196,6 +196,10 @@ void regclass_graph_PartialShape(py::module m) {
return self.size();
});
shape.def("__setitem__", [](ov::PartialShape& self, size_t key, ov::Dimension::value_type d) {
self[key] = d;
});
shape.def("__setitem__", [](ov::PartialShape& self, size_t key, ov::Dimension& d) {
self[key] = d;
});
@@ -269,6 +269,9 @@ static void regclass_graph_InputTensorInfo(py::module m) {
const std::vector<std::string>& sub_names = {}) {
return &me.set_color_format(format, sub_names);
});
info.def("set_memory_type", [](ov::preprocess::InputTensorInfo& me, const std::string& memory_type) {
return &me.set_memory_type(memory_type);
});
}
static void regclass_graph_OutputTensorInfo(py::module m) {
@@ -423,4 +426,14 @@ void regclass_graph_PrePostProcessor(py::module m) {
},
py::arg("output_index"));
proc.def("build", &ov::preprocess::PrePostProcessor::build);
proc.def("__str__", [](const ov::preprocess::PrePostProcessor& self) -> std::string {
std::stringstream ss;
ss << self;
return ss.str();
});
proc.def("__repr__", [](const ov::preprocess::PrePostProcessor& self) -> std::string {
return "<PrePostProcessor: " + py::cast(self).attr("__str__")().cast<std::string>() + ">";
});
}
@@ -22,10 +22,16 @@ void regclass_graph_Shape(py::module m) {
shape.def(py::init<const std::initializer_list<size_t>&>(), py::arg("axis_lengths"));
shape.def(py::init<const std::vector<size_t>&>(), py::arg("axis_lengths"));
shape.def(py::init<const ov::Shape&>(), py::arg("axis_lengths"));
shape.def(
"__eq__",
[](const ov::Shape& a, const ov::Shape& b) {
return a == b;
},
py::is_operator());
shape.def("__len__", [](const ov::Shape& v) {
return v.size();
});
shape.def("__setitem__", [](ov::Shape& self, size_t key, size_t d) {
shape.def("__setitem__", [](ov::Shape& self, size_t key, ov::Dimension::value_type d) {
self[key] = d;
});
shape.def("__setitem__", [](ov::Shape& self, size_t key, ov::Dimension d) {
@@ -5,7 +5,7 @@ import numpy as np
import pytest
import openvino.runtime.opset8 as ops
from openvino.runtime import Model, Tensor, Output, Dimension,\
from openvino.runtime import Core, Model, Tensor, Output, Dimension,\
Layout, Type, PartialShape, Shape, set_batch, get_batch
@@ -349,3 +349,15 @@ def test_reshape_with_names():
for input in model.inputs:
model.reshape({input.any_name: new_shape})
assert input.partial_shape == new_shape
def test_reshape(device):
shape = Shape([1, 10])
param = ops.parameter(shape, dtype=np.float32)
model = Model(ops.relu(param), [param])
ref_shape = model.input().partial_shape
ref_shape[0] = 3
model.reshape(ref_shape)
core = Core()
compiled = core.compile_model(model, device)
assert compiled.input().partial_shape == ref_shape
@@ -220,6 +220,16 @@ def test_partial_shape_equals():
shape = Shape([1, 2, 3])
ps = PartialShape([1, 2, 3])
assert shape == ps
assert shape == ps.to_shape()
def test_input_shape_read_only():
shape = Shape([1, 10])
param = ov.parameter(shape, dtype=np.float32)
model = Model(ov.relu(param), [param])
ref_shape = model.input().shape
ref_shape[0] = Dimension(3)
assert model.input().shape == shape
def test_repr_dynamic_shape():
@@ -232,6 +232,20 @@ def test_ngraph_preprocess_set_shape():
assert np.equal(output, expected_output).all()
def test_ngraph_preprocess_set_memory_type():
shape = [1, 1, 1]
parameter_a = ops.parameter(shape, dtype=np.int32, name="A")
op = ops.relu(parameter_a)
model = op
function = Model(model, [parameter_a], "TestFunction")
p = PrePostProcessor(function)
p.input().tensor().set_memory_type("some_memory_type")
function = p.build()
assert any(key for key in function.input().rt_info if "memory_type" in key)
@pytest.mark.parametrize(
"algorithm, color_format1, color_format2, is_failing",
[(ResizeAlgorithm.RESIZE_LINEAR, ColorFormat.UNDEFINED, ColorFormat.BGR, True),
@@ -431,3 +445,33 @@ def test_ngraph_preprocess_model():
output = computation(input_data, input_data)
assert np.equal(output, expected_output).all()
def test_ngraph_preprocess_dump():
shape = [1, 3, 224, 224]
parameter_a = ops.parameter(shape, dtype=np.float32, name="RGB_input")
model = parameter_a
function = Model(model, [parameter_a], "TestFunction")
p = PrePostProcessor(function)
p.input().tensor()\
.set_layout(ov.Layout("NHWC"))\
.set_element_type(Type.u8)\
.set_spatial_dynamic_shape()
p.input().preprocess()\
.convert_element_type(Type.f32)\
.reverse_channels()\
.mean([1, 2, 3])\
.scale([4, 5, 6])\
.resize(ResizeAlgorithm.RESIZE_LINEAR)
p.input().model().set_layout(ov.Layout("NCHW"))
p_str = str(p)
print(p)
assert "Pre-processing steps (5):" in p_str
assert "convert type (f32):" in p_str
assert "reverse channels:" in p_str
assert "mean (1,2,3):" in p_str
assert "scale (4,5,6):" in p_str
assert "resize to model width/height:" in p_str
assert "Implicit pre-processing steps (1):" in p_str
assert "convert layout " + ov.Layout("NCHW").to_string() in p_str
+1
View File
@@ -69,6 +69,7 @@ add_library(openvino::runtime::dev ALIAS ${TARGET_NAME}_dev)
target_include_directories(${TARGET_NAME}_dev INTERFACE
$<BUILD_INTERFACE:${OpenVINO_SOURCE_DIR}/src/common/transformations/include>
$<BUILD_INTERFACE:${OpenVINO_SOURCE_DIR}/src/core/dev_api>
$<BUILD_INTERFACE:${OpenVINO_SOURCE_DIR}/src/inference/dev_api>
$<BUILD_INTERFACE:${OpenVINO_SOURCE_DIR}/src/common/low_precision_transformations/include>
$<TARGET_PROPERTY:inference_engine_preproc,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -333,6 +333,13 @@ protected:
const bool updatePrecision,
const bool moveSubtract = true) const;
std::shared_ptr<ngraph::Node> moveDequantizationBefore(
TransformationContext& context,
const std::shared_ptr<ngraph::Node>& operation,
const FakeQuantizeDequantization& dequantization,
const bool updatePrecision,
const bool moveSubtract = true) const;
void updateOutput(
TransformationContext &context,
std::shared_ptr<ngraph::Node> lastNode,
@@ -17,6 +17,7 @@ public:
NGRAPH_RTTI_DECLARATION;
MoveFakeQuantize(const Params& params = Params());
bool transform(TransformationContext& context, ngraph::pattern::Matcher &m) override;
bool canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> layer) const override;
bool isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept override;
};
@@ -173,6 +173,16 @@ public:
const bool updatePrecision,
const bool moveSubtract);
static InsertDequantizationResult moveDequantizationBefore(
const std::shared_ptr<ngraph::Node>& operation,
const FakeQuantizeDequantization& dequantization,
const bool updatePrecision,
const bool moveSubtract);
static std::vector<std::vector<std::shared_ptr<ngraph::opset1::Constant>>> split_consts_before_concat(
const std::shared_ptr<ov::Node> concat,
const std::vector<std::shared_ptr<opset1::Constant>> currConstants);
static bool checkConstantValuePrecision(const element::Type expectedPrecision, const std::shared_ptr<Node>& constant);
static size_t getChildInputIndex(const std::shared_ptr<ngraph::Node>& parent, const std::shared_ptr<ngraph::Node>& child);
@@ -29,7 +29,7 @@ public:
const std::vector<float>& outputLowValues,
const std::vector<float>& outputHighValues);
static bool outputLayoutIsSupported(std::shared_ptr<opset1::FakeQuantize> quantize);
static bool outputLayoutIsSupported(std::shared_ptr<opset1::FakeQuantize> quantize, bool isConvertExpected = false);
static void getInputIntervals(
std::shared_ptr<opset1::FakeQuantize> quantize,
@@ -387,6 +387,17 @@ std::shared_ptr<ngraph::Node> LayerTransformation::moveDequantizationAfter(
return result.newOperation;
}
std::shared_ptr<ngraph::Node> LayerTransformation::moveDequantizationBefore(
TransformationContext& context,
const std::shared_ptr<ngraph::Node>& operation,
const FakeQuantizeDequantization& dequantization,
const bool updatePrecision,
const bool moveSubtract) const {
const auto result = ngraph::pass::low_precision::NetworkHelper::moveDequantizationBefore(operation, dequantization, updatePrecision, moveSubtract);
updateOutput(context, result.newOperation, result.lastDequantization);
return result.newOperation;
}
void LayerTransformation::updateOutput(
TransformationContext &context,
std::shared_ptr<ngraph::Node> lastNode,
@@ -275,7 +275,7 @@ bool ngraph::pass::low_precision::LowPrecision::isFunctionQuantized(const std::s
const std::shared_ptr<ngraph::opset1::FakeQuantize> fakeQuantize = ov::as_type_ptr<ngraph::opset1::FakeQuantize>(parent);
if ((fakeQuantize != nullptr) &&
QuantizationDetails::outputLayoutIsSupported(fakeQuantize) &&
QuantizationDetails::outputLayoutIsSupported(fakeQuantize, true) &&
QuantizationDetails::isSupportedLevel(fakeQuantize->get_levels())) {
return true;
}
@@ -8,7 +8,7 @@
#include <ngraph/opsets/opset1.hpp>
#include <memory>
#include <ngraph/ngraph.hpp>
#include <ngraph/node.hpp>
#include <ngraph/opsets/opset1.hpp>
#include <ngraph/pattern/op/or.hpp>
@@ -39,26 +39,12 @@ MoveFakeQuantize::MoveFakeQuantize(const Params& params) : LayerTransformation(p
output_low,
output_high });
ngraph::graph_rewrite_callback callback = [=](pattern::Matcher& m) {
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
auto op = m.get_match_root();
if (transformation_callback(op)) {
return false;
}
// workaround: only per-tensor quantization is allowed
const auto& pattern_map = m.get_pattern_value_map();
const auto is_scalar = [&](const std::shared_ptr<ngraph::Node>& wrapped_constant) {
return NetworkHelper::isScalarLike(
as_type_ptr<opset1::Constant>(pattern_map.at(wrapped_constant).get_node_shared_ptr()));
};
if (!is_scalar(input_low) ||
!is_scalar(input_high) ||
!is_scalar(output_low) ||
!is_scalar(output_high)) {
return false;
}
return transform(*context, m);
};
@@ -70,49 +56,111 @@ MoveFakeQuantize::MoveFakeQuantize(const Params& params) : LayerTransformation(p
bool MoveFakeQuantize::transform(TransformationContext& context, ngraph::pattern::Matcher& m) {
auto fq = m.get_match_root();
if (!canBeTransformed(context, fq)) {
return false;
}
auto operation = fq->get_input_node_shared_ptr(0);
std::shared_ptr<ngraph::Node> concat;
bool only_concat = true;
std::string fq_original_name = fq->get_friendly_name(), operation_original_name;
bool without_operation = true;
std::string fq_original_name = fq->get_friendly_name(),
operation_original_name,
convert_q_original_name;
if (is_type<opset1::Concat>(operation)) {
concat = operation;
} else {
operation_original_name = operation->get_friendly_name();
concat = operation->get_input_node_shared_ptr(0);
only_concat = false;
without_operation = false;
}
if (!ConcatTransformation::isQuantizedStatic(concat)) {
return false;
}
std::vector<std::shared_ptr<ngraph::Node>> fqs;
size_t input_size = concat->get_input_size();
for (size_t i{ 0 }; i < input_size; ++i) {
auto convert_q = (*fq->output(0).get_target_inputs().begin()).get_node()->shared_from_this();
bool q_dq = is_type<opset1::Convert>(convert_q);
std::vector<std::shared_ptr<opset1::Constant>> currConstants(4);
bool multi_chanels = false;
const auto number_of_concat_inputs = concat->get_input_size();
const auto concatNode = as_type_ptr<opset1::Concat>(concat);
const auto concat_axis = concatNode->get_concatenation_axis();
for (size_t i = 0; i < 4; i++) {
currConstants[i] = as_type_ptr<opset1::Constant>(fq->get_input_node_shared_ptr(i + 1));
if (!multi_chanels && currConstants[i]->get_shape().size() > 1 && currConstants[i]->get_shape()[concat_axis] != 1) {
multi_chanels = true;
}
}
std::vector<std::vector<std::shared_ptr<ngraph::opset1::Constant>>> newConstants;
if (multi_chanels) {
newConstants = NetworkHelper::split_consts_before_concat(concat, currConstants);
}
std::vector<std::shared_ptr<ngraph::Node>> newNodes;
for (size_t i{ 0 }; i < number_of_concat_inputs; ++i) {
std::shared_ptr<ngraph::Node> fq_input;
if (only_concat) {
if (without_operation) {
fq_input = concat->get_input_node_shared_ptr(i);
} else {
auto input = concat->get_input_node_shared_ptr(i);
fq_input = operation->clone_with_new_inputs({ input });
fq_input->set_friendly_name(operation_original_name + "_" + std::to_string(i + 1));
}
auto newFq = fq->clone_with_new_inputs({ fq_input,
fq->get_input_node_shared_ptr(1)->clone_with_new_inputs({}),
fq->get_input_node_shared_ptr(2)->clone_with_new_inputs({}),
fq->get_input_node_shared_ptr(3)->clone_with_new_inputs({}),
fq->get_input_node_shared_ptr(4)->clone_with_new_inputs({}) });
std::shared_ptr<ngraph::Node> newFq;
if (multi_chanels) {
newFq = fq->clone_with_new_inputs({ fq_input,
newConstants[0][newConstants[0].size() == 1 ? 0 : i],
newConstants[1][newConstants[1].size() == 1 ? 0 : i],
newConstants[2][newConstants[2].size() == 1 ? 0 : i],
newConstants[3][newConstants[3].size() == 1 ? 0 : i] });
} else {
newFq = fq->clone_with_new_inputs({ fq_input,
fq->get_input_node_ptr(1)->clone_with_new_inputs({}),
fq->get_input_node_ptr(2)->clone_with_new_inputs({}),
fq->get_input_node_ptr(3)->clone_with_new_inputs({}),
fq->get_input_node_ptr(4)->clone_with_new_inputs({}) });
}
ngraph::copy_runtime_info(fq, newFq);
newFq->set_friendly_name(fq_original_name + "_" + std::to_string(i + 1));
fqs.push_back(newFq);
if (q_dq) {
auto newConvert_q = convert_q->clone_with_new_inputs({ newFq });
ngraph::copy_runtime_info(convert_q, newConvert_q);
newConvert_q->set_friendly_name(convert_q->get_friendly_name() + "_" + std::to_string(i + 1));
newNodes.push_back(newConvert_q);
} else {
newNodes.push_back(newFq);
}
}
ngraph::copy_runtime_info(fq, fqs);
auto newConcat = concat->clone_with_new_inputs(ngraph::OutputVector(fqs.begin(), fqs.end()));
auto newConcat = concat->clone_with_new_inputs(ngraph::OutputVector(newNodes.begin(), newNodes.end()));
newConcat->set_friendly_name(concat->get_friendly_name());
replace_node(fq, newConcat);
NetworkHelper::copyInfo(concat, newConcat);
if (q_dq) {
auto dq = NetworkHelper::getDequantizationBelow(convert_q);
moveDequantizationBefore(context, newConcat, dq, false);
return true;
}
replace_node(fq, newConcat);
updateOutput(context, newConcat, fq);
return true;
}
bool MoveFakeQuantize::isPrecisionPreserved(std::shared_ptr<Node> layer) const noexcept {
bool MoveFakeQuantize::canBeTransformed(const TransformationContext& context, std::shared_ptr<Node> layer) const {
auto operation = layer->get_input_node_shared_ptr(0);
std::shared_ptr<ngraph::Node> concat;
if (is_type<opset1::Concat>(operation)) {
concat = operation;
} else {
concat = operation->get_input_node_shared_ptr(0);
}
if (!ConcatTransformation::isQuantizedStatic(concat)) {
return false;
}
auto convert_q = (*layer->output(0).get_target_inputs().begin()).get_node()->shared_from_this();
bool q_dq = is_type<opset1::Convert>(convert_q);
if (q_dq && (convert_q->get_output_size() != 1 || layer->get_output_size() != 1)) {
return false;
}
return true;
}
bool MoveFakeQuantize::isPrecisionPreserved(std::shared_ptr<Node>) const noexcept {
return true;
}
@@ -1662,6 +1662,144 @@ NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationAfter
return InsertDequantizationResult(newOperation, parent);
}
NetworkHelper::InsertDequantizationResult NetworkHelper::moveDequantizationBefore(
const std::shared_ptr<ngraph::Node>& operation,
const FakeQuantizeDequantization& dequantization,
const bool updatePrecision,
const bool moveSubtract) {
assert(
(NetworkHelper::getDequantizationBelow(operation).subtractConstant == nullptr) ||
(NetworkHelper::getDequantizationBelow(operation).subtractConstant.get() == dequantization.subtractConstant.get()));
assert(
(NetworkHelper::getDequantizationBelow(operation).multiplyConstant == nullptr) ||
(NetworkHelper::getDequantizationBelow(operation).multiplyConstant.get() == dequantization.multiplyConstant.get()));
std::vector<std::vector<std::shared_ptr<ngraph::opset1::Constant>>> multiplyConstants, subtractConstants;
if (is_type<opset1::Concat>(operation)) {
const auto concatNode = as_type_ptr<opset1::Concat>(operation);
auto axis = concatNode->get_concatenation_axis();
if (dequantization.multiply && dequantization.multiplyConstant->get_shape().size() > 1 && dequantization.multiplyConstant->get_shape()[axis] != 1) {
multiplyConstants = NetworkHelper::split_consts_before_concat(operation, { dequantization.multiplyConstant });
}
if (dequantization.subtract && dequantization.subtractConstant->get_shape().size() > 1 && dequantization.subtractConstant->get_shape()[axis] != 1) {
subtractConstants = NetworkHelper::split_consts_before_concat(operation, { dequantization.subtractConstant });
}
}
std::vector<std::shared_ptr<ngraph::Node>> newNodes;
for (size_t i = 0; i < operation->get_input_size(); ++i) {
auto parent = operation->get_input_node_shared_ptr(i);
const element::Type deqPrecision = dequantization.multiplyConstant->get_element_type();
const bool shouldConvert = (operation->get_output_element_type(0) != deqPrecision);
if (shouldConvert) {
const auto convertOutputPrecision = dequantization.convert != nullptr ?
dequantization.convert->get_output_element_type(0) :
deqPrecision;
parent = std::make_shared<opset1::Convert>(parent, convertOutputPrecision);
parent->set_friendly_name(dequantization.convert->get_friendly_name() + "_" + std::to_string(i + 1));
ngraph::copy_runtime_info(dequantization.convert, parent);
}
if (moveSubtract && (dequantization.subtract != nullptr)) {
if (dequantization.subtractConvert == nullptr) {
const element::Type parentPrecision = parent->get_output_element_type(0);
if (parentPrecision.bitwidth() < dequantization.subtractConstant->get_element_type().bitwidth()) {
THROW_IE_LPT_EXCEPTION(*parent) <<
"unexpected precisions: on data " << parent->get_friendly_name() << ":" << parentPrecision <<
", subtract dequantization constant " << dequantization.subtractConstant->get_friendly_name() << ":" <<
dequantization.subtractConstant->get_element_type();
}
auto subtractConstant = subtractConstants.size() ? subtractConstants[0][i] : dequantization.subtractConstant;
parent = std::make_shared<op::TypeRelaxed<opset1::Subtract>>(
std::vector<element::Type>{element::f32, element::f32}, std::vector<element::Type>{ element::f32 },
ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
ngraph::op::TemporaryReplaceOutputType(
subtractConstant->output(0).get_element_type() == parentPrecision ?
subtractConstant :
foldConvert(subtractConstant, parentPrecision), element::f32).get());
parent->set_friendly_name(dequantization.subtract->get_friendly_name() + "_" + std::to_string(i + 1));
} else {
parent = std::make_shared<opset1::Subtract>(parent, dequantization.subtractConvert);
}
ngraph::copy_runtime_info(dequantization.subtract, parent);
}
if (dequantization.multiply != nullptr) {
auto multiplyConstant = multiplyConstants.size() ? multiplyConstants[0][i] : dequantization.multiplyConstant;
const element::Type parentPrecision = parent->get_output_element_type(0);
if (parentPrecision.bitwidth() < multiplyConstant->get_element_type().bitwidth()) {
THROW_IE_LPT_EXCEPTION(*parent) <<
"unexpected precisions: on data " << parent->get_friendly_name() << ":" << parentPrecision <<
", multiply dequantization constant " << multiplyConstant->get_friendly_name() << ":" << multiplyConstant->get_element_type();
}
parent = std::make_shared<op::TypeRelaxed<opset1::Multiply>>(
opset1::Multiply(parent,
multiplyConstant->output(0).get_element_type() == parentPrecision ?
multiplyConstant :
foldConvert(multiplyConstant->output(0), parentPrecision)),
dequantization.multiply->get_output_element_type(0));
ngraph::copy_runtime_info(dequantization.multiply, parent);
parent->set_friendly_name(dequantization.multiply->get_friendly_name() + "_" + std::to_string(i + 1));
}
if ((!moveSubtract) && (dequantization.convert != nullptr) && (dequantization.subtract != nullptr)) {
// issue #43088
// NetworkHelper::optimizeElementwise(dequantization.subtract);
}
newNodes.push_back(parent);
}
auto newOperation = operation->clone_with_new_inputs(ngraph::OutputVector(newNodes.begin(), newNodes.end()));
NetworkHelper::copyInfo(operation, newOperation);
replace_node(dequantization.multiply, newOperation);
auto op = std::dynamic_pointer_cast<ngraph::op::TypeRelaxedBase>(newOperation);
if (op != nullptr) {
if (updatePrecision) {
op->set_overridden_output_type(newOperation->get_input_element_type(0));
} else if (dequantization.multiply) {
op->set_overridden_output_type(dequantization.multiplyConstant->get_element_type());
} else if (dequantization.subtract) {
op->set_overridden_output_type(dequantization.subtractConstant->get_element_type());
}
std::dynamic_pointer_cast<ngraph::Node>(newOperation)->validate_and_infer_types();
}
return InsertDequantizationResult(newOperation, dequantization.multiply);
}
std::vector<std::vector<std::shared_ptr<ngraph::opset1::Constant>>> NetworkHelper::split_consts_before_concat(const std::shared_ptr<ov::Node> concat,
const std::vector<std::shared_ptr<opset1::Constant>> currConstants) {
std::vector<std::vector<std::shared_ptr<ngraph::opset1::Constant>>> newConstants(currConstants.size());
auto number_of_concat_inputs = concat->get_input_size();
const auto concatNode = as_type_ptr<opset1::Concat>(concat);
const auto concat_axis = concatNode->get_concatenation_axis();
std::vector<unsigned int> shape_axis(number_of_concat_inputs);
for (size_t i{ 0 }; i < number_of_concat_inputs; ++i) {
auto shape = concat->get_input_shape(i);
shape_axis[i] = shape[concat_axis];
}
for (size_t i = 0; i < currConstants.size(); ++i) {
std::vector<std::shared_ptr<ngraph::opset1::Constant>> newConstant;
if (currConstants[i]->output(0).get_shape()[concat_axis] == 1) {
newConstant.push_back(currConstants[i]);
newConstants[i] = newConstant;
continue;
}
auto split = std::make_shared<opset1::VariadicSplit>(currConstants[i],
opset1::Constant::create(element::i64, Shape{}, { concat_axis }),
opset1::Constant::create(element::i64, Shape{ number_of_concat_inputs }, shape_axis));
OutputVector outputResults(split->get_output_size());
auto foldResult = split->constant_fold(outputResults, split->input_values());
if (!foldResult) {
// handle potential constant fold issue here
}
for (auto outputResult : outputResults) {
auto constant = as_type_ptr<opset1::Constant>(outputResult.get_node_shared_ptr());
newConstant.push_back(constant);
}
newConstants[i] = newConstant;
}
return newConstants;
}
bool NetworkHelper::checkConstantValuePrecision(const element::Type expectedPrecision, const std::shared_ptr<Node>& constant) {
if (expectedPrecision.is_signed()) {
return true;
@@ -49,11 +49,19 @@ QuantizationDetails::QuantizationDetails(const size_t levels, const std::vector<
outputLowValues(outputLowValues),
outputHighValues(outputHighValues) {}
bool QuantizationDetails::outputLayoutIsSupported(std::shared_ptr<opset1::FakeQuantize> quantize) {
return ov::is_type<opset1::Constant>(quantize->get_input_node_ptr(1)) &&
ov::is_type<opset1::Constant>(quantize->get_input_node_ptr(2)) &&
ov::is_type<opset1::Constant>(quantize->get_input_node_ptr(3)) &&
ov::is_type<opset1::Constant>(quantize->get_input_node_ptr(4));
bool QuantizationDetails::outputLayoutIsSupported(std::shared_ptr<opset1::FakeQuantize> quantize, bool isConvertExpected) {
const auto inputs = quantize->inputs();
for (size_t i = 1; i < inputs.size(); ++i) {
const auto node = inputs[i].get_source_output().get_node_shared_ptr();
bool supported = ov::is_type<opset1::Constant>(node);
if (!supported && isConvertExpected) {
supported = ov::is_type<op::Convert>(node) && ov::is_type<opset1::Constant>(node->get_input_node_ptr(0));
}
if (!supported) {
return false;
}
}
return true;
}
void QuantizationDetails::getInputIntervals(
@@ -28,10 +28,6 @@ target_include_directories(${TARGET_NAME} PUBLIC ${PUBLIC_HEADERS_DIR}
add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME})
# Add include path to so_extension.hpp
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/json_extension/json_config.cpp
PROPERTIES INCLUDE_DIRECTORIES "${OpenVINO_SOURCE_DIR}/src/core/src/")
# developer package
openvino_developer_export_targets(COMPONENT core TARGETS ${TARGET_NAME})
@@ -1,24 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/ngraph.hpp>
#include <ngraph/pass/pass.hpp>
#include <transformations_visibility.hpp>
namespace ngraph {
namespace pass {
class TRANSFORMATIONS_API AlgebraicSimplification;
} // namespace pass
} // namespace ngraph
class ngraph::pass::AlgebraicSimplification : public GraphRewrite {
public:
NGRAPH_RTTI_DECLARATION;
AlgebraicSimplification() = default;
};
@@ -0,0 +1,33 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <string>
#include <vector>
#include "openvino/pass/pass.hpp"
#include "transformations_visibility.hpp"
namespace ov {
namespace pass {
class TRANSFORMATIONS_API ChangePlaceholderTypes;
/**
* @brief Add OldApiMap with legacy type for Parameter node
*/
class ChangePlaceholderTypes : public ModelPass {
public:
OPENVINO_RTTI("ChangePlaceholderTypes", "0");
explicit ChangePlaceholderTypes(const std::vector<std::string>& params_with_custom_types)
: m_params_with_custom_types(params_with_custom_types) {}
bool run_on_model(const std::shared_ptr<ov::Model>& model) override;
private:
std::vector<std::string> m_params_with_custom_types;
};
} // namespace pass
} // namespace ov
@@ -0,0 +1,28 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/pass/pass.hpp"
#include "transformations_visibility.hpp"
namespace ov {
namespace pass {
class TRANSFORMATIONS_API MarkPrecisionSensitiveDivides;
} // namespace pass
} // namespace ov
/**
* @ingroup ie_transformation_common_api
* @brief MarkPrecisionSensitiveDivides transformation marks the Divide fp16 layers
* inside the subgraph starting from precision-sensitive input and ending at
* the ShapeOf node as disabled for ConvertDivide transformation.
*/
class ov::pass::MarkPrecisionSensitiveDivides : public ModelPass {
public:
OPENVINO_RTTI("MarkPrecisionSensitiveDivides", "0");
bool run_on_model(const std::shared_ptr<ov::Model>& m) override;
};
@@ -0,0 +1,45 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <string>
#include <vector>
#include "openvino/pass/pass.hpp"
#include "transformations_visibility.hpp"
namespace ov {
namespace pass {
class TRANSFORMATIONS_API MOCLegacyTransformations;
} // namespace pass
} // namespace ov
namespace ov {
namespace pass {
/**
* @brief This transformation is an entry point for nGraph transformations that
* will be applied inside MOC. This transformations container is filled with
* legacy transformations to reach parity between legacy front-ends and new
* frontends calling from the Model Optimizer. It contains transformations to
* avoid limitations of OpenVINO 1.X API such as unsupported INT64 for inputs,
* usage of NCHW layout that is critical for TensorFlow models.
*/
class MOCLegacyTransformations : public ModelPass {
public:
OPENVINO_RTTI("MOCLegacyTransformations", "0");
explicit MOCLegacyTransformations(const std::vector<std::string>& params_with_custom_types)
: m_params_with_custom_types(params_with_custom_types) {}
bool run_on_model(const std::shared_ptr<ov::Model>& f) override;
private:
std::vector<std::string> m_params_with_custom_types;
};
} // namespace pass
} // namespace ov
@@ -0,0 +1,34 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/core/node.hpp"
#include "openvino/core/runtime_attribute.hpp"
#include "transformations_visibility.hpp"
namespace ov {
TRANSFORMATIONS_API void disable_divide_conversion(const std::shared_ptr<Node>& node);
TRANSFORMATIONS_API void enable_divide_conversion(const std::shared_ptr<Node>& node);
TRANSFORMATIONS_API bool divide_is_nonconvertible(const std::shared_ptr<Node>& node);
/**
* @ingroup ie_runtime_attr_api
* @brief NonconvertibleDivide class represents runtime info attribute that marks
* a Divide as prohibitted to transform it to power.
*/
class TRANSFORMATIONS_API NonconvertibleDivide : public RuntimeAttribute {
public:
OPENVINO_RTTI("nonconvertable_divide", "0");
NonconvertibleDivide() = default;
bool is_copyable() const override { return false; }
};
} // namespace ov
@@ -62,7 +62,7 @@ inline OldApiMapElementType get_old_api_map_element_type(const std::shared_ptr<N
return rt_map.at(OldApiMapElementType::get_type_info_static()).as<OldApiMapElementType>();
}
inline void set_old_api_map_element_type(std::shared_ptr<Node>& node, const OldApiMapElementType& old_api_map) {
inline void set_old_api_map_element_type(const std::shared_ptr<Node>& node, const OldApiMapElementType& old_api_map) {
auto& rt_map = node->get_rt_info();
rt_map[OldApiMapElementType::get_type_info_static()] = old_api_map;
}
@@ -180,6 +180,10 @@ TRANSFORMATIONS_API std::shared_ptr<Node> clone_try_fold(const std::shared_ptr<N
TRANSFORMATIONS_API bool shapes_equal_except_dynamic_expected_batch(const ngraph::PartialShape& expected, const ngraph::PartialShape& actual);
TRANSFORMATIONS_API void visit_shape_path(const std::shared_ptr<ov::Node>& node,
std::unordered_set<std::shared_ptr<ov::Node>>& visited,
std::function<void(std::shared_ptr<ov::Node>)> func);
template <typename T, typename... Args>
std::shared_ptr<Node> make_try_fold(Args&&... args) {
auto unary_output_node = std::make_shared<T>(std::forward<Args>(args)...);
@@ -1,7 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/common_optimizations/algebraic_simplification.hpp"
NGRAPH_RTTI_DEFINITION(ngraph::pass::AlgebraicSimplification, "AlgebraicSimplification", 0);
@@ -0,0 +1,61 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/common_optimizations/change_placeholder_types.hpp"
#include <algorithm>
#include <memory>
#include <numeric>
#include "ngraph/node.hpp"
#include "ngraph/opsets/opset8.hpp"
#include "transformations/rt_info/old_api_map_element_type_attribute.hpp"
using namespace std;
using namespace ngraph;
namespace {
bool is_node_casts_to_float_or_shapeof(const Node* node) {
if (dynamic_cast<const opset8::ShapeOf*>(node)) {
return true;
}
auto convert = dynamic_cast<const opset8::Convert*>(node);
if (convert && convert->get_destination_type() == element::f32) {
return true;
}
return false;
}
} // namespace
bool ov::pass::ChangePlaceholderTypes::run_on_model(const shared_ptr<ov::Model>& f) {
for (auto& param : f->get_parameters()) {
// do not set legacy type if an user defines own type
auto& param_name = param->get_friendly_name();
if (std::find(m_params_with_custom_types.begin(), m_params_with_custom_types.end(), param_name) !=
m_params_with_custom_types.end())
continue;
element::Type legacy_type = element::undefined;
bool all_castable_or_shapeof = true;
for (const auto& target_input : param->get_output_target_inputs(0)) {
all_castable_or_shapeof &= is_node_casts_to_float_or_shapeof(target_input.get_node());
}
if (all_castable_or_shapeof) {
legacy_type = element::f32;
}
if (param->get_element_type() == element::i64) {
legacy_type = element::i32;
} else if (param->get_element_type() == element::u8) {
legacy_type = element::f32;
}
// set OldApiMapElementType only if legacy_type is defined
if (legacy_type != element::undefined) {
set_old_api_map_element_type(param, ov::OldApiMapElementType(legacy_type));
}
}
return true;
}
@@ -53,6 +53,7 @@
#include "transformations/common_optimizations/convert_compression_only_to_legacy.hpp"
#include <transformations/common_optimizations/transpose_reshape_elimination_for_matmul.hpp>
#include "transformations/common_optimizations/matmul_multiply_fusion.hpp"
#include "transformations/common_optimizations/mark_precision_sensitive_divides.hpp"
#include "transformations/op_conversions/bidirectional_sequences_decomposition.hpp"
#include "transformations/op_conversions/convert_pad_to_group_conv.hpp"
#include "transformations/op_conversions/convert_divide.hpp"
@@ -117,6 +118,8 @@ bool ngraph::pass::CommonOptimizations::run_on_model(const std::shared_ptr<ngrap
// after support for FP16 IR is implemented
manager.register_pass<ov::pass::ConvertCompressedOnlyToLegacy>();
manager.register_pass<ov::pass::MarkPrecisionSensitiveDivides>();
// TODO: move to KMB
manager.register_pass<ngraph::pass::WeightsDequantizeToFakeQuantize>();
@@ -0,0 +1,47 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/common_optimizations/mark_precision_sensitive_divides.hpp"
#include <memory>
#include <vector>
#include "openvino/op/util/precision_sensitive_attribute.hpp"
#include "openvino/opsets/opset8.hpp"
#include "transformations/rt_info/nonconvertible_divide.hpp"
#include "transformations/utils/utils.hpp"
bool ov::pass::MarkPrecisionSensitiveDivides::run_on_model(const std::shared_ptr<ov::Model>& m) {
std::deque<std::shared_ptr<Node>> nodes;
std::unordered_set<std::shared_ptr<Node>> visited;
for (auto& r : m->get_results())
nodes.push_back(r);
for (auto& r : m->get_sinks())
nodes.emplace_back(r);
auto markup_func = [](std::shared_ptr<Node> node) {
if (ov::is_type<ov::opset8::Divide>(node) && node->get_output_element_type(0) == ngraph::element::f16) {
ov::disable_divide_conversion(node);
}
};
while (!nodes.empty()) {
auto curr_node = nodes.front();
nodes.pop_front();
if (visited.count(curr_node))
continue;
for (auto& input : curr_node->inputs()) {
if (ov::is_precision_sensitive(input))
ngraph::op::util::visit_shape_path(input.get_source_output().get_node_shared_ptr(), visited, markup_func);
}
visited.insert(curr_node);
for (auto& input_value : curr_node->input_values()) {
// continue searching
const auto& input_node = input_value.get_node_shared_ptr();
nodes.push_front(input_node);
}
}
return true;
}
@@ -17,33 +17,6 @@
using namespace std;
namespace {
void visit_shape_path(const shared_ptr<ov::Node>& node, unordered_set<shared_ptr<ov::Node>>& visited) {
if (!node)
return;
visited.insert(node);
deque<shared_ptr<ov::Node>> nodes{node};
while (!nodes.empty()) {
auto curr_node = nodes.front();
nodes.pop_front();
// Do not check if already visited
if (ov::is_type<ov::opset1::ShapeOf>(curr_node) || ov::is_type<ov::opset3::ShapeOf>(curr_node)) {
continue;
}
visited.insert(curr_node);
if (ov::is_type<ov::opset8::Constant>(curr_node)) {
ov::disable_fp16_compression(curr_node);
} else {
for (auto& input_value : curr_node->input_values()) {
// continue searching
const auto& input_node = input_value.get_node_shared_ptr();
nodes.push_front(input_node);
}
}
}
}
} // namespace
bool ov::pass::MarkPrecisionSensitiveSubgraphs::run_on_model(const std::shared_ptr<ov::Model>& f) {
deque<shared_ptr<Node>> nodes;
unordered_set<shared_ptr<Node>> visited;
@@ -52,6 +25,12 @@ bool ov::pass::MarkPrecisionSensitiveSubgraphs::run_on_model(const std::shared_p
for (auto& r : f->get_sinks())
nodes.emplace_back(r);
auto markup_func = [](shared_ptr<Node> node) {
if (ov::is_type<ov::opset8::Constant>(node)) {
ov::disable_fp16_compression(node);
}
};
while (!nodes.empty()) {
auto curr_node = nodes.front();
nodes.pop_front();
@@ -59,7 +38,7 @@ bool ov::pass::MarkPrecisionSensitiveSubgraphs::run_on_model(const std::shared_p
continue;
for (auto& input : curr_node->inputs()) {
if (ov::is_precision_sensitive(input))
visit_shape_path(input.get_source_output().get_node_shared_ptr(), visited);
ngraph::op::util::visit_shape_path(input.get_source_output().get_node_shared_ptr(), visited, markup_func);
}
visited.insert(curr_node);
@@ -0,0 +1,19 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/common_optimizations/moc_legacy_transformations.hpp"
#include <memory>
#include "openvino/pass/manager.hpp"
#include "transformations/common_optimizations/change_placeholder_types.hpp"
bool ov::pass::MOCLegacyTransformations::run_on_model(const std::shared_ptr<ov::Model>& f) {
ov::pass::Manager manager(get_pass_config());
manager.register_pass<ov::pass::ChangePlaceholderTypes>(m_params_with_custom_types);
manager.run_passes(f);
return false;
}
@@ -74,20 +74,31 @@ ngraph::pass::GroupedGatherElimination::GroupedGatherElimination() {
while (inputs.size() > i + 1) {
auto curr = inputs[i].get_node_shared_ptr(), next = inputs[i + 1].get_node_shared_ptr();
if (curr->get_type_info() != next->get_type_info() ||
(!ov::is_type<opset1::Gather>(curr) && !ov::is_type<opset7::Gather>(curr)) ||
(!ov::is_type<opset1::Gather>(curr) && !ov::is_type<opset7::Gather>(curr) && !ov::is_type<opset8::Gather>(curr)) ||
(curr->input_value(0) != next->input_value(0))) {
++i;
continue;
} // curr and next are the same type of gather which takes data from the same source
bool is_opset1 = ov::is_type<opset1::Gather>(curr);
auto joint_indices = ngraph::op::util::make_try_fold<opset1::Concat>(OutputVector{curr->input_value(1), next->input_value(1)}, 0);
std::shared_ptr<Node> new_gather;
if (is_opset1)
if (ov::is_type<opset1::Gather>(curr)) {
new_gather = register_new_node<ngraph::opset1::Gather>(
curr->input_value(0), joint_indices->output(0), ngraph::opset1::Constant::create(element::i64, {}, {0})->output(0));
else
curr->input_value(0),
joint_indices->output(0),
ngraph::opset1::Constant::create(element::i64, {}, {0})->output(0));
} else if (ov::is_type<opset7::Gather>(curr)) {
new_gather = register_new_node<ngraph::opset7::Gather>(
curr->input_value(0), joint_indices->output(0), ngraph::opset1::Constant::create(element::i64, {}, {0})->output(0));
curr->input_value(0),
joint_indices->output(0),
ngraph::opset1::Constant::create(element::i64, {}, {0})->output(0));
} else if (ov::is_type<opset8::Gather>(curr)) {
new_gather = register_new_node<ngraph::opset8::Gather>(
curr->input_value(0),
joint_indices->output(0),
ngraph::opset1::Constant::create(element::i64, {}, {0})->output(0));
} else {
OPENVINO_UNREACHABLE("Unexpected Gather version");
}
new_ops.push_back(joint_indices);
new_ops.push_back(new_gather);
inputs.erase(inputs.begin() + i);
@@ -239,8 +250,7 @@ ngraph::pass::SimplifySecondInputOfReshape::SimplifySecondInputOfReshape() {
auto check_shape_of_gather = [&](const std::shared_ptr<Node>& gather) {
auto shape_of = gather->get_input_node_shared_ptr(0);
if ((!is_type<opset8::ShapeOf>(shape_of) && !is_type<opset1::ShapeOf>(shape_of)) ||
(shape_of->get_output_target_inputs(0).size() > 1)) {
if (!is_type<opset8::ShapeOf>(shape_of) && !is_type<opset1::ShapeOf>(shape_of)) {
return false;
}
return shape_of->input_value(0) == data;
@@ -14,6 +14,8 @@
#include <ngraph/validation_util.hpp>
#include <ngraph/log.hpp>
#include "transformations/rt_info/nonconvertible_divide.hpp"
NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertDivide, "ConvertDivide", 0);
NGRAPH_RTTI_DEFINITION(ngraph::pass::ConvertDivideWithConstant, "ConvertDivideWithConstant", 0);
@@ -21,8 +23,8 @@ namespace {
bool convert_divide(std::shared_ptr<ngraph::Node> node) {
auto div = std::dynamic_pointer_cast<ngraph::opset1::Divide>(node);
// We can not apply this transformation in case with integer input data type
if (!div || div->get_input_element_type(0).is_integral()
|| div->get_input_element_type(1).is_integral()) {
if (!div || ov::divide_is_nonconvertible(div)
|| div->get_input_element_type(0).is_integral()) {
return false;
}
@@ -1,4 +1,4 @@
// Copyright (C) 2018-2021 Intel Corporation
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
@@ -87,35 +87,38 @@ namespace {
reverse_seq_before = std::make_shared<ngraph::opset5::ReverseSequence>(X, seq_lengths, 0, 1);
}
auto axis_0 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 0 });
auto axis_1 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
// TensorIterator Body: begin
auto X_param_pshape = X_pshape;
X_param_pshape[1] = 1; // split by seq_lengths dimension
auto X_body_param = std::make_shared<ngraph::opset5::Parameter>(X.get_element_type(), X_param_pshape);
auto H_body_param = std::make_shared<ngraph::opset5::Parameter>(H_t.get_element_type(), H_t.get_partial_shape());
const auto squeezed_h = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(H_t, axis_1);
auto H_body_param = std::make_shared<ngraph::opset5::Parameter>(squeezed_h->get_element_type(), squeezed_h->get_output_partial_shape(0));
auto seq_body_param = std::make_shared<ngraph::opset5::Parameter>(seq_lengths.get_element_type(), seq_lengths.get_partial_shape());
// LSTM sequence case
const bool cell_state_defined = C_t.get_node_shared_ptr() != nullptr;
std::shared_ptr<ngraph::opset5::Parameter> C_body_param = cell_state_defined ?
std::make_shared<ngraph::opset5::Parameter>(C_t.get_element_type(), C_t.get_partial_shape()) :
nullptr;
auto axis_0 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 0 });
auto axis_1 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
std::shared_ptr<ngraph::opset5::Parameter> C_body_param = nullptr;
std::shared_ptr<ngraph::Node> squeezed_c = nullptr;
if (cell_state_defined) {
squeezed_c = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(C_t, axis_1);
C_body_param = std::make_shared<ngraph::opset5::Parameter>(squeezed_c->get_element_type(), squeezed_c->get_output_partial_shape(0));
}
const auto squeezed_x = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(X_body_param, axis_1);
const auto squeezed_h = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(H_body_param, axis_1);
const auto squeezed_w = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(W, axis_0);
const auto squeezed_r = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(R, axis_0);
const auto squeezed_b = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(B, axis_0);
std::shared_ptr<ngraph::Node> cell;
if (const auto lstm_sequence = ngraph::as_type_ptr<ngraph::opset5::LSTMSequence>(sequence)) {
const auto squeezed_c = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(C_body_param, axis_1);
cell = std::make_shared<ngraph::opset5::LSTMCell>(
squeezed_x,
squeezed_h,
squeezed_c,
H_body_param,
C_body_param,
squeezed_w,
squeezed_r,
squeezed_b,
@@ -127,7 +130,7 @@ namespace {
} else if (const auto rnn_sequence = ngraph::as_type_ptr<ngraph::opset5::RNNSequence>(sequence)) {
cell = std::make_shared<ngraph::opset5::RNNCell>(
squeezed_x,
squeezed_h,
H_body_param,
squeezed_w,
squeezed_r,
squeezed_b,
@@ -139,7 +142,7 @@ namespace {
} else if (const auto gnn_sequence = ngraph::as_type_ptr<ngraph::opset5::GRUSequence>(sequence)) {
cell = std::make_shared<ngraph::opset5::GRUCell>(
squeezed_x,
squeezed_h,
H_body_param,
squeezed_w,
squeezed_r,
squeezed_b,
@@ -153,24 +156,24 @@ namespace {
ngraph::ParameterVector body_params;
ngraph::ResultVector body_results;
auto unsqueeze_dum_dir_h = std::make_shared<ngraph::opset5::Unsqueeze>(cell->output(0), axis_1);
ngraph::Output<ngraph::Node> h_node_to_result = unsqueeze_dum_dir_h;
auto unsqueeze_dum_dir_c = cell_state_defined ? std::make_shared<ngraph::opset5::Unsqueeze>(cell->output(1), axis_1) : nullptr;
ngraph::Output<ngraph::Node> c_node_to_result = cell_state_defined ? unsqueeze_dum_dir_c : ngraph::Output<ngraph::Node>();
ngraph::Output<ngraph::Node> hidden_state = cell->output(0);
ngraph::Output<ngraph::Node> cell_state;
if (cell_state_defined)
cell_state = cell->output(1);
auto tensor_iterator = std::make_shared<ngraph::opset5::TensorIterator>();
if (enable_mask) {
const auto current_iter = get_current_iter(body_params, body_results, seq_body_param);
h_node_to_result = get_masked_value(tensor_iterator, body_params, body_results, current_iter, unsqueeze_dum_dir_h, seq_body_param);
hidden_state = get_masked_value(tensor_iterator, body_params, body_results, current_iter, hidden_state, seq_body_param);
if (cell_state_defined)
c_node_to_result = get_masked_value(tensor_iterator, body_params, body_results, current_iter, unsqueeze_dum_dir_c, seq_body_param);
cell_state = get_masked_value(tensor_iterator, body_params, body_results, current_iter, cell_state, seq_body_param);
}
auto H_res = std::make_shared<ngraph::opset5::Result>(h_node_to_result);
auto C_res = cell_state_defined ? std::make_shared<ngraph::opset5::Result>(c_node_to_result) : nullptr;
auto unsqueeze_seq_len = std::make_shared<ngraph::opset5::Unsqueeze>(h_node_to_result, axis_1);
auto concat_res = std::make_shared<ngraph::opset5::Result>(unsqueeze_seq_len);
auto H_res = std::make_shared<ngraph::opset5::Result>(hidden_state);
auto C_res = cell_state_defined ? std::make_shared<ngraph::opset5::Result>(cell_state) : nullptr;
auto hidden_state_unsqueezed = std::make_shared<ngraph::opset5::Unsqueeze>(hidden_state, axis_1);
auto concat_res = std::make_shared<ngraph::opset5::Result>(hidden_state_unsqueezed);
body_params.push_back(X_body_param);
body_params.push_back(H_body_param);
@@ -190,21 +193,21 @@ namespace {
if (!enable_mask) {
// Reversed order, stride -1
tensor_iterator->set_sliced_input(X_body_param, X, -1, -1, 1, 0, 1);
tensor_iterator->get_concatenated_slices(concat_res, -1, -1, 1, 0, 2);
tensor_iterator->get_concatenated_slices(concat_res, -1, -1, 1, 0, 1);
} else {
// use ReverseSequence as initializer
tensor_iterator->set_sliced_input(X_body_param, reverse_seq_before, 0, 1, 1, -1, 1);
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 2);
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 1);
}
} else {
// forward order
tensor_iterator->set_sliced_input(X_body_param, X, 0, 1, 1, -1, 1);
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 2);
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 1);
}
tensor_iterator->set_merged_input(H_body_param, H_t, H_res);
tensor_iterator->set_merged_input(H_body_param, squeezed_h, H_res);
if (cell_state_defined)
tensor_iterator->set_merged_input(C_body_param, C_t, C_res);
tensor_iterator->set_merged_input(C_body_param, squeezed_c, C_res);
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
ngraph::Output<ngraph::Node> H_out = H_res;
@@ -242,8 +245,12 @@ namespace {
if (cell_state_defined)
tensor_iterator->get_iter_value(C_out);
tensor_iterator->set_friendly_name(sequence->get_friendly_name());
ngraph::NodeVector new_nodes{squeezed_h, tensor_iterator};
if (cell_state_defined)
new_nodes.push_back(squeezed_c);
ngraph::OutputVector nodes_to_replace;
if (enable_mask && is_reverse) {
auto reverse_seq_after = std::make_shared<ngraph::opset5::ReverseSequence>(tensor_iterator->output(0), seq_lengths, 0, 2);
auto reverse_seq_after = std::make_shared<ngraph::opset5::ReverseSequence>(tensor_iterator->output(0), seq_lengths, 0, 1);
// Resolve a collision of names data nodes in CNN Network in Reverse case with mask.
/*
* Before transformation (no collisions)
@@ -262,33 +269,31 @@ namespace {
* TI [other_name] -- (data_node: other_name.0) --> RevSequence [rnn_name.0] -- (data_node: rnn_name.0) -> Result1
* -- (data_node: other_name.1) --> Identity(rnn_name.1) -- (data_node: rnn_name.1) -> Result2
*/
auto identity_1_h = std::make_shared<ngraph::opset5::Unsqueeze>(tensor_iterator->output(1), axis_1);
auto identity_2_h = std::make_shared<ngraph::opset5::Squeeze>(identity_1_h, axis_1);
ngraph::NodeVector new_nodes{ reverse_seq_after, tensor_iterator, reverse_seq_before, identity_1_h, identity_2_h };
ngraph::OutputVector nodes_to_replace{ reverse_seq_after, identity_2_h };
new_nodes.push_back(reverse_seq_before);
new_nodes.push_back(reverse_seq_after);
nodes_to_replace.push_back(reverse_seq_after);
nodes_to_replace.push_back(tensor_iterator->output(1));
if (cell_state_defined) {
auto identity_1_c = std::make_shared<ngraph::opset5::Unsqueeze>(tensor_iterator->output(2), axis_1);
auto identity_2_c = std::make_shared<ngraph::opset5::Squeeze>(identity_1_c, axis_1);
new_nodes.emplace_back(identity_1_c);
new_nodes.emplace_back(identity_2_c);
nodes_to_replace.emplace_back(identity_2_c);
identity_2_c->set_friendly_name(sequence->get_friendly_name() + ".2");
auto cell_state = tensor_iterator->output(2);
new_nodes.emplace_back(cell_state.get_node_shared_ptr());
nodes_to_replace.emplace_back(cell_state);
}
ngraph::copy_runtime_info(sequence, new_nodes);
ngraph::replace_node(sequence, nodes_to_replace);
tensor_iterator->set_friendly_name(sequence->get_friendly_name() + "/tensor_iterator");
reverse_seq_after->set_friendly_name(sequence->get_friendly_name() + ".0");
identity_2_h->set_friendly_name(sequence->get_friendly_name() + ".1");
} else {
ngraph::copy_runtime_info(sequence, tensor_iterator);
ngraph::replace_node(sequence, tensor_iterator);
nodes_to_replace = tensor_iterator->outputs();
}
for (size_t i = 0; i < nodes_to_replace.size(); i++) {
auto unsqueeze = std::make_shared<ngraph::opset5::Unsqueeze>(nodes_to_replace[i], axis_1);
unsqueeze->set_friendly_name(sequence->get_friendly_name() + "." + std::to_string(i));
nodes_to_replace[i] = unsqueeze;
new_nodes.push_back(unsqueeze);
}
ngraph::copy_runtime_info(sequence, new_nodes);
ngraph::replace_node(sequence, nodes_to_replace);
return true;
}
} // namespace
@@ -78,7 +78,7 @@ bool convertTensorIteratorToSequence(
ordered_out_descs[0] = output_desc;
} else if (res->input_value(0) == found_cell->output(0)) {
ordered_out_descs[1] = output_desc;
} else if (found_cell->get_output_size() == 3 && res->input_value(0) == found_cell->output(1)) {
} else if (found_cell->get_output_size() == 2 && res->input_value(0) == found_cell->output(1)) {
ordered_out_descs[2] = output_desc;
} else {
return false;
@@ -0,0 +1,20 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/rt_info/nonconvertible_divide.hpp"
void ov::disable_divide_conversion(const std::shared_ptr<Node>& node) {
auto& rt_info = node->get_rt_info();
rt_info[NonconvertibleDivide::get_type_info_static()] = NonconvertibleDivide{};
}
void ov::enable_divide_conversion(const std::shared_ptr<Node>& node) {
auto& rt_info = node->get_rt_info();
rt_info.erase(NonconvertibleDivide::get_type_info_static());
}
bool ov::divide_is_nonconvertible(const std::shared_ptr<Node>& node) {
const auto& rt_info = node->get_rt_info();
return rt_info.count(NonconvertibleDivide::get_type_info_static());
}
@@ -8,6 +8,7 @@
#include <functional>
#include <memory>
#include <ngraph/opsets/opset1.hpp>
#include <ngraph/op/broadcast.hpp>
#include <ngraph/op/constant.hpp>
#include <ngraph/op/reshape.hpp>
@@ -177,6 +178,31 @@ bool shapes_equal_except_dynamic_expected_batch(const ngraph::PartialShape& expe
}
}
void visit_shape_path(const std::shared_ptr<ov::Node>& node,
std::unordered_set<std::shared_ptr<ov::Node>>& visited,
std::function<void(std::shared_ptr<ov::Node>)> func) {
if (!node)
return;
visited.insert(node);
std::deque<std::shared_ptr<ov::Node>> nodes{node};
while (!nodes.empty()) {
auto curr_node = nodes.front();
nodes.pop_front();
// Do not check if already visited
if (ngraph::is_type<ngraph::opset1::ShapeOf>(curr_node) || ngraph::is_type<ngraph::opset3::ShapeOf>(curr_node)) {
continue;
}
visited.insert(curr_node);
func(curr_node);
for (auto& input_value : curr_node->input_values()) {
// continue searching
const auto& input_node = input_value.get_node_shared_ptr();
nodes.push_front(input_node);
}
}
}
} // namespace util
} // namespace op
} // namespace ngraph
+5 -1
View File
@@ -46,6 +46,10 @@ set_source_files_properties(${MIXED_SRC}
source_group("src" FILES ${LIBRARY_SRC})
source_group("include" FILES ${PUBLIC_HEADERS})
# Create ov_core_dev library
add_library(ov_core_dev INTERFACE)
target_include_directories(ov_core_dev INTERFACE $<BUILD_INTERFACE:${OpenVINO_SOURCE_DIR}/src/core/dev_api>)
# Create static or shared library depending on BUILD_SHARED_LIBS
add_library(ngraph_obj OBJECT ${LIBRARY_SRC} ${PUBLIC_HEADERS} ${IE_SHARED_SRCS})
@@ -57,7 +61,7 @@ ie_faster_build(ngraph_obj
addVersionDefines(src/version.cpp CI_BUILD_NUMBER)
target_link_libraries(ngraph_obj PRIVATE ngraph::builder ngraph::reference openvino::util pugixml::static ov_shape_inference)
target_link_libraries(ngraph_obj PRIVATE ngraph::builder ngraph::reference openvino::util pugixml::static ov_shape_inference ov_core_dev)
ie_mark_target_as_cc(ngraph_obj)
File renamed without changes.
+1 -1
View File
@@ -375,7 +375,7 @@ public:
Any& operator=(Any&& other) = default;
/**
* @brief Destructor presereves unload order of implementation object and reference to library
* @brief Destructor preserves unloading order of implementation object and reference to library
*/
~Any();
@@ -132,6 +132,18 @@ public:
/// \return Smallest interval dimension enclosing inputs
Dimension operator-(const Dimension& dim) const;
/// \brief Division operator for Dimension divided by a value_type parameter.
/// \param divisor Right operand for division.
/// \return Smallest interval dimension enclosing inputs
Dimension operator/(const value_type divisor) const;
/// \brief Divided-into operator for Dimension.
/// \param divisor Right operand for multiplication.
/// \return A reference to `*this`, after updating `*this` to the value `*this * dim`.
Dimension& operator/=(const value_type divisor) {
return (*this = *this / divisor);
}
/// \brief Multiplication operator for Dimension.
/// \param dim Right operand for multiplicaiton.
/// \return Smallest interval containing all "produces" which are 0 if either of `this` or
@@ -94,7 +94,21 @@ public:
///
/// \return Function with added pre/post-processing operations
std::shared_ptr<Model> build();
private:
friend OPENVINO_API std::ostream& operator<<(std::ostream& str, const PrePostProcessor& prePostProcessor);
void dump(std::ostream&) const;
};
/// \brief Inserts a human-readable representation of a PrePostProcessors into an output stream. The output to the
/// stream is in "informal" notation and can be used for debugging purposes
///
/// \param str The output stream targeted for insertion.
///
/// \param prePostProcessor The shape to be inserted into output stream.
///
/// \return A reference to same output stream after insertion.
OPENVINO_API std::ostream& operator<<(std::ostream& str, const PrePostProcessor& prePostProcessor);
} // namespace preprocess
} // namespace ov
+2 -2
View File
@@ -48,7 +48,7 @@ private:
static constexpr size_t INPUT_MEAN = 3;
static constexpr size_t INPUT_VARIANCE = 4;
double m_epsilon;
double m_epsilon{0};
};
} // namespace v0
namespace v5 {
@@ -89,7 +89,7 @@ private:
static constexpr size_t INPUT_MEAN = 3;
static constexpr size_t INPUT_VARIANCE = 4;
double m_epsilon;
double m_epsilon{0};
};
} // namespace v5
} // namespace op
+1 -1
View File
@@ -51,7 +51,7 @@ public:
private:
element::Type m_output_type;
bool m_with_right_bound;
bool m_with_right_bound{true};
};
} // namespace v3
} // namespace op
+1 -1
View File
@@ -709,7 +709,7 @@ private:
element::Type m_element_type;
Shape m_shape{};
std::shared_ptr<ngraph::runtime::AlignedBuffer> m_data;
bool m_all_elements_bitwise_identical;
bool m_all_elements_bitwise_identical = false;
bool m_alloc_buffer_on_visit_attributes = true;
};
} // namespace v0
@@ -31,7 +31,7 @@ public:
}
private:
bool m_ctc_merge_repeated;
bool m_ctc_merge_repeated{true};
};
} // namespace v0
} // namespace op
@@ -92,7 +92,7 @@ public:
}
private:
bool m_merge_repeated;
bool m_merge_repeated{true};
element::Type m_classes_index_type{element::i32};
element::Type m_sequence_length_type{element::i32};
};
@@ -166,7 +166,7 @@ public:
}
private:
bool m_bilinear_interpolation_pad;
bool m_bilinear_interpolation_pad{false};
};
} // namespace v8
} // namespace op
@@ -94,8 +94,8 @@ public:
}
private:
int64_t m_output_dim;
float m_spatial_scale;
int64_t m_output_dim{0};
float m_spatial_scale{0};
int64_t m_group_size = 1;
std::string m_mode = "bilinear_deformable";
int64_t m_spatial_bins_x = 1;
@@ -42,7 +42,7 @@ public:
DepthToSpace(const Output<Node>& data, const std::string& mode, std::size_t block_size = 1);
bool visit_attributes(AttributeVisitor& visitor) override;
std::size_t get_block_size() const {
const std::size_t& get_block_size() const {
return m_blocksize;
}
DepthToSpaceMode get_mode() const {
+1 -1
View File
@@ -35,7 +35,7 @@ public:
}
private:
double m_alpha;
double m_alpha{0};
};
} // namespace v0
} // namespace op
@@ -39,7 +39,7 @@ public:
}
private:
size_t m_max_rois;
size_t m_max_rois{0};
template <class T>
friend void shape_infer(ExperimentalDetectronTopKROIs* op,
@@ -64,7 +64,7 @@ private:
Shape m_patch_sizes;
Strides m_patch_movement_strides;
Shape m_patch_selection_rates;
PadType m_padding;
PadType m_padding{PadType::EXPLICIT};
template <class T>
friend void shape_infer(const ExtractImagePatches* op,
const std::vector<T>& input_shapes,
@@ -33,7 +33,7 @@ public:
}
private:
int64_t m_axis;
int64_t m_axis{0};
template <class T>
void friend shape_infer(const GatherElements* op,
const std::vector<T>& input_shapes,
@@ -191,7 +191,7 @@ public:
}
private:
direction m_direction;
direction m_direction{direction::FORWARD};
};
} // namespace v5
} // namespace op
+1 -1
View File
@@ -74,7 +74,7 @@ public:
bool has_evaluate() const override;
private:
PadMode m_pad_mode;
PadMode m_pad_mode{PadMode::CONSTANT};
bool evaluate_pad(const HostTensorVector& outputs, const HostTensorVector& inputs) const;
};
} // namespace v1
+1 -1
View File
@@ -45,7 +45,7 @@ public:
private:
Shape m_output_size{0, 0};
float m_spatial_scale;
float m_spatial_scale{0};
std::string m_method = "max";
};
} // namespace v0
+1 -1
View File
@@ -44,7 +44,7 @@ public:
}
private:
RoundMode m_mode;
RoundMode m_mode{RoundMode::HALF_TO_EVEN};
};
} // namespace v5
} // namespace op
@@ -40,7 +40,7 @@ public:
SpaceToDepth(const Output<Node>& data, const std::string& mode, std::size_t block_size = 1);
bool visit_attributes(AttributeVisitor& visitor) override;
std::size_t get_block_size() const {
const std::size_t& get_block_size() const {
return m_blocksize;
}
SpaceToDepthMode get_mode() const {
@@ -50,6 +50,10 @@ public:
bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override;
OPENVINO_SUPPRESS_DEPRECATED_END
const BroadcastModeSpec& get_broadcast_spec() const {
return m_mode;
}
protected:
BroadcastModeSpec m_mode;
@@ -67,12 +67,6 @@ public:
bool visit_attributes(AttributeVisitor& visitor) override;
OPENVINO_SUPPRESS_DEPRECATED_START
bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override;
OPENVINO_SUPPRESS_DEPRECATED_END
bool has_evaluate() const override;
protected:
bool is_type_supported(const ov::element::Type& type) const;
@@ -79,7 +79,7 @@ class OPENVINO_API Allocator {
public:
/**
* @brief Destructor presereves unload order of implementation object and reference to library
* @brief Destructor preserves unloading order of implementation object and reference to library
*/
~Allocator();
+1 -1
View File
@@ -75,7 +75,7 @@ public:
Tensor& operator=(Tensor&& other) = default;
/**
* @brief Destructor presereves unload order of implementation object and reference to library
* @brief Destructor preserves unloading order of implementation object and reference to library
*/
~Tensor();
@@ -108,6 +108,52 @@ void color_convert_i420(const T* arg_y,
}
}
template <ov::element::Type_t ET>
inline bool color_convert_nv12(const std::shared_ptr<Node>& op,
const ov::HostTensorVector& outputs,
const ov::HostTensorVector& inputs,
ov::op::util::ConvertColorNV12Base::ColorConversion type) {
static const size_t N_DIM = 0;
static const size_t H_DIM = 1;
static const size_t W_DIM = 2;
NGRAPH_CHECK(op->get_input_size() == 1 || op->get_input_size() == 2,
"NV12 conversion shall have one or 2 inputs, but it is ",
op->get_input_size());
auto single_plane = op->get_input_size() == 1;
const auto& y_tensor = inputs[0];
auto batch_size = y_tensor->get_shape()[N_DIM];
auto image_w = y_tensor->get_shape()[W_DIM];
auto image_h = y_tensor->get_shape()[H_DIM];
if (single_plane) {
image_h = image_h * 2 / 3;
}
outputs[0]->set_shape({batch_size, image_h, image_w, 3}); // 3 is RGB
if (single_plane) {
color_convert_nv12(y_tensor->get_data_ptr<ET>(),
y_tensor->get_data_ptr<ET>() + image_w * image_h,
outputs[0]->get_data_ptr<ET>(),
batch_size,
image_h,
image_w,
image_w * image_h * 3 / 2,
image_w * image_h * 3 / 2,
type);
} else {
const auto& uv_tensor = inputs[1];
color_convert_nv12(y_tensor->get_data_ptr<ET>(),
uv_tensor->get_data_ptr<ET>(),
outputs[0]->get_data_ptr<ET>(),
batch_size,
image_h,
image_w,
image_w * image_h,
image_w * image_h / 2,
type);
}
return true;
}
} // namespace reference
} // namespace runtime
} // namespace ngraph
@@ -181,7 +181,6 @@ static void enumerate_proposals(const T* bottom4d,
template <typename T>
static void nms(const int num_boxes,
std::vector<int>& is_dead,
const std::vector<ProposalBox<T>>& proposals,
std::vector<unsigned int>& index_out,
int& num_out,
@@ -189,7 +188,7 @@ static void nms(const int num_boxes,
const float nms_thresh,
const int max_num_out,
T coordinates_offset) {
std::fill(is_dead.begin(), is_dead.begin() + num_boxes, 0);
std::vector<int> is_dead(num_boxes, 0);
for (int box = 0; box < num_boxes; ++box) {
if (is_dead[box])
continue;
@@ -348,7 +347,6 @@ static void proposal_exec(const T* class_probs,
int num_rois = 0;
std::vector<ProposalBox<T>> proposals(num_proposals);
const int pre_nms_topn = num_proposals < attrs.pre_nms_topn ? num_proposals : attrs.pre_nms_topn;
std::vector<int> is_dead(pre_nms_topn);
std::vector<unsigned int> roi_indices(attrs.post_nms_topn);
std::vector<float> anchors = generate_anchors(attrs, anchor_count);
@@ -359,6 +357,9 @@ static void proposal_exec(const T* class_probs,
bool swap_xy = attrs.framework == "tensorflow";
for (unsigned int batch_idx = 0; batch_idx < batch_num; ++batch_idx) {
std::fill(roi_indices.begin(), roi_indices.end(), 0);
num_rois = 0;
enumerate_proposals(p_bottom_item + num_proposals + batch_idx * num_proposals * 2,
p_d_anchor_item + batch_idx * num_proposals * 4,
anchors.data(),
@@ -385,7 +386,6 @@ static void proposal_exec(const T* class_probs,
return (box1.score > box2.score);
});
nms(pre_nms_topn,
is_dead,
proposals,
roi_indices,
num_rois,
@@ -0,0 +1,119 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <cstdint>
#include <openvino/core/validation_util.hpp>
#include <openvino/op/batch_to_space.hpp>
#include <openvino/opsets/opset2.hpp>
#include "utils.hpp"
namespace ov {
namespace op {
namespace v1 {
template <class T>
void shape_infer(const ov::op::v1::BatchToSpace* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {}) {
using ValType = typename std::iterator_traits<typename T::iterator>::value_type::value_type;
NODE_VALIDATION_CHECK(op, input_shapes.size() == 4 && output_shapes.size() == 1);
const auto& data_shape = input_shapes[0];
const auto& block_shape = input_shapes[1];
const auto& crops_begin_shape = input_shapes[2];
const auto& crops_end_shape = input_shapes[3];
bool got_const_data = false;
auto inputs_same_ps = crops_begin_shape;
NODE_VALIDATION_CHECK(op,
T::merge_into(inputs_same_ps, crops_end_shape) && T::merge_into(inputs_same_ps, block_shape),
"block_shape, crops_begin and crops_end inputs must have the same shape. Got: ",
block_shape,
", ",
crops_begin_shape,
" and ",
crops_end_shape);
NODE_VALIDATION_CHECK(op,
inputs_same_ps.rank().compatible(1),
"block_shape and crops inputs must have rank 1. Got: ",
inputs_same_ps.rank());
const ov::Rank data_rank = data_shape.rank();
if (data_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
(data_rank.get_length() >= 2),
"data input must have rank greater or equal than 2. Got: ",
data_rank.get_length());
if (inputs_same_ps.is_static()) {
NODE_VALIDATION_CHECK(op,
data_rank.get_length() == inputs_same_ps[0].get_length(),
"block_shape and crop inputs must have same number of elements "
"as data input rank. Got: ",
inputs_same_ps[0],
" and ",
data_rank);
}
auto& output_shape = output_shapes[0];
output_shape.resize(data_shape.size());
std::vector<int64_t> block_val, crops_begin_val, crops_end_val;
if (get_data_as_int64<T>(1, op, block_val, constant_data) &&
get_data_as_int64<T>(2, op, crops_begin_val, constant_data) &&
get_data_as_int64<T>(3, op, crops_end_val, constant_data)) {
got_const_data = true;
bool block_vals_valid = std::all_of(begin(block_val), end(block_val), [](int64_t elem) {
return elem >= 1;
});
NODE_VALIDATION_CHECK(op,
block_vals_valid,
"Elements of block_shape input must be greater or equal to one.");
bool crops_begin_vals_valid = std::all_of(begin(crops_begin_val), end(crops_begin_val), [](int64_t elem) {
return elem >= 0;
});
bool crops_end_vals_valid = std::all_of(begin(crops_end_val), end(crops_end_val), [](int64_t elem) {
return elem >= 0;
});
NODE_VALIDATION_CHECK(op,
crops_begin_vals_valid && crops_end_vals_valid,
"Elements of crops_begin and crops_end inputs must be greater or equal to zero.");
if (data_shape.is_static()) {
for (size_t idx = 0; idx < data_shape.size(); idx++) {
const bool is_valid_crops_and_shape =
crops_begin_val[idx] + crops_end_val[idx] <= block_val[idx] * data_shape[idx].get_length();
NODE_VALIDATION_CHECK(op,
is_valid_crops_and_shape,
"crops_begin[i] + crops_end[i] must be less or equal to "
"block_shape[i] * input_shape[i]");
}
}
int64_t block_prod = std::accumulate(begin(block_val), end(block_val), 1, std::multiplies<int64_t>());
const auto divisor = static_cast<ValType>(block_prod);
output_shape[0] = data_shape[0] / divisor;
check_divided_result(op, output_shape[0], data_shape[0], divisor);
for (size_t idx = 1; idx < data_shape.size(); idx++) {
output_shape[idx] = data_shape[idx] * static_cast<ValType>(block_val[idx]) -
static_cast<ValType>(crops_begin_val[idx]) -
static_cast<ValType>(crops_end_val[idx]);
}
}
}
if (!got_const_data)
// For PartialShape, Set the output to be dynamic;
// For StaticShape, throw error caused by implicitly constructing StaticShape with PartialShape argument;
output_shapes[0] = ov::PartialShape::dynamic(data_rank);
}
} // namespace v1
} // namespace op
} // namespace ov
@@ -0,0 +1,301 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/validation_util.hpp>
#include <openvino/op/broadcast.hpp>
#include <openvino/op/util/broadcast_base.hpp>
#include "ngraph/op/concat.hpp"
#include "openvino/core/axis_vector.hpp"
#include "utils.hpp"
namespace ov {
namespace op {
namespace util {
template <typename T>
void validate_target_shape_none(const ov::Node* op,
const T& arg_shape,
const AxisVector& axes_mapping_val,
const T& target_shape) {
if (arg_shape.rank().is_static() && target_shape.rank().is_static()) {
const auto target_rank_length = target_shape.size();
// axes_mapping needs to be in sorted order
NODE_VALIDATION_CHECK(op,
std::is_sorted(axes_mapping_val.begin(), axes_mapping_val.end()),
"Broadcast doesn't permit transposes. axes_mapping ",
axes_mapping_val,
" not in sorted order");
if (arg_shape.size() == 0 && axes_mapping_val.size() > 0) {
NODE_VALIDATION_CHECK(op,
target_shape[axes_mapping_val[0]].compatible(1),
"Broadcast target[axes_mapping[0]]. Expected 1. Got ",
target_shape[axes_mapping_val[0]]);
}
for (size_t i = 0; i < axes_mapping_val.size(); i++) {
NODE_VALIDATION_CHECK(op,
axes_mapping_val[i] < target_rank_length,
"Broadcast axes_mapping[",
i,
"]: ",
axes_mapping_val[i],
" exceeds target rank ",
target_rank_length);
if (arg_shape.size() > 0) {
NODE_VALIDATION_CHECK(
op,
target_shape[axes_mapping_val[i]].compatible(arg_shape[i]) || arg_shape[i].compatible(1),
"Broadcast target[axes_mapping[",
i,
"]]",
" Expected ",
arg_shape[i],
". Got ",
target_shape[axes_mapping_val[i]]);
}
}
}
}
template <typename T>
void validate_target_shape_numpy(const ov::Node* op, const T& arg_shape, const T& target_shape) {
if (arg_shape.rank().is_dynamic() || target_shape.rank().is_dynamic()) {
return;
}
const auto arg_rank_length = arg_shape.size();
const auto target_rank_length = target_shape.size();
const int64_t start_axis = target_rank_length - arg_rank_length;
NODE_VALIDATION_CHECK(op,
start_axis >= 0,
"Broadcast target_shape has smaller rank ",
target_rank_length,
" than arg shape ",
arg_rank_length);
for (auto i = start_axis; i < target_rank_length; i++) {
NODE_VALIDATION_CHECK(op,
arg_shape[i - start_axis].is_dynamic() || target_shape[i].is_dynamic() ||
arg_shape[i - start_axis].compatible(1) ||
arg_shape[i - start_axis].compatible(target_shape[i]),
"Input shape dimension equal ",
arg_shape[i - start_axis],
" cannot be broadcasted (numpy mode) to ",
target_shape[i],
". Allowed input dimension value would be 1",
target_shape[i] != 1 ? " or " : "",
target_shape[i] != 1 ? std::to_string(target_shape[i].get_length()) : "");
}
}
template <typename T>
void set_result_shape_pdpd(const ov::Node* op,
const T& arg0_shape,
const T& target_shape,
T& result_shape,
const ov::op::BroadcastModeSpec& broadcast_spec) {
using DimType = typename std::iterator_traits<typename T::iterator>::value_type;
if (arg0_shape.rank().is_dynamic() || target_shape.rank().is_dynamic()) {
result_shape = PartialShape::dynamic(target_shape.rank());
return;
}
result_shape = target_shape;
auto& start_axis = broadcast_spec.m_axis;
NODE_VALIDATION_CHECK(op, start_axis >= 0, "Broadcast start_axis must be greater than 0");
for (size_t i = start_axis; i < target_shape.size(); i++) {
const auto& arg_dim = arg0_shape[i - start_axis];
if (arg_dim == 1) {
result_shape[i] = target_shape[i];
} else if (target_shape[i] == 1) {
result_shape[i] = arg_dim;
} else {
NODE_VALIDATION_CHECK(op,
DimType::merge(result_shape[i], arg_dim, target_shape[i]),
"Broadcast incorrect target shape. Expecting either 1 or ",
arg_dim,
" . Got ",
target_shape[i]);
}
}
}
template <typename T>
void set_result_shape_bidirectional(const ov::Node* op, const T& arg_shape, T& target_shape, T& result_shape) {
using DimType = typename std::iterator_traits<typename T::iterator>::value_type;
if (arg_shape.rank().is_dynamic() || target_shape.rank().is_dynamic()) {
result_shape = PartialShape::dynamic();
return;
}
auto arg_shape_vec = arg_shape;
// Add left padding to shorter target or argument shape
const auto target_padded_rank = std::max(arg_shape_vec.size(), target_shape.size());
while (arg_shape_vec.size() < target_padded_rank) {
arg_shape_vec.insert(arg_shape_vec.begin(), 1);
}
while (target_shape.size() < target_padded_rank) {
target_shape.insert(target_shape.begin(), 1);
}
result_shape.resize(target_padded_rank);
for (size_t i = 0; i < target_shape.size(); ++i) {
if (arg_shape_vec[i] == 1) {
result_shape[i] = target_shape[i];
} else if (target_shape[i] == 1) {
result_shape[i] = arg_shape_vec[i];
} else {
NODE_VALIDATION_CHECK(op,
DimType::merge(result_shape[i], arg_shape_vec[i], target_shape[i]),
"Broadcast incorrect target shape. Expecting either 1 or ",
arg_shape_vec[i],
". Got ",
target_shape[i]);
}
}
}
template <class T>
void broadcase_base_shape_infer(
const ov::op::util::BroadcastBase* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {}) {
// shape node should produce a one dimensional shape.
auto broadcast_shape_rank = input_shapes[1].rank();
NODE_VALIDATION_CHECK(op,
broadcast_shape_rank.compatible(1),
"Broadcast shape rank must be 1, but has ",
broadcast_shape_rank);
const auto& mode = op->get_broadcast_spec();
if (mode.m_type == BroadcastType::NONE) {
// axes_mapping node should produce a one dimensional shape.
auto axes_shape_rank = input_shapes[2].rank();
NODE_VALIDATION_CHECK(op,
axes_shape_rank.compatible(1),
"Broadcast axes rank must be 1, but has ",
axes_shape_rank);
}
auto& result_shape = output_shapes[0];
const auto& input_shape = input_shapes[0];
const auto& target_shape = input_shapes[1];
const bool is_target_shape_known = target_shape.is_static();
T output_shape;
bool output_shape_defined = get_data_as_shape<T>(1, op, output_shape, constant_data);
if (!output_shape_defined) {
if (auto concat = ov::as_type_ptr<ov::opset1::Concat>(op->get_input_node_shared_ptr(1))) {
const auto concat_inputs = concat->input_values();
if (concat->get_output_partial_shape(0).is_static() && concat->get_shape().size() == 1 &&
concat_inputs.size() == shape_size(concat->get_shape())) {
for (const auto& concat_input : concat_inputs) {
auto source_node_ptr = concat_input.get_node_shared_ptr();
if (auto source_const_ptr = ov::as_type_ptr<ov::opset1::Constant>(source_node_ptr)) {
output_shape.push_back(source_const_ptr->get_axis_vector_val()[0]);
} else {
output_shape.push_back(Dimension::dynamic());
}
}
output_shape_defined = true;
}
}
}
if (mode.m_type == BroadcastType::NONE) {
if (output_shape_defined) {
result_shape = output_shape;
} else if (is_target_shape_known) {
result_shape = PartialShape::dynamic(target_shape[0].get_length());
} else {
result_shape = PartialShape::dynamic();
}
// Validate axes_mapping
const auto& axes_shape = input_shapes[2];
if (input_shape.rank().is_static() && target_shape.rank().is_static() && axes_shape.is_static()) {
auto input_rank = (input_shape.size() == 0 && axes_shape[0].get_length() > 0) ? 1 : input_shape.size();
NODE_VALIDATION_CHECK(op,
axes_shape[0].get_length() == input_rank,
"Broadcast axes_mapping shape ",
axes_shape,
" doesn't match rank of input tensor ",
input_rank);
std::vector<int64_t> axes_mapping_val;
if (output_shape_defined && get_data_as_int64<T>(2, op, axes_mapping_val, constant_data)) {
AxisVector axes_mapping =
AxisVector(std::vector<size_t>(axes_mapping_val.begin(), axes_mapping_val.end()));
validate_target_shape_none(op, input_shape, axes_mapping, output_shape);
}
}
} else if (mode.m_type == BroadcastType::NUMPY) {
if (output_shape_defined) {
result_shape = output_shape;
validate_target_shape_numpy(op, input_shape, output_shape);
} else if (is_target_shape_known) {
result_shape = PartialShape::dynamic(target_shape[0].get_length());
} else {
result_shape = PartialShape::dynamic();
}
} else if (mode.m_type == BroadcastType::PDPD) {
if (output_shape_defined) {
set_result_shape_pdpd(op, input_shape, output_shape, result_shape, mode);
} else if (is_target_shape_known) {
result_shape = PartialShape::dynamic(target_shape[0].get_length());
} else {
result_shape = PartialShape::dynamic();
}
} else if (mode.m_type == BroadcastType::BIDIRECTIONAL) {
if (output_shape_defined) {
set_result_shape_bidirectional(op, input_shape, output_shape, result_shape);
} else if (input_shape.rank().is_static() && is_target_shape_known) {
auto output_rank = std::max(input_shape.size(), static_cast<size_t>(target_shape[0].get_length()));
result_shape = PartialShape::dynamic(output_rank);
} else {
result_shape = PartialShape::dynamic();
}
}
}
} // namespace util
namespace v3 {
template <class T>
void shape_infer(const ov::op::v3::Broadcast* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {}) {
NODE_VALIDATION_CHECK(op, output_shapes.size() == 1);
auto& mode = op->get_broadcast_spec();
if (mode.m_type == BroadcastType::NONE) {
NODE_VALIDATION_CHECK(op,
input_shapes.size() == 3,
"axes_mapping input should be provided if explicit mode is used");
} else {
NODE_VALIDATION_CHECK(op,
input_shapes.size() == 2,
"axes_mapping input should not be provided for mode other than explicit");
}
broadcase_base_shape_infer(op, input_shapes, output_shapes, constant_data);
}
} // namespace v3
namespace v1 {
template <class T>
void shape_infer(const ov::op::v1::Broadcast* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {}) {
NODE_VALIDATION_CHECK(op, output_shapes.size() == 1 && (input_shapes.size() == 2 || input_shapes.size() == 3));
broadcase_base_shape_infer(op, input_shapes, output_shapes, constant_data);
}
} // namespace v1
} // namespace op
} // namespace ov
@@ -0,0 +1,59 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <cstdint>
#include <openvino/core/validation_util.hpp>
#include <openvino/op/depth_to_space.hpp>
#include <openvino/opsets/opset1.hpp>
#include "utils.hpp"
namespace ov {
namespace op {
namespace v0 {
template <class T>
void shape_infer(const ov::op::v0::DepthToSpace* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes) {
using ValType = typename std::iterator_traits<typename T::iterator>::value_type::value_type;
NODE_VALIDATION_CHECK(op, input_shapes.size() == 1 && output_shapes.size() == 1);
const auto& data_shape = input_shapes[0];
const ov::Rank data_rank = data_shape.rank();
const auto& block_size = op->get_block_size();
if (data_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
data_shape.size() >= 3,
"The input tensor with rank lower than 3 is not supported (input rank: ",
data_shape.size(),
")");
const size_t divider = std::pow(block_size, data_shape.size() - 2);
NODE_VALIDATION_CHECK(op, (divider), "DepthToSpace: The divider must not be 0");
auto& output_shape = output_shapes[0];
output_shape.resize(data_shape.size());
output_shape[0] = data_shape[0];
const auto divisor = static_cast<ValType>(divider);
output_shape[1] = data_shape[1] / divisor;
check_divided_result(op, output_shape[1], data_shape[1], divisor);
for (size_t i = 2; i < output_shape.size(); i++) {
output_shape[i] = data_shape[i] * static_cast<ValType>(block_size);
}
} else {
// For PartialShape, Set the output to be dynamic;
// For StaticShape, throw error caused by implicitly constructing StaticShape with PartialShape argument;
output_shapes[0] = ov::PartialShape::dynamic(data_rank);
}
}
} // namespace v0
} // namespace op
} // namespace ov
@@ -160,7 +160,7 @@ void shape_infer_base(const DetectionOutputBase* op,
if (!num_prior_boxes && box_logits_pshape[1].is_static()) {
auto box_logits_pshape_2nd_dim = box_logits_pshape[1].get_length();
NODE_VALIDATION_CHECK(op,
(box_logits_pshape_2nd_dim % (num_loc_classes * 4)) == 0,
num_loc_classes != 0 && (box_logits_pshape_2nd_dim % (num_loc_classes * 4)) == 0,
"Box logits' second dimension must be a multiply of num_loc_classes * 4 (",
num_loc_classes * 4,
"). Current value is: ",
@@ -340,4 +340,4 @@ void shape_infer(const DetectionOutput* op, const std::vector<T>& input_shapes,
} // namespace v8
} // namespace op
} // namespace ov
} // namespace ov
@@ -71,7 +71,7 @@ void shape_infer(const Einsum* op, const std::vector<T>& input_shapes, std::vect
label_to_shape[label].compatible(T{pshape[label_ind]}),
"Different input dimensions indicated by the same labels for Einsum "
"must be compatible.");
T::merge_into(label_to_shape[label], T{pshape[dim_ind]});
OPENVINO_ASSERT(T::merge_into(label_to_shape[label], T{pshape[dim_ind]}));
}
++dim_ind;
}
@@ -3,6 +3,7 @@
//
#pragma once
#include <openvino/op/lstm_cell.hpp>
#include "utils.hpp"
namespace ov {
@@ -16,7 +17,7 @@ void lstm_shape_infer(const OpsType* op,
using DimType = typename std::iterator_traits<typename ShapeType::iterator>::value_type;
enum { X, initial_hidden_state, initial_cell_state, W, R, B };
std::vector<bool> input_rank_static(6, false);
bool all_rank_dynamic = false;
bool all_rank_dynamic = true;
bool all_rank_static = true;
// Prepare OutShape
auto& hidden_shape = output_shapes[0];
@@ -43,7 +44,7 @@ void lstm_shape_infer(const OpsType* op,
bool is_hidden_init = false;
// deduce batch/hidden_size
for (size_t i = 0; i < input_shapes.size() && i < 6 ; i++) {
for (size_t i = 0; i < input_shapes.size() && i < 6; i++) {
const auto& input = input_shapes[i];
if (input_rank_static[i]) {
// batch could be deduced from x, cell_state or hidden_state
@@ -94,7 +95,9 @@ void lstm_shape_infer(const OpsType* op,
} else {
NODE_VALIDATION_CHECK(
op,
DimType::merge(output_hidden_size, output_hidden_size, input[0].get_length() / gates_count),
DimType::merge(output_hidden_size,
output_hidden_size,
input[0].get_length() / gates_count),
"Parameter hidden_size not matched for W, R, B, initial_hidden_state and "
"initial_cell_state "
"inputs.");
@@ -115,7 +118,9 @@ void lstm_shape_infer(const OpsType* op,
} else {
NODE_VALIDATION_CHECK(
op,
DimType::merge(output_hidden_size, output_hidden_size, input[0].get_length() / gates_count),
DimType::merge(output_hidden_size,
output_hidden_size,
input[0].get_length() / gates_count),
"Parameter hidden_size not matched for W, R, B, initial_hidden_state and "
"initial_cell_state "
"inputs.");
@@ -140,9 +145,7 @@ void lstm_shape_infer(const OpsType* op,
// Check peepholes
if (input_shapes.size() == 7) {
const auto& p_pshape = input_shapes[6];
NODE_VALIDATION_CHECK(op,
(p_pshape.rank().compatible(1)),
"LSTMCell input tensor P shall have dimension 1D.");
NODE_VALIDATION_CHECK(op, (p_pshape.rank().compatible(1)), "LSTMCell input tensor P shall have dimension 1D.");
}
// check input size
@@ -66,7 +66,7 @@ void infer_prop_shape(const OpType* op,
auto out_dim = DimType{};
if (class_probs_ps.rank().is_static() && bbox_deltas_ps.rank().is_static()) {
DimType::merge(out_dim, class_probs_ps[0], bbox_deltas_ps[0]);
OPENVINO_ASSERT(DimType::merge(out_dim, class_probs_ps[0], bbox_deltas_ps[0]));
} else if (class_probs_ps.rank().is_static()) {
out_dim = class_probs_ps[0];
} else if (bbox_deltas_ps.rank().is_static()) {
@@ -62,7 +62,7 @@ void shape_infer(const ov::op::v3::ROIAlign* op, const std::vector<T>& input_sha
// if either of those 2 dimensions is static its value will be used
// for the first dimension of the output shape - 'NUM_ROIS'
if (rois_ps_rank.is_static() && batch_indices_ps_rank.is_static()) {
DimType::merge(output_shape[0], batch_indices_ps[0], rois_ps[0]);
OPENVINO_ASSERT(DimType::merge(output_shape[0], batch_indices_ps[0], rois_ps[0]));
} else if (rois_ps_rank.is_static()) {
output_shape[0] = rois_ps[0];
} else if (batch_indices_ps_rank.is_static()) {
@@ -74,4 +74,4 @@ void shape_infer(const ov::op::v3::ROIAlign* op, const std::vector<T>& input_sha
} // namespace v3
} // namespace op
} // namespace ov
} // namespace ov
@@ -0,0 +1,90 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <cstdint>
#include <openvino/core/validation_util.hpp>
#include <openvino/op/space_to_batch.hpp>
#include <openvino/opsets/opset2.hpp>
#include "utils.hpp"
namespace ov {
namespace op {
namespace v1 {
template <class T>
void shape_infer(const ov::op::v1::SpaceToBatch* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {}) {
using ValType = typename std::iterator_traits<typename T::iterator>::value_type::value_type;
NODE_VALIDATION_CHECK(op, input_shapes.size() == 4 && output_shapes.size() == 1);
const auto& data_shape = input_shapes[0];
const auto& block_shape = input_shapes[1];
const auto& pads_begin_shape = input_shapes[2];
const auto& pads_end_shape = input_shapes[3];
const ov::Rank data_rank = data_shape.rank();
bool got_const_data = false;
auto inputs_same_ps = pads_begin_shape;
NODE_VALIDATION_CHECK(op,
T::merge_into(inputs_same_ps, pads_end_shape) && T::merge_into(inputs_same_ps, block_shape),
"block_shape, pads_begin and pads_end inputs must have the same shape. Got: ",
block_shape,
", ",
pads_begin_shape,
" and ",
pads_end_shape);
NODE_VALIDATION_CHECK(op,
inputs_same_ps.rank().compatible(1),
"block_shape and pads inputs must have rank 1. Got: ",
inputs_same_ps.rank());
if (data_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
(data_shape.size() >= 2),
"The data tensor with rank lower than 2 is not supported (data rank: ",
data_shape.size(),
")");
std::vector<int64_t> block_val, pads_begin_val, pads_end_val;
auto& output_shape = output_shapes[0];
output_shape.resize(data_shape.size());
if (get_data_as_int64<T>(1, op, block_val, constant_data) &&
get_data_as_int64<T>(2, op, pads_begin_val, constant_data) &&
get_data_as_int64<T>(3, op, pads_end_val, constant_data)) {
got_const_data = true;
int64_t block_prod = std::accumulate(begin(block_val), end(block_val), 1, std::multiplies<int64_t>());
output_shape[0] = data_shape[0] * static_cast<ValType>(block_prod);
for (size_t idx = 1; idx < output_shape.size(); ++idx) {
NODE_VALIDATION_CHECK(op, block_val[idx] > 0, "block_shape values must be greater than 0");
if (data_shape[idx].is_dynamic() && data_shape[idx] == ov::Dimension::dynamic()) {
output_shape[idx] = ov::Dimension::dynamic();
} else {
const auto divided =
data_shape[idx] + static_cast<ValType>((pads_begin_val[idx] + pads_end_val[idx]));
const auto divisor = static_cast<ValType>(block_val[idx]);
output_shape[idx] = divided / divisor;
check_divided_result(op, output_shape[idx], divided, divisor);
}
}
}
}
if (!got_const_data)
// For PartialShape, Set the output to be dynamic;
// For StaticShape, throw error caused by implicitly constructing StaticShape with PartialShape argument;
output_shapes[0] = ov::PartialShape::dynamic(data_rank);
}
} // namespace v1
} // namespace op
} // namespace ov
@@ -0,0 +1,57 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <cstdint>
#include <openvino/core/validation_util.hpp>
#include <openvino/op/space_to_depth.hpp>
#include <openvino/opsets/opset1.hpp>
#include "utils.hpp"
namespace ov {
namespace op {
namespace v0 {
template <class T>
void shape_infer(const ov::op::v0::SpaceToDepth* op,
const std::vector<T>& input_shapes,
std::vector<T>& output_shapes) {
using ValType = typename std::iterator_traits<typename T::iterator>::value_type::value_type;
NODE_VALIDATION_CHECK(op, input_shapes.size() == 1 && output_shapes.size() == 1);
const auto& data_shape = input_shapes[0];
const ov::Rank data_rank = data_shape.rank();
if (data_rank.is_static()) {
NODE_VALIDATION_CHECK(op,
!(data_shape.size() < 3),
"The input tensor with rank lower than 3 is not supported (input rank: ",
data_shape.size(),
")");
const auto& block_size = op->get_block_size();
NODE_VALIDATION_CHECK(op, block_size > 0, "The block size must begreater then 0 ", block_size);
const ValType multiplier = std::pow(block_size, data_shape.size() - 2);
auto& out_shape = output_shapes[0];
out_shape.resize(data_shape.size());
out_shape[0] = data_shape[0];
out_shape[1] = data_shape[1] * multiplier;
const auto divisor = static_cast<ValType>(block_size);
for (size_t i = 2; i < out_shape.size(); i++) {
out_shape[i] = data_shape[i] / divisor;
check_divided_result(op, out_shape[i], data_shape[i], divisor);
}
} else {
// For PartialShape, Set the output to be dynamic;
// For StaticShape, will throw error caused by implicitly constructing StaticShape with PartialShape argument;
output_shapes[0] = ov::PartialShape::dynamic(data_rank);
}
}
} // namespace v0
} // namespace op
} // namespace ov
Loaded 100 of 308 files, more files were not shown because too many files have changed in this diff. Show more