Skip to content

[core] Fix ov::Tensor::data access perfomance #30673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/core/dev_api/openvino/core/type/element_type_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (C) 2018-2025 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <cstdint>
#include <string>

#include "openvino/core/type/element_type.hpp"

namespace ov::element {

struct TypeInfo {
size_t m_bitwidth;
bool m_is_real;
bool m_is_signed;
bool m_is_quantized;
const char* m_cname;
const char* m_type_name;
const char* const* aliases;
size_t alias_count;

bool has_name(const std::string& type) const {
if (type == m_type_name) {
return true;
} else {
const auto last = aliases + alias_count;
return std::find(aliases, last, type) != last;
}
}

constexpr bool is_valid() const {
return m_cname != nullptr && m_type_name != nullptr;
}
};

/**
* @brief Get TypeInfo of given element type.
*
* @param type Openvino element type to get its description.
* @return Reference to TypeInfo.
*/
OPENVINO_API const TypeInfo& get_type_info(Type_t type);

} // namespace ov::element
15 changes: 12 additions & 3 deletions src/core/dev_api/openvino/runtime/itensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,25 @@ class OPENVINO_API ITensor : public std::enable_shared_from_this<ITensor> {
*/
virtual const ov::Strides& get_strides() const = 0;

/**
* @brief Provides an access to the underlying host memory
* @return A host pointer to tensor memory
* @{
*/
virtual void* data();
virtual const void* data() const = 0;
/// @}

/**
* @brief Provides an access to the underlying host memory
* @param type Optional type parameter.
* @note If type parameter is specified, the method throws an exception
* @note The method throws an exception
* if specified type's fundamental type does not match with tensor element type's fundamental type
* @return A host pointer to tensor memory
* @{
*/
virtual void* data(const element::Type& type = {});
virtual const void* data(const element::Type& type = {}) const = 0;
virtual void* data(const element::Type& type);
virtual const void* data(const element::Type& type) const = 0;
/// @}

/**
Expand Down
23 changes: 18 additions & 5 deletions src/core/include/openvino/runtime/tensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,17 +219,30 @@ class OPENVINO_API Tensor {

/**
* @brief Provides an access to the underlying host memory
* @param type Optional type parameter.
* @note If type parameter is specified, the method throws an exception
* if specified type's fundamental type does not match with tensor element type's fundamental type
* @return A host pointer to tensor memory
* @{
*/

#ifndef IN_OV_COMPONENT
OPENVINO_DEPRECATED("This function will return const void* in 2026.0. Check if used correctly")
#endif
void* data() const;
void* data();
/// @}

/**
* @brief Provides an access to the underlying host memory
* @param type Optional type parameter.
* @note The method throws an exception
* if specified type's fundamental type does not match with tensor element type's fundamental type
* @return A host pointer to tensor memory
* @{
*/
#ifndef IN_OV_COMPONENT
OPENVINO_DEPRECATED("This function will return const void* in 2026.0. Check if used correctly")
#endif
void* data(const element::Type& type = {}) const;
void* data(const element::Type& type = {});
void* data(const element::Type& type) const;
void* data(const element::Type& type);
/// @}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/core/src/runtime/itensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ void ITensor::copy_to(const std::shared_ptr<ov::ITensor>& dst) const {
}
}

void* ITensor::data() {
return const_cast<void*>(std::as_const(*this).data());
}

void* ITensor::data(const element::Type& type) {
return const_cast<void*>(static_cast<const ITensor*>(this)->data(type));
}
Expand Down
8 changes: 8 additions & 0 deletions src/core/src/runtime/tensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ size_t Tensor::get_byte_size() const {
OV_TENSOR_STATEMENT(return _impl->get_byte_size(););
}

void* Tensor::data() {
OV_TENSOR_STATEMENT(return _impl->data());
}

void* Tensor::data() const {
OV_TENSOR_STATEMENT(return const_cast<void*>(std::as_const(*_impl).data()););
}

void* Tensor::data(const element::Type& element_type) {
OV_TENSOR_STATEMENT(return _impl->data(element_type));
}
Expand Down
39 changes: 8 additions & 31 deletions src/core/src/type/element_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <string_view>
#include <unordered_map>

#include "openvino/core/type/element_type_info.hpp"
#include "openvino/core/type/element_type_traits.hpp"
#include "openvino/util/common_util.hpp"

