Correct inf bound check for 32-bit in shape infer (#17047)

This commit is contained in:
Pawel Raasz
2023-04-19 17:33:01 +02:00
committed by GitHub
parent 3d33cb2b43
commit 4c3a4a8992
4 changed files with 65 additions and 28 deletions

View File

@@ -14,6 +14,49 @@ namespace dim {
constexpr auto inf_bound = -1; //!< Infinite bound value for dimension.
/**
* @brief Checks if dimension length is infinite bound (undefined).
*
* @tparam T Type of dimension length.
* @param dim Dimension length value.
* @return True if dimension length has infinite bound, otherwise false.
*/
template <class T>
constexpr bool is_inf_bound(const T dim) {
return dim == static_cast<T>(inf_bound);
}
/**
* @brief Convert static dimension length to ov::Dimension::value_type.
*
* As static dimension length type is size_t (bit-length depends on architecture) the maximum value (undefined)
* is convert to ov::Dimension infinite bound.
*
* @tparam T Static dimension type (size_t)
* @tparam U ov::Dimension::value_type
* @param dim Dimension length to convert.
* @return Converted input value to ov::Dimension::value_type.
*/
template <class T, class U = typename Dimension::value_type>
constexpr typename std::enable_if<std::is_same<T, size_t>::value, U>::type value_convert(const T dim) {
return is_inf_bound(dim) ? inf_bound : static_cast<U>(dim);
}
/**
* @brief Conversion of dimension when input type is same as ov::Dimension::value_type.
*
* Return value as it is.
*
* @tparam T Dimension type same as ov::Dimension::value_type.
* @tparam U Dimension::value_type.
* @param dim Dimension length to convert.
* @return Same value as input.
*/
template <class T, class U = typename Dimension::value_type>
constexpr typename std::enable_if<std::is_same<T, U>::value, U>::type value_convert(const T dim) {
return dim;
}
/**
* @brief Calculate dilated dimension value.
*
@@ -50,7 +93,7 @@ constexpr auto dilated(const TDim& dim, const typename TDim::value_type dilation
template <class TDim>
constexpr typename std::enable_if<std::is_arithmetic<TDim>::value, TDim>::type padded(const TDim dim,
const int64_t pad_num) {
return ((dim == inf_bound) || (dim + pad_num < 0)) ? inf_bound : dim + pad_num;
return (is_inf_bound(dim) || (dim + pad_num < 0)) ? inf_bound : dim + pad_num;
}
/**

View File

@@ -7,19 +7,12 @@
#include <openvino/core/validation_util.hpp>
#include <openvino/op/pad.hpp>
#include "dimension_util.hpp"
#include "utils.hpp"
namespace ov {
namespace op {
namespace v1 {
namespace pad {
inline auto calc_dim(const int64_t dim, const int64_t pad_dim_diff) -> int64_t {
constexpr auto inf_bound = -1;
const auto padded_dim = dim + pad_dim_diff;
return ((dim == inf_bound) || (padded_dim < 0)) ? inf_bound : padded_dim;
};
} // namespace pad
template <class TShape>
std::vector<TShape> shape_infer(const Pad* op,
const std::vector<TShape>& input_shapes,
@@ -117,8 +110,9 @@ std::vector<TShape> shape_infer(const Pad* op,
const auto pad_dim_diff_lb = begin_lb + end_lb;
const auto pad_dim_diff_ub = begin.second + end.second;
if ((pad_dim_diff_lb != 0) || (pad_dim_diff_ub != 0)) {
const auto lb = pad::calc_dim(dim_lb, pad_dim_diff_lb);
const auto ub = pad::calc_dim(arg_shape[i].get_max_length(), pad_dim_diff_ub);
using namespace ov::util;
const auto lb = dim::padded(dim_lb, pad_dim_diff_lb);
const auto ub = dim::padded(arg_shape[i].get_max_length(), pad_dim_diff_ub);
output_shape.emplace_back(lb, ub);
} else {
output_shape.push_back(arg_shape[i]);

View File

@@ -128,17 +128,14 @@ namespace slice {
* \return -1 for infinite number otherwise [0..int64_max] for finit step.
*/
inline int64_t get_sliced_value(const int64_t dim, const int64_t start, const int64_t stop, const int64_t step) {
using namespace ov::util;
const auto is_reverse_step = step < 0;
constexpr int64_t min_bound = 0;
constexpr int64_t inf_bound = -1;
const auto& norm_dim = dim == inf_bound ? std::numeric_limits<int64_t>::max() : dim;
#ifdef OPENVINO_ARCH_64_BIT
const auto& norm_dim = dim::is_inf_bound(dim) ? std::numeric_limits<int64_t>::max() : dim;
const auto is_norm_dim_max = ov::internal::is_max(norm_dim);
#else
const auto is_norm_dim_max = ov::internal::is_max(size_t(norm_dim));
#endif
const auto is_start_lt_min_bound = start < min_bound;
const auto are_bounds_diff_sign = is_start_lt_min_bound != (stop < 0);
@@ -151,24 +148,24 @@ inline int64_t get_sliced_value(const int64_t dim, const int64_t start, const in
int64_t lb, ub;
if (is_norm_dim_max && (are_bounds_diff_sign || any_bound_max || is_start_limit)) {
if (is_reverse_step) {
ub = (is_start_lt_min_bound || any_bound_max) ? inf_bound : inf_bound - start;
ub = (is_start_lt_min_bound || any_bound_max) ? dim::inf_bound : dim::inf_bound - start;
} else if (is_start_lt_min_bound && !is_start_limit) {
ub = is_stop_max ? -start : stop;
} else {
ub = inf_bound;
ub = dim::inf_bound;
}
lb = min_bound;
} else {
const int64_t lower_max = is_reverse_step ? norm_dim - 1 : norm_dim;
const int64_t upper_min = is_reverse_step ? inf_bound : min_bound;
const int64_t upper_min = is_reverse_step ? dim::inf_bound : min_bound;
lb = ov::util::clip(ov::util::normalize(start, norm_dim), min_bound, lower_max);
ub = ov::util::clip(ov::util::normalize(stop, norm_dim), upper_min, norm_dim);
}
// Calculate sliced value from bounds and step.
if (is_norm_dim_max && lb == min_bound && ub == inf_bound) {
return inf_bound;
if (is_norm_dim_max && lb == min_bound && dim::is_inf_bound(ub)) {
return dim::inf_bound;
} else {
// Limit sliced value to not-positive for negative step or not-negative for positive step
auto sliced_value =
@@ -312,6 +309,7 @@ std::unique_ptr<TResult> get_input_bounds(const ov::Node* op,
template <class TDim>
TDim make_dim(const TDim& dim, const Bounds& start, const Bounds& stop, int64_t step) {
using TDimVal = typename TDim::value_type;
using namespace ov::util;
const auto is_start_zero_crossing = is_bounds_zero_crossing(start);
const auto start_lb = is_start_zero_crossing && is_lb_within_dim(start.first, dim) ? 0 : start.first;
@@ -323,11 +321,11 @@ TDim make_dim(const TDim& dim, const Bounds& start, const Bounds& stop, int64_t
TDimVal lb, ub;
if (step > 0) {
lb = static_cast<TDimVal>(get_sliced_value(dim.get_min_length(), start_ub, stop_lb, step));
ub = static_cast<TDimVal>(get_sliced_value(dim.get_max_length(), start_lb, stop_ub, step));
lb = static_cast<TDimVal>(get_sliced_value(dim::value_convert(dim.get_min_length()), start_ub, stop_lb, step));
ub = static_cast<TDimVal>(get_sliced_value(dim::value_convert(dim.get_max_length()), start_lb, stop_ub, step));
} else {
lb = static_cast<TDimVal>(get_sliced_value(dim.get_min_length(), start_lb, stop_ub, step));
ub = static_cast<TDimVal>(get_sliced_value(dim.get_max_length(), start_ub, stop_lb, step));
lb = static_cast<TDimVal>(get_sliced_value(dim::value_convert(dim.get_min_length()), start_lb, stop_ub, step));
ub = static_cast<TDimVal>(get_sliced_value(dim::value_convert(dim.get_max_length()), start_ub, stop_lb, step));
}
return {lb, ub};

View File

@@ -92,8 +92,10 @@ std::vector<TShape> shape_infer(const util::TopKBase* op,
const auto k_max = k.get_max_length();
const auto lower = std::min<TDimValue>(in_min, k_min);
const auto upper = in_max < 0 ? Dimension::dynamic().get_max_length()
: std::min<TDimValue>(in_max, (k_max < 0 ? Interval::s_max : k_max));
const auto upper =
in_max < 0
? Dimension::dynamic().get_max_length()
: std::min<TDimValue>(in_max, (k_max < 0 ? std::numeric_limits<TDimValue>::max() : k_max));
dim_axis = TDim(lower, upper);
}
} else {