Skip to content

Commit 0c0cb1c

Browse files
authored
Merge branch 'master' into yet_another_staging_testing
2 parents c9be7d1 + 09d1712 commit 0c0cb1c

File tree

27 files changed

+779
-284
lines changed

27 files changed

+779
-284
lines changed

docs/articles_en/openvino-workflow/running-inference/optimize-inference/precision-control.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,35 @@ capabilities).
9494
for ``inference_precision`` attribute.
9595

9696

97+
Activation Scaling
98+
###################
99+
100+
Since ``f16`` has a smaller dynamic range compared to ``f32`` or ``bf16``, overflow might occur when using ``f16`` for ``inference_precision``.
101+
To address this issue, activation scaling divides the input of linear operations such as ``MatMul`` or ``Convolution`` by an activations scale factor, ensuring the layer's output does not exceed ``f16``'s dynamic range.
102+
103+
The layer's output is then multiplied back by the activations scale factor to restore its original value, but overflow can occur again during this process.
104+
Activation scaling uses :doc:`LPT (Low Precision Transformations) <../../../documentation/openvino-extensibility/openvino-plugin-library/advanced-guides/low-precision-transformations>` to delay multiplication by the scale factor as much as possible, preventing overflow.
105+
The activations scale factor can be specified in the ``rt_info`` of the model IR or via ``ov::hint::activations_scale_factor``.
106+
Currently, this property is supported on GPU.
107+
108+
.. scrollbox::   
109+
110+
.. code-block:: cpp
111+
112+
<?xml version="1.0" ?>
113+
<net name="model_file_name" version="10">
114+
...
115+
<rt_info>
116+
...
117+
<runtime_options>
118+
<ACTIVATIONS_SCALE_FACTOR value="8.0" />
119+
</runtime_options>
120+
...
121+
</rt_info>
122+
</net>
123+
124+
125+
97126
.. _limited_inference_precision:
98127

99128
Limitation of the ``bf16`` inference precision

src/bindings/c/include/openvino/c/openvino.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@
3737
#include "openvino/c/ov_remote_context.h"
3838
#include "openvino/c/ov_shape.h"
3939
#include "openvino/c/ov_tensor.h"
40+
#include "openvino/c/ov_util.h"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#pragma once
6+
7+
#include "openvino/c/ov_common.h"
8+
9+
/**
10+
* @brief Callback function type for logging messages.
11+
* @param message The log message as a null-terminated C string.
12+
*/
13+
typedef void (*ov_util_log_callback_func)(const char* message);
14+
15+
/**
16+
* @brief Sets user log message handling callback.
17+
* @param [in] func The function pointer to user-defined message logging callback.
18+
* Null pointer is accepted (no logging).
19+
*/
20+
OPENVINO_C_API(void)
21+
ov_util_set_log_callback(ov_util_log_callback_func func);
22+
23+
/**
24+
* @brief Resets log message handling callback to its default (standard output).
25+
*/
26+
OPENVINO_C_API(void)
27+
ov_util_reset_log_callback();

