223 lines
7.1 KiB
C++
223 lines
7.1 KiB
C++
// Copyright (C) 2018-2025 Intel Corporation
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <unordered_map>
|
|
|
|
#include "openvino/core/attribute_adapter.hpp"
|
|
#include "openvino/core/core_visibility.hpp"
|
|
#include "openvino/core/node_output.hpp"
|
|
#include "openvino/core/partial_shape.hpp"
|
|
#include "openvino/core/rank.hpp"
|
|
#include "openvino/core/runtime_attribute.hpp"
|
|
|
|
namespace ov {
|
|
|
|
/**
|
|
* @defgroup ov_layout_cpp_api Layout
|
|
* @ingroup ov_model_cpp_api
|
|
* OpenVINO Layout API to work and configure layouts for ov::Model inputs or outputs
|
|
*
|
|
*/
|
|
|
|
/// \brief ov::Layout represents the text information of tensor's dimensions/axes. E.g. layout `NCHW` means that 4D
|
|
/// tensor `{-1, 3, 480, 640}` will have:
|
|
/// - 0: `N = -1`: batch dimension is dynamic
|
|
/// - 1: `C = 3`: number of channels is '3'
|
|
/// - 2: `H = 480`: image height is 480
|
|
/// - 3: `W = 640`: image width is 640
|
|
///
|
|
/// Examples: `ov::Layout` can be specified for:
|
|
/// - Preprocessing purposes. E.g.
|
|
/// - To apply normalization (means/scales) it is usually required to set 'C' dimension in a layout.
|
|
/// - To resize the image to specified width/height it is needed to set 'H' and 'W' dimensions in a layout
|
|
/// - To transpose image - source and target layout can be set (see
|
|
/// `ov::preprocess::PreProcessSteps::convert_layout`)
|
|
/// - To set/get model's batch (see `ov::get_batch`/`ov::set_batch') it is required in general to specify 'N' dimension
|
|
/// in layout for appropriate inputs
|
|
///
|
|
/// Refer also to `ov::layout` namespace for various additional helper functions of `ov::Layout`
|
|
/// \ingroup ov_layout_cpp_api
|
|
class OPENVINO_API Layout {
|
|
public:
|
|
/// \brief Constructs a dynamic Layout with no layout information.
|
|
Layout();
|
|
|
|
/// \brief Constructs layout representing scalar
|
|
static Layout scalar();
|
|
|
|
/// \brief Constructs a Layout with static or dynamic layout information based
|
|
/// on string representation.
|
|
///
|
|
/// \param layoutStr The string used to construct Layout from.
|
|
/// The string representation can be in the following form:
|
|
/// - can define order and meaning for dimensions "NCHW"
|
|
/// - partial layout specialization:
|
|
/// - "NC?" defines 3 dimensional layout, first two NC, 3rd one is not defined
|
|
/// - "N...C" defines layout with dynamic rank where 1st dimension is N, last one is C
|
|
/// - "NC..." defines layout with dynamic rank where first two are NC, others are not
|
|
/// defined
|
|
/// - only order of dimensions "adbc" (0312)
|
|
/// - Advanced syntax can be used for multi-character names like "[N,C,H,W,...,CustomName]"
|
|
Layout(const char* layoutStr) : Layout(std::string(layoutStr)) {}
|
|
|
|
explicit Layout(const std::string& layoutStr);
|
|
|
|
/// \brief Comparison operator (equal)
|
|
bool operator==(const Layout& rhs) const;
|
|
|
|
/// \brief Comparison operator (not equal)
|
|
bool operator!=(const Layout& rhs) const;
|
|
|
|
/// \brief Checks if dimension with specified name is in layout
|
|
/// \return `true` if layout has information about dimension index with a given name
|
|
bool has_name(const std::string& dimensionName) const;
|
|
|
|
/// \brief Gets index of dimension with a specified name
|
|
///
|
|
/// \throws ov::AssertFailure if dimension name is not found in a layout
|
|
///
|
|
/// \return Index of given dimension name
|
|
std::int64_t get_index_by_name(const std::string& dimensionName) const;
|
|
|
|
/// \brief String representation of Layout
|
|
std::string to_string() const;
|
|
|
|
/// \brief Returns 'true' if layout has no information, i.e. equals to Layout()
|
|
bool empty() const {
|
|
return *this == Layout();
|
|
}
|
|
|
|
private:
|
|
/// stores dimension names map to index in a layout
|
|
std::unordered_map<std::string, std::int64_t> m_names;
|
|
std::unordered_map<std::int64_t, std::string> m_index_map;
|
|
|
|
/// special case for scalar
|
|
bool m_scalar = false;
|
|
|
|
bool m_dynamic = false;
|
|
int64_t m_left_size = 0;
|
|
int64_t m_right_size = 0;
|
|
|
|
friend class LayoutUtils;
|
|
};
|
|
|
|
namespace layout {
|
|
|
|
/// \brief Checks if layout has 'batch' dimension
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API bool has_batch(const Layout& layout);
|
|
|
|
/// \brief Returns 'batch' dimension index.
|
|
///
|
|
/// \throws ov::AssertFailure if dimension doesn't exist.
|
|
///
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API std::int64_t batch_idx(const Layout& layout);
|
|
|
|
/// \brief Checks if layout has 'channels' dimension
|
|
///
|
|
/// \throws ov::AssertFailure if dimension doesn't exist.
|
|
///
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API bool has_channels(const Layout& layout);
|
|
|
|
/// \brief Returns 'channels' dimension index.
|
|
///
|
|
/// \throws ov::AssertFailure if dimension doesn't exist.
|
|
///
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API std::int64_t channels_idx(const Layout& layout);
|
|
|
|
/// \brief Checks if layout has 'depth' dimension
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API bool has_depth(const Layout& layout);
|
|
|
|
/// \brief Returns 'depth' dimension index.
|
|
///
|
|
/// \throws ov::AssertFailure if dimension doesn't exist.
|
|
///
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API std::int64_t depth_idx(const Layout& layout);
|
|
|
|
/// \brief Checks if layout has 'height' dimension
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API bool has_height(const Layout& layout);
|
|
|
|
/// \brief Returns 'height' dimension index.
|
|
///
|
|
/// \throws ov::AssertFailure if dimension doesn't exist.
|
|
///
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API std::int64_t height_idx(const Layout& layout);
|
|
|
|
/// \brief Checks if layout has 'width' dimension
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API bool has_width(const Layout& layout);
|
|
|
|
/// \brief Returns 'width' dimension index.
|
|
///
|
|
/// \throws ov::AssertFailure if dimension doesn't exist.
|
|
///
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API std::int64_t width_idx(const Layout& layout);
|
|
|
|
/// \brief Sets Layout of port
|
|
///
|
|
/// \throws ov::Exception if port is not connected with Result or Parameter
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API void set_layout(ov::Output<ov::Node> output, const ov::Layout& layout);
|
|
|
|
/// \brief Gets Layout of port
|
|
///
|
|
/// \return layout from port and empty layout in other case
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API ov::Layout get_layout(const ov::Output<ov::Node>& output);
|
|
|
|
/// \brief Gets Layout of port
|
|
///
|
|
/// \return layout from port and empty layout in other case
|
|
/// \ingroup ov_layout_cpp_api
|
|
OPENVINO_API ov::Layout get_layout(const ov::Output<const ov::Node>& output);
|
|
|
|
} // namespace layout
|
|
|
|
template <>
|
|
class OPENVINO_API AttributeAdapter<Layout> : public ValueAccessor<std::string> {
|
|
public:
|
|
OPENVINO_RTTI("AttributeAdapter<Layout>");
|
|
explicit AttributeAdapter(Layout& value) : m_ref(value) {}
|
|
~AttributeAdapter() override;
|
|
|
|
const std::string& get() override;
|
|
void set(const std::string& value) override;
|
|
explicit operator Layout&() {
|
|
return m_ref;
|
|
}
|
|
|
|
protected:
|
|
Layout& m_ref;
|
|
std::string m_dump;
|
|
};
|
|
|
|
class OPENVINO_API LayoutAttribute : public ov::RuntimeAttribute {
|
|
public:
|
|
OPENVINO_RTTI("layout", "0", RuntimeAttribute);
|
|
|
|
LayoutAttribute() = default;
|
|
|
|
explicit LayoutAttribute(const Layout& value) : value(value) {}
|
|
|
|
bool visit_attributes(AttributeVisitor& visitor) override;
|
|
|
|
std::string to_string() const override;
|
|
|
|
Layout value;
|
|
};
|
|
|
|
} // namespace ov
|