Merge remote-tracking branch 'upstream/master' into debian-packages
This commit is contained in:
commit
2267703a55
308 files changed
+12983
-5113
No files matched your search
@@ -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)
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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 | |
|
||||
|
||||
Vendored
+46
@@ -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
@@ -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 %}
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,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
|
||||
@@ -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>)
|
||||
|
||||
+7
@@ -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);
|
||||
|
||||
+1
-1
@@ -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})
|
||||
-24
@@ -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;
|
||||
};
|
||||
+33
@@ -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
|
||||
+28
@@ -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;
|
||||
};
|
||||
+45
@@ -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
|
||||
+1
-1
@@ -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)...);
|
||||
|
||||
-7
@@ -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);
|
||||
+61
@@ -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;
|
||||
}
|
||||
+3
@@ -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>();
|
||||
|
||||
|
||||
+47
@@ -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;
|
||||
}
|
||||
+7
-28
@@ -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);
|
||||
|
||||
|
||||
+19
@@ -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;
|
||||
}
|
||||
+18
-8
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+55
-50
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
@@ -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.
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
Reference in new issue
Block a user