src/bindings/c/src/ov_util.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include "openvino/c/ov_util.h"
6+
7+
#include "openvino/core/log.hpp"
8+
9+
void ov_util_set_log_callback(ov_util_log_callback_func f) {
10+
if (f) {
11+
static std::function<void(std::string_view)> callback;
12+
callback = [f](std::string_view msg) {
13+
f(msg.data());
14+
};
15+
ov::util::set_log_callback(callback);
16+
} else {
17+
ov::util::set_log_callback({});
18+
}
19+
}
20+
21+
void ov_util_reset_log_callback() {
22+
ov::util::reset_log_callback();
23+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include <gtest/gtest.h>
6+
7+
#include <cstring>
8+
9+
#include "openvino/c/openvino.h"
10+
#include "openvino/util/log.hpp"
11+
12+
namespace {
13+
void test_log_msg(const char* msg) {
14+
ov::util::LogHelper{ov::util::LOG_TYPE::_LOG_TYPE_INFO, "1664804", 101}.stream() << msg;
15+
}
16+
17+
std::string got_message;
18+
void callback_func(const char* msg) {
19+
got_message = msg;
20+
}
21+
bool compare_msg(const char* msg) {
22+
const auto msg_size = std::strlen(msg);
23+
if (got_message.size() < msg_size) {
24+
return false;
25+
}
26+
return std::strncmp(msg, got_message.data() + got_message.size() - msg_size, msg_size) == 0;
27+
}
28+
} // namespace
29+
30+
TEST(ov_util, set_log_callback) {
31+
got_message.clear();
32+
test_log_msg("default");
33+
EXPECT_TRUE(got_message.empty());
34+
ov_util_set_log_callback(&callback_func);
35+
const char test_msg[] = "callback";
36+
test_log_msg(test_msg);
37+
EXPECT_TRUE(compare_msg(test_msg));
38+
}
39+
40+
TEST(ov_util, reset_log_callback) {
41+
got_message.clear();
42+
ov_util_set_log_callback(&callback_func);
43+
ov_util_reset_log_callback();
44+
test_log_msg("default");
45+
EXPECT_TRUE(got_message.empty());
46+
}
47+
48+
TEST(ov_util, no_log_callback) {
49+
got_message.clear();
50+
ov_util_set_log_callback(NULL);
51+
EXPECT_NO_THROW(test_log_msg("default"));
52+
EXPECT_TRUE(got_message.empty());
53+
}

src/core/shape_inference/include/pad_shape_inference.hpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,16 @@ std::vector<TRShape> shape_infer(const util::PadBase* op,
123123
}
124124
}
125125
} else {
126-
NODE_SHAPE_INFER_CHECK(
127-
op,
128-
input_shapes,
129-
pads_begin_rank.is_dynamic() || cmp::le(pads_begin_shape[0].get_length(), arg_rank_len),
130-
"Number of elements of pads_begin must be >= 0 and <= arg rank");
131-
NODE_SHAPE_INFER_CHECK(
132-
op,
133-
input_shapes,
134-
pads_begin_rank.is_dynamic() || cmp::le(pads_end_shape[0].get_length(), arg_rank_len),
135-
"Number of elements of pads_end must be >= 0 and <= arg rank");
126+
NODE_SHAPE_INFER_CHECK(op,
127+
input_shapes,
128+
pads_begin_rank.is_dynamic() || pads_begin_shape[0].is_dynamic() ||
129+
cmp::le(pads_begin_shape[0].get_length(), arg_rank_len),
130+
"Number of elements of pads_begin must be >= 0 and <= arg rank");
131+
NODE_SHAPE_INFER_CHECK(op,
132+
input_shapes,
133+
pads_end_rank.is_dynamic() || pads_end_shape[0].is_dynamic() ||
134+
cmp::le(pads_end_shape[0].get_length(), arg_rank_len),
135+
"Number of elements of pads_end must be >= 0 and <= arg rank");
136136
output_shape.resize(arg_shape_rank.get_length());
137137
}
138138
} else {

src/core/tests/type_prop/pad.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,24 @@ TYPED_TEST_P(PadTest, pad_begin_and_end_has_inf_interval_as_bounds) {
280280
EXPECT_THAT(get_shape_symbols(pad->get_output_partial_shape(0)), Each(nullptr));
281281
}
282282

283+
TYPED_TEST_P(PadTest, pad_begin_and_end_dynamic) {
284+
auto arg_shape = PartialShape{9, {3, 5}, {3, 5}, {3, 4}, {3, 4}};
285+
auto begin_shape = PartialShape{-1};
286+
auto end_shape = PartialShape{-1};
287+
set_shape_symbols(arg_shape);
288+
set_shape_symbols(begin_shape);
289+
set_shape_symbols(end_shape);
290+
291+
auto arg = make_shared<op::v0::Parameter>(element::f32, arg_shape);
292+
auto begin = make_shared<op::v0::Parameter>(element::i32, begin_shape);
293+
auto end = make_shared<op::v0::Parameter>(element::i32, end_shape);
294+
295+
auto pad = this->make_op(arg, begin, end, op::PadMode::CONSTANT);
296+
297+
EXPECT_EQ(pad->get_output_partial_shape(0), PartialShape({-1, -1, -1, -1, -1}));
298+
EXPECT_THAT(get_shape_symbols(pad->get_output_partial_shape(0)), Each(nullptr));
299+
}
300+
283301
REGISTER_TYPED_TEST_SUITE_P(PadTest,
284302
pad_default_ctor,
285303
pad_arg_pad_value_type_mismatch,
@@ -301,7 +319,8 @@ REGISTER_TYPED_TEST_SUITE_P(PadTest,
301319
pad_dynamic_input_type_with_static_value,
302320
pad_preserve_partial_values_and_symbols_via_evaluates_bounds,
303321
pad_begin_and_end_has_inf_interval_as_bounds,
304-
pad_preserve_partial_values_and_symbols_on_inputs);
322+
pad_preserve_partial_values_and_symbols_on_inputs,
323+
pad_begin_and_end_dynamic);
305324

306325
using PadOpTypes = Types<op::v1::Pad, op::v12::Pad>;
307326
INSTANTIATE_TYPED_TEST_SUITE_P(type_prop, PadTest, PadOpTypes);

src/frontends/common_translators/include/common_translators.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ COMMON_OP_CONVERTER(translate_erfc);
2222

2323
COMMON_OP_CONVERTER(translate_equal);
2424

25+
COMMON_OP_CONVERTER(translate_unsqueeze);
26+
2527
OutputVector translate_atan2_util(const NodeContext& context, const Output<Node>& lhs, const Output<Node>& rhs);
2628
OutputVector translate_erfc_util(const NodeContext& context, const Output<Node>& data);
2729

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include "openvino/op/unsqueeze.hpp"
6+
7+
#include "common_translators.hpp"
8+
#include "openvino/core/validation_util.hpp"
9+
#include "openvino/frontend/complex_type_mark.hpp"
10+
#include "openvino/op/convert.hpp"
11+
#include "openvino/op/less.hpp"
12+
#include "openvino/op/select.hpp"
13+
#include "openvino/op/subtract.hpp"
14+
#include "utils.hpp"
15+
16+
using namespace ov::op;
17+
18+
namespace ov {
19+
namespace frontend {
20+
namespace common_translators {
21+
22+
OutputVector translate_unsqueeze(const NodeContext& context) {
23+
num_inputs_check(context, 2, 2, true);
24+
auto x = context.get_input(0);
25+
auto dim = context.get_input(1);
26+
27+
auto complex = as_type_ptr<ComplexTypeMark>(x.get_node_shared_ptr());
28+
bool is_complex = complex != nullptr;
29+
30+
if (is_complex) {
31+
if (dim.get_element_type() != element::i32) {
32+
dim = context.mark_node(std::make_shared<v0::Convert>(dim, element::i32));
33+
}
34+
35+
auto data = complex->get_input_source_output(0);
36+
37+
auto one = context.mark_node(v0::Constant::create(element::i32, Shape{1}, {1}));
38+
39+
auto zero = context.mark_node(v0::Constant::create(element::i32, Shape{1}, {0}));
40+
41+
auto neg_dim = context.mark_node(std::make_shared<v1::Subtract>(dim, one));
42+
auto zero_cond = context.mark_node(std::make_shared<v1::Less>(dim, zero));
43+
auto new_dim = context.mark_node(std::make_shared<v1::Select>(zero_cond, neg_dim, dim));
44+
const auto dim_const = ov::util::get_constant_from_source(new_dim);
45+
auto res = context.mark_node(std::make_shared<v0::Unsqueeze>(data, dim_const));
46+
res = context.mark_node(std::make_shared<ComplexTypeMark>(res));
47+
return {res};
48+
}
49+
50+
auto res = context.mark_node(std::make_shared<v0::Unsqueeze>(x, dim));
51+
return {res};
52+
};
53+
54+
} // namespace common_translators
55+
} // namespace frontend
56+
} // namespace ov

src/frontends/pytorch/src/frontend.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#include "transforms/index_loop_getitem_replacer.hpp"
3333
#include "transforms/listconstruct_replacer.hpp"
3434
#include "transforms/min_max_prim_list_construct_replacer.hpp"
35-
#include "transforms/prim_list_construct_pad.hpp"
3635
#include "transforms/prim_list_tuple_construct_replacer.hpp"
3736
#include "transforms/prim_list_unpack_replacer.hpp"
3837
#include "transforms/prim_unpack_parameter_replacer.hpp"
@@ -317,7 +316,6 @@ void FrontEnd::normalize(const std::shared_ptr<ov::Model>& model) const {
317316
// TODO: remove AtenIndexToSelect when problem with dynamic input rank is gone.
318317
manager.register_pass<ov::frontend::pytorch::pass::AtenIndexToSelect>();
319318
manager.register_pass<ov::frontend::pytorch::pass::AtenIndexPutReplacer>();
320-
manager.register_pass<ov::frontend::pytorch::pass::PrimListConstructPadReplacer>();
321319
manager.register_pass<ov::frontend::pytorch::pass::IndexLoopGetitemReplacer>();
322320

323321
// Check if model is symmetrically quantized

0 commit comments

Comments
 (0)