* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*
* The code snippet comes from Ascend project.
*
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef METADEF_CXX_INC_EXE_GRAPH_TENSOR_H_
#define METADEF_CXX_INC_EXE_GRAPH_TENSOR_H_
#include <cstring>
#include "graph/ge_error_codes.h"
#include "storage_shape.h"
#include "storage_format.h"
#include "tensor_data.h"
namespace gert {
using TensorAddress = void *;
using ConstTensorAddress = void *const;
class Tensor {
public:
Tensor() {
(void) memset(reserved_, 0, sizeof(reserved_));
(void) memset(reserved_field_, 0, sizeof(reserved_field_));
}
Tensor(const StorageShape &storage_shape, const StorageFormat &storage_format, const TensorPlacement placement,
const ge::DataType data_type, TensorAddress addr)
: Tensor(storage_shape, storage_format, placement, data_type, addr, nullptr) {}
Tensor(const StorageShape &storage_shape, const StorageFormat &storage_format, ge::DataType data_type)
: storage_shape_(storage_shape), storage_format_(storage_format), data_type_(data_type) {
(void) memset(reserved_, 0, sizeof(reserved_));
(void) memset(reserved_field_, 0, sizeof(reserved_field_));
}
Tensor(const StorageShape &storage_shape, const StorageFormat &storage_format, const TensorPlacement placement,
const ge::DataType data_type, TensorAddress addr, TensorAddrManager manager)
: storage_shape_(storage_shape), storage_format_(storage_format), data_type_(data_type),
tensor_data_(addr, manager, static_cast<size_t>(ge::GetSizeInBytes(GetShapeSize(), data_type_)), placement) {
(void) memset(reserved_, 0, sizeof(reserved_));
(void) memset(reserved_field_, 0, sizeof(reserved_field_));
}
* 获取shape size,所谓shape size是指本shape中包含的element数量
* @return shape size
*/
int64_t GetShapeSize() const {
return storage_shape_.GetStorageShape().GetShapeSize();
}
* 获取Tensor的数据地址
* @tparam T 数据类型
* @return 数据地址
*/
template<class T>
const T *GetData() const {
return static_cast<const T *>(GetAddr());
}
* 获取Tensor的数据地址
* @tparam T 数据类型
* @return 数据地址
*/
template<class T>
auto GetData() -> T* {
return static_cast<T *>(GetAddr());
}
* 设置Tensor数据
* @param data 数据
*/
void SetData(TensorData &&data) {
tensor_data_ = std::move(data);
}
* 获取Tensor的数据地址
* @return 数据地址
*/
const void *GetAddr() const {
if (tensor_data_.GetPlacement() == kFollowing) {
return reinterpret_cast<const void *>(reinterpret_cast<const uint8_t *>(this) + sizeof(*this));
} else {
return tensor_data_.GetAddr();
}
}
* 获取Tensor的数据地址
* @return 数据地址
*/
void *GetAddr() {
if (tensor_data_.GetPlacement() == kFollowing) {
return reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(this) + sizeof(*this));
} else {
return tensor_data_.GetAddr();
}
}
* 获取Tensor的内存大小
* @return 内存大小
*/
size_t GetSize() const {
return tensor_data_.GetSize();
}
* 设置Tensor的内存大小
* @param Tensor的内存大小
*/
void SetSize(const size_t size) {
tensor_data_.SetSize(size);
}
* 获取Tensor的data type
* @return data type
*/
ge::DataType GetDataType() const {
return data_type_;
}
* 设置Tensor的data type
* @param data_type data type
*/
void SetDataType(const ge::DataType data_type) {
data_type_ = data_type;
}
* 创建一个Tensor,tensor数据在Tensor对象后面连续排布
* @param shape_size 元素个数
* @param dt 数据类型
* @param total_size 创建出的Tensor在内存中的长度
* @return 创建出的Tensor指针
*/
static std::unique_ptr<uint8_t[]> CreateFollowing(const int64_t shape_size, const ge::DataType dt,
size_t &total_size) {
total_size = static_cast<size_t>(ge::GetSizeInBytes(shape_size, dt));
return NewFollowingTensor(dt, total_size);
}
* 创建一个Tensor,tensor数据在Tensor对象后面连续排布
* @param tensor_size tensor长度
* @param dt 数据类型
* @param total_size 创建出的Tensor在内存中的长度
* @return 创建出的Tensor指针
*/
static std::unique_ptr<uint8_t[]> CreateFollowing(const ge::DataType dt, const size_t tensor_size,
size_t &total_size) {
total_size = tensor_size;
if (ge::AddOverflow(total_size, sizeof(Tensor), total_size)) {
return nullptr;
}
auto holder = std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[total_size]);
if (holder == nullptr) {
return nullptr;
}
auto tensor = reinterpret_cast<Tensor *>(holder.get());
new (holder.get()) Tensor({}, {}, dt);
tensor->SetPlacement(kFollowing);
tensor->tensor_data_ = TensorData(nullptr, nullptr, total_size - sizeof(Tensor), kFollowing);
return holder;
}
* 获取运行shape
* @return 只读的运行时shape引用
*/
const Shape &GetStorageShape() const {
return storage_shape_.GetStorageShape();
}
* 获取运行shape
* @return 运行时shape的引用
*/
Shape &MutableStorageShape() {
return storage_shape_.MutableStorageShape();
}
* 获取原始shape
* @return 只读的原始shape引用
*/
const Shape &GetOriginShape() const {
return storage_shape_.GetOriginShape();
}
* 获取原始shape
* @return 原始shape引用
*/
Shape &MutableOriginShape() {
return storage_shape_.MutableOriginShape();
}
* 获取shape,包含运行和原始shape
* @return 只读的shape引用
*/
const StorageShape &GetShape() const {
return storage_shape_;
}
* 获取shape,包含运行和原始shape
* @return shape引用
*/
StorageShape &GetShape() {
return storage_shape_;
}
* 获取运行时format
* @return 运行时format
*/
ge::Format GetStorageFormat() const {
return storage_format_.GetStorageFormat();
}
* 设置运行时format
* @param storage_format 运行时format
*/
void SetStorageFormat(const ge::Format storage_format) {
storage_format_.SetStorageFormat(storage_format);
}
* 获取原始format
* @return 原始format
*/
ge::Format GetOriginFormat() const {
return storage_format_.GetOriginFormat();
}
* 设置原始format
* @param origin_format 原始format
*/
void SetOriginFormat(const ge::Format origin_format) {
storage_format_.SetOriginFormat(origin_format);
}
* 获取format,format包含运行时format和原始format
* @return 只读的format引用
*/
const StorageFormat &GetFormat() const {
return storage_format_;
}
* 获取format,format包含运行时format和原始format
* @return format引用
*/
StorageFormat &MutableFormat() {
return storage_format_;
}
* 获取补维规则
* @return 补维规则
*/
ExpandDimsType GetExpandDimsType() const {
return storage_format_.GetExpandDimsType();
}
* 设置补维规则
* @param expand_dims_type 补维规则
*/
void SetExpandDimsType(const ExpandDimsType &expand_dims_type) {
storage_format_.SetExpandDimsType(expand_dims_type);
}
* 获取tensor的placement
* @return tensor的placement
*/
TensorPlacement GetPlacement() const {
return tensor_data_.GetPlacement();
}
* 设置tensor的placement
* @param tensor的placement
*/
void SetPlacement(const TensorPlacement placement) {
tensor_data_.SetPlacement(placement);
}
* 获取tensor data
* @return 只读的tensor data引用
*/
const TensorData &GetTensorData() const {
return tensor_data_;
}
* 获取tensor data
* @return 可写的tensor data引用
*/
TensorData &MutableTensorData() {
return tensor_data_;
}
private:
static std::unique_ptr<uint8_t[]> NewFollowingTensor(const ge::DataType dt, size_t &total_size) {
if (ge::AddOverflow(total_size, sizeof(Tensor), total_size)) {
return nullptr;
}
auto holder = std::unique_ptr<uint8_t[]>(new (std::nothrow) uint8_t[total_size]);
if (holder == nullptr) {
return nullptr;
}
auto tensor = reinterpret_cast<Tensor *>(holder.get());
new (holder.get()) Tensor({}, {}, dt);
tensor->SetPlacement(kFollowing);
tensor->tensor_data_ = TensorData(nullptr, nullptr, total_size - sizeof(Tensor), kFollowing);
return holder;
}
private:
StorageShape storage_shape_;
StorageFormat storage_format_;
uint8_t reserved_[4];
ge::DataType data_type_;
TensorData tensor_data_;
uint8_t reserved_field_[40];
};
static_assert(std::is_standard_layout<Tensor>::value, "The class Tensor must be a POD");
}
#endif