Expand All @@ -22,30 +23,6 @@ constexpr size_t idx(Type_t e) noexcept {
// Update it when new type is added
constexpr size_t enum_types_size = idx(f8e8m0) + 1;

struct TypeInfo {
size_t m_bitwidth;
bool m_is_real;
bool m_is_signed;
bool m_is_quantized;
const char* m_cname;
const char* m_type_name;
const char* const* aliases;
size_t alias_count;

bool has_name(const std::string& type) const {
if (type == m_type_name) {
return true;
} else {
const auto last = aliases + alias_count;
return std::find(aliases, last, type) != last;
}
}

constexpr bool is_valid() const {
return m_cname != nullptr && m_type_name != nullptr;
}
};

template <class Array>
constexpr TypeInfo type_info(size_t bitwidth,
bool is_real,
Expand Down Expand Up @@ -133,12 +110,6 @@ size_t type_idx_for(const std::string& type_name) {
return type_idx;
}

const TypeInfo& get_type_info(Type_t type) {
const auto type_idx = idx(type);
OPENVINO_ASSERT(is_valid_type_idx(type_idx), "Type_t not supported: ", type_idx);
return types_info[type_idx];
}

Type type_from_string(const std::string& type) {
const auto type_idx = type_idx_for(type);
OPENVINO_ASSERT(is_valid_type_idx(type_idx), "Unsupported element type: ", type);
Expand All @@ -155,6 +126,12 @@ static constexpr auto known_types = [] {
}();
} // namespace

const TypeInfo& get_type_info(Type_t type) {
const auto type_idx = idx(type);
OPENVINO_ASSERT(is_valid_type_idx(type_idx), "Type_t not supported: ", type_idx);
return types_info[type_idx];
}

std::vector<const Type*> Type::get_known_types() {
std::vector<const Type*> result(known_types.size());
for (size_t i = 0; i < known_types.size(); ++i) {
Expand Down Expand Up @@ -275,7 +252,7 @@ bool Type::merge(Type& dst, const Type& t1, const Type& t2) {
}

bool Type::is_static() const {
return get_type_info(m_type).m_bitwidth != 0;
return m_type != Type_t::dynamic;
}

bool Type::is_real() const {
Expand Down
6 changes: 5 additions & 1 deletion src/inference/dev_api/openvino/runtime/iremote_tensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ namespace ov {

class OPENVINO_RUNTIME_API IRemoteTensor : public ITensor {
public:
const void* data(const element::Type& type = {}) const override final {
const void* data() const override final {
OPENVINO_NOT_IMPLEMENTED;
}

const void* data(const element::Type& type) const override final {
OPENVINO_NOT_IMPLEMENTED;
}

Expand Down
33 changes: 26 additions & 7 deletions src/inference/src/dev/make_tensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <mutex>

#include "openvino/core/type/element_iterator.hpp"
#include "openvino/core/type/element_type_info.hpp"
#include "openvino/runtime/iremote_tensor.hpp"
#include "openvino/runtime/properties.hpp"
#include "openvino/runtime/tensor.hpp"
Expand Down Expand Up @@ -57,14 +58,18 @@ class ViewTensor : public ITensor {
OPENVINO_ASSERT(m_element_type.is_static());
}

const void* data() const override {
return m_ptr;
}

const void* data(const element::Type& element_type) const override {
if (!is_pointer_representable(element_type)) {
OPENVINO_THROW("Tensor data with element type ",
get_element_type(),
", is not representable as pointer to ",
element_type);
}
return m_ptr;
return data();
}

const element::Type& get_element_type() const override {
Expand Down Expand Up @@ -92,11 +97,17 @@ class ViewTensor : public ITensor {

protected:
bool is_pointer_representable(const element::Type& element_type) const {
return element_type.is_dynamic() ||
((get_element_type() != element::string && element_type != element::string &&
element_type.bitwidth() == get_element_type().bitwidth() &&
element_type.is_real() == get_element_type().is_real()) ||
(element_type == element::string && element::string == get_element_type()));
if (element_type.is_dynamic()) {
return true;
} else {
// gets type info to reduce validation to access speed, due to performance issues
const auto& other_type_info = element::get_type_info(element_type);
const auto& this_type_info = element::get_type_info(get_element_type());
return (get_element_type() != element::string && element_type != element::string &&
other_type_info.m_bitwidth == this_type_info.m_bitwidth &&
other_type_info.m_is_real == this_type_info.m_is_real) ||
(element_type == element::string && element::string == get_element_type());
}
}

void update_strides() const {
Expand Down Expand Up @@ -134,9 +145,13 @@ class ReadOnlyViewTensor : public ViewTensor {

using ViewTensor::data;

[[noreturn]] void* data(const element::Type& element_type) override {
[[noreturn]] void* data() override {
OPENVINO_THROW("Can not access non-const pointer use e.g. 'static_cast<const ov::Tensor&>.data()'");
}

[[noreturn]] void* data(const element::Type& element_type) override {
OPENVINO_THROW("Can not access non-const pointer use e.g. 'static_cast<const ov::Tensor&>.dataelement_type)'");
}
};

/**
Expand Down Expand Up @@ -416,6 +431,10 @@ class RoiTensor : public BaseRoiTensor, public ITensor {
BaseRoiTensor::set_shape(new_shape);
}

const void* data() const override {
return static_cast<uint8_t*>(m_owner->data()) + m_offset;
}

const void* data(const element::Type& element_type) const override {
auto owner_data = m_owner->data(element_type);
return static_cast<uint8_t*>(owner_data) + m_offset;
Expand Down
6 changes: 5 additions & 1 deletion src/plugins/intel_cpu/src/cpu_tensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ void Tensor::update_strides() const {
});
}

const void* Tensor::data() const {
return m_memptr->getData();
}

const void* Tensor::data(const element::Type& element_type) const {
if (element_type.is_static()) {
OPENVINO_ASSERT(element_type == get_element_type(),
Expand All @@ -91,7 +95,7 @@ const void* Tensor::data(const element::Type& element_type) const {
", is not representable as pointer to ",
element_type);
}
return m_memptr->getData();
return data();
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/plugins/intel_cpu/src/cpu_tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Tensor : public ITensor {

const ov::Strides& get_strides() const override;

const void* data() const override;
const void* data(const element::Type& type) const override;

MemoryPtr get_memory() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ class USMHostTensor : public ov::ITensor {

~USMHostTensor() override = default;

const void* data() const override;
const void* data(const element::Type& element_type) const override;

const element::Type& get_element_type() const override;

const Shape& get_shape() const override;
Expand Down
6 changes: 5 additions & 1 deletion src/plugins/intel_gpu/src/plugin/usm_host_tensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ USMHostTensor::USMHostTensor(std::shared_ptr<RemoteContextImpl> context, const e
USMHostTensor::USMHostTensor(std::shared_ptr<RemoteTensorImpl> tensor)
: m_impl(tensor) {}

const void* USMHostTensor::data(const element::Type& element_type) const {
const void* USMHostTensor::data() const {
return m_impl->get_original_memory()->buffer_ptr();
}

const void* USMHostTensor::data(const element::Type&) const {
return data();
}

const element::Type& USMHostTensor::get_element_type() const {
return m_impl->get_element_type();
}
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/intel_npu/src/backend/include/zero_tensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class ZeroTensor final : public ov::ITensor {
const ov::Shape& shape,
const ov::Allocator& allocator);

const void* data(const ov::element::Type& type = {}) const override;
const void* data() const override;
const void* data(const ov::element::Type& type) const override;

const ov::element::Type& get_element_type() const override;

Expand Down
6 changes: 5 additions & 1 deletion src/plugins/intel_npu/src/backend/src/zero_tensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ ZeroTensor::ZeroTensor(const std::shared_ptr<ZeroInitStructsHolder>& init_struct
_ptr = data;
}

const void* ZeroTensor::data() const {
return _ptr;
}

const void* ZeroTensor::data(const ov::element::Type& element_type) const {
if (element_type != ov::element::dynamic &&
(element_type.bitwidth() != get_element_type().bitwidth() ||
Expand All @@ -44,7 +48,7 @@ const void* ZeroTensor::data(const ov::element::Type& element_type) const {
", is not representable as pointer to ",
element_type);
}
return _ptr;
return data();
}

const ov::element::Type& ZeroTensor::get_element_type() const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class ZeroHostTensor : public ov::ITensor {

~ZeroHostTensor() override = default;

const void* data() const override;
const void* data(const ov::element::Type& element_type) const override;
const ov::element::Type& get_element_type() const override;

Expand Down
Loading
Loading