TVM Object类型系统

在TVM Object类型系统中最重要的是三个类:Object、ObjectPtr、ObjectRef

为什么需要这三个类?

设计目的:为了能够在不更改python前端的情况下扩展c++中的语言对象,且能够对任何语言对象序列化。

  • Object:编译器中所有的语言对象(命名一般以Node结尾)都是Object的子类,Object的子类保存了一般保存了数据成员变量
  • ObjectPtr:Object的子定义智能指针,用于进行内存管理
  • ObjectRef:Object的引用,ObjectRef的子类一般包含操作Object类的函数

代码实现

class TVM_DLL Object {protected:uint32_t type_index_{0};RefCounterType ref_counter_{0};FDeleter deleter_ = nullptr;inline void IncRef(); // 增加引用计数inline void DecRef(); // 减少引用计数private:inline int use_count() const; // 返回引用计数
};template <typename T>
class ObjectPtr {public:// 默认构造函数ObjectPtr() {}ObjectPtr(std::nullptr_t) {}// 拷贝构造,会调用构造函数从而增加引用数ObjectPtr(const ObjectPtr<T>& other) : ObjectPtr(other.data_) {}template <typename U>ObjectPtr(const ObjectPtr<U>& other) : ObjectPtr(other.data_) {static_assert(std::is_base_of<T, U>::value,"can only assign of child class ObjectPtr to parent");}// 移动构造函数,不调用构造函数,引用数不变ObjectPtr(ObjectPtr<T>&& other) : data_(other.data_) { other.data_ = nullptr; }template <typename Y>ObjectPtr(ObjectPtr<Y>&& other) : data_(other.data_) {static_assert(std::is_base_of<T, Y>::value, "can only assign of child class ObjectPtr to parent");other.data_ = nullptr;}// 析构函数~ObjectPtr() {if (data_ != nullptr) {data_->DecRef();data_ = nullptr;}// 使用计数int use_count() const { return data_ != nullptr ? data_->use_count() : 0; }// 访问成员变量T* get() const { return static_cast<T*>(data_); }T* operator->() const { return get(); }T& operator*() const { return *get(); }private:Object* data_{nullptr};// 构造函数,explicit意味着参数不能进行隐式转换explicit ObjectPtr(Object* data) : data_(data) {if (data != nullptr) {data_->IncRef();}}
};class ObjectRef {public:const Object* get() const { return data_.get(); }const Object* operator->() const { return get(); }using ContainerType = Object;protected:ObjectPtr<Object> data_;
};

ObjectPtr类中有Object*类型的data_成员变量,可以通过->操作符和get()函数返回Object*指针。
ObjectRef类中有ObjectPtr<Object>类型的data_成员变量,也可以通过->操作符和get()函数返回Object*指针(调用了data_成员变量的get()函数)。

我们以StringObj、String类为例来展示功能:

class StringObj : public Object {public:const char* data;uint64_t size;static constexpr const uint32_t _type_index = TypeIndex::kRuntimeString;static constexpr const char* _type_key = "runtime.String";TVM_DECLARE_FINAL_OBJECT_INFO(StringObj, Object);private:class FromStd; // 内部类,用于从std::string初始化data和size
};class StringObj::FromStd : public StringObj {public:explicit FromStd(std::string other) : data_container{other} {}private:std::string data_container;
};class String : public ObjectRef {public:String() : String(std::string()) {}String(std::string other);String(const char* other): String(std::string(other)) {}String(std::nullptr_t): ObjectRef(nullptr) {}const char* c_str() const { return get()->data; }const char* data() const { return get()->data; }// 类型转换运算符重载operator std::string() const { return std::string{get()->data, size()}; }size_t size() const {const auto* ptr = get();return ptr->size;}size_t length() const { return size(); }bool empty() const { return size() == 0; }char at(size_t pos) const {...}TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS(String, ObjectRef, StringObj);
};

StringObj类中定义了字符串的首字符的指针和字符串的长度,定义了类型键和类型索引,并使用了TVM_DECLARE_FINAL_OBJECT_INFO宏,定义如下:

#define TVM_DECLARE_FINAL_OBJECT_INFO(TypeName, ParentType) \static const constexpr bool _type_final = true;           \static const constexpr int _type_child_slots = 0;         \TVM_DECLARE_BASE_OBJECT_INFO(TypeName, ParentType)#define TVM_DECLARE_BASE_OBJECT_INFO(TypeName, ParentType)                                     \static_assert(!ParentType::_type_final, "ParentObj marked as final");                        \static uint32_t RuntimeTypeIndex() {                                                         \static_assert(TypeName::_type_child_slots == 0 || ParentType::_type_child_slots == 0 ||    \TypeName::_type_child_slots < ParentType::_type_child_slots,             \"Need to set _type_child_slots when parent specifies it.");                  \if (TypeName::_type_index != ::tvm::runtime::TypeIndex::kDynamic) {                        \return TypeName::_type_index;                                                            \}                                                                                          \return _GetOrAllocRuntimeTypeIndex();                                                      \}                                                                                            \static uint32_t _GetOrAllocRuntimeTypeIndex() {                                              \static uint32_t tindex = Object::GetOrAllocRuntimeTypeIndex(                               \TypeName::_type_key, TypeName::_type_index, ParentType::_GetOrAllocRuntimeTypeIndex(), \TypeName::_type_child_slots, TypeName::_type_child_slots_can_overflow);                \return tindex;                                                                             \}

TVM_DECLARE_BASE_OBJECT_INFO宏定义了两个静态变量以及两个静态函数,RuntimeTypeIndex()用于获取运行时类型索引,在StringObj构造时type_index_成员变量的值通过该函数得到。

tvm::runtime::String类中定义了对StringObj进行操作的函数,如size(),并使用了TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS宏,定义如下:

#define TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS(TypeName, ParentType, ObjectName)            \explicit TypeName(::tvm::runtime::ObjectPtr<::tvm::runtime::Object> n) : ParentType(n) {}    \TVM_DEFINE_DEFAULT_COPY_MOVE_AND_ASSIGN(TypeName);                                           \const ObjectName* operator->() const { return static_cast<const ObjectName*>(data_.get()); } \const ObjectName* get() const { return operator->(); }                                       \static constexpr bool _type_is_nullable = false;                                             \using ContainerType = ObjectName;

TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS宏定义了一个构造函数,重载了->运算符和get()函数(返回值类型不再是Object*而是StringObj*),标记该类型是不可为空的,定义了容器类型。

构造过程

构造函数String(std::string other);的实现如下:

inline String::String(std::string other) {auto ptr = make_object<StringObj::FromStd>(std::move(other));ptr->size = ptr->data_container.size();ptr->data = ptr->data_container.data();data_ = std::move(ptr);
}

可以看到在构造tvm::runtime::String时,首先使用分配器由std::string参数创建一个ObjectPtr<StringObj::FromStd>类型的对象。分配器创建完成后将StringObj::FromStddata_container的size和data直接赋值给StringObj的size和data,然后将ptr移动到tvm::runtime::Stringdata_


// include/tvm/runtime/memory.h
template <typename T, typename... Args>
inline ObjectPtr<T> make_object(Args&&... args) {return SimpleObjAllocator().make_object<T>(std::forward<Args>(args)...);
}template <typename Derived>
class ObjAllocatorBase {public:template <typename T, typename... Args>inline ObjectPtr<T> make_object(Args&&... args) {using Handler = typename Derived::template Handler<T>;static_assert(std::is_base_of<Object, T>::value, "make can only be used to create Object");T* ptr = Handler::New(static_cast<Derived*>(this), std::forward<Args>(args)...);ptr->type_index_ = T::RuntimeTypeIndex();ptr->deleter_ = Handler::Deleter();return ObjectPtr<T>(ptr);}
}

使用分配器创建时把std::string移动到了data_container中,这时调用了StringObj的构造函数,然后设置了StringObjtype_index_deleter_,最后构造(通过ObjectPtr(Object* data))并返回了ObjectPtr,在构造时增加了Object的引用数。

总结

构造ObjectRef的过程中对Object进行了构造,主要使用Object保存数据,ObjectPtr用于内存管理,ObjectRef表示引用并对数据进行操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/806103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GNU Autotools 套件详解

GNU Autotools 是一套用于构建和安装软件的工具,它包括了一系列的工具,如 `autoscan`, `aclocal`, `autoconf`, `autoheader`, `automake` 等。 这些工具的目的是简化软件的编译过程,使得软件能够在不同的操作系统和硬件平台上编译和运行。 历史背景 GNU Autotools 的历史…

操作系统(第四周 第一堂)

目录 回顾 进程调度&#xff08;process schedule&#xff09; 进程角度 计算机整体——调度队列 队列图 调度程序 总结 回顾 上一篇文章的重点只有一个————进程 对进程的了解包含以下几个方面&#xff1a;1、程序如何变为进程 2、进程在内存中的存储形式 3、进…

魔法工艺 Magicraft CE基址

魔法工艺 Magicraft CE基址 游戏版本&#xff1a;0.82.7 Magicraft.CT <?xml version"1.0" encoding"utf-8"?> <CheatTable CheatEngineTableVersion"45"><CheatEntries><CheatEntry><ID>19</ID><De…

socks5代理、代理IP、游戏技术与网络安全,探讨它们在跨界电商领域中的应用和重要性

首先&#xff0c;我们来理解socks5代理。socks5代理是一种网络协议&#xff0c;它通过一个中间服务器来转发客户端的网络请求&#xff0c;从而帮助用户绕过网络审查或访问地区性内容。与其前身socks4相比&#xff0c;socks5支持更多的认证方式和更复杂的网络通信&#xff0c;包…

【网站项目】校园二手交易平台小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

力扣HOT100 - 189. 轮转数组

解题思路&#xff1a; 三次反转。 先反转一次&#xff0c;再根据 k 拆分成两部分各反转一次。 class Solution {public void rotate(int[] nums, int k) {k % nums.length;reverse(nums, 0, nums.length - 1);reverse(nums, 0, k - 1);reverse(nums, k, nums.length - 1);}pu…

相机参数的意义

相机标定的意义&#xff1a; 相机标定&#xff1a;使用带有pattern的标定板来求解相机参数的过程&#xff1b;用一个简化的数学模型来代表复杂的三维到二维的成像过程&#xff1b;相机参数包括&#xff1a;相机内参&#xff08;焦距等&#xff09;&#xff0c;外参&#xff08…

node 的全局对象有哪些

node 和浏览器是两个不同的运行 js 的平台&#xff0c;对于浏览器来说&#xff0c;我们知道全局对象有window&#xff0c;对应的 node 中就是 global 常见的全局对象有 真正的全局对象 globalconsole console是宿主环境【node、浏览器】中的对象&#xff0c;所以我们在生产环…

【分布式缓存】

1. 缓存雪崩、缓存击穿与缓存穿透 1.1 缓存雪崩 缓存雪崩是指在缓存中的大量数据同时失效或过期&#xff0c;导致大量的请求直接打到数据库或后端系统&#xff0c;造成系统压力骤增&#xff0c;甚至导致系统崩溃。 原因&#xff1a; 缓存服务器宕机&#xff1a; 如果缓存服…

完全平方数(蓝桥杯,acwing,数论)

题目描述&#xff1a; 一个整数 a 是一个完全平方数&#xff0c;是指它是某一个整数的平方&#xff0c;即存在一个整数 b&#xff0c;使得 ab^2。 给定一个正整数 n&#xff0c;请找到最小的正整数 x&#xff0c;使得它们的乘积是一个完全平方数。 输入格式&#xff1a; 输…

[CUDA 学习笔记] 矩阵转置算子优化

矩阵转置算子优化 矩阵转置是一种基础的矩阵操作, 即将二维矩阵的行列进行反转. 本文主要围绕行主序的二维单精度矩阵的转置考虑相关的优化. 以下 kernel 笔者均是在 NVIDIA V100 (7.0 算力) 上进行测试的, 且选择矩阵的行列维度大小为 M2300 N1500. Version 0. 朴素实现 _…

处理慢查询时使用explain一般看哪些字段

explain之后会出现这些&#xff0c;一般就只看下面这几个字段 select_type就是查询类型&#xff0c;在我司的业务里基本上用的都是简单查询&#xff0c;在内存中处理逻辑&#xff0c;复杂查询的话排查问题比较麻烦&#xff0c;引起慢查询还会拖累数据库&#xff0c;数据库里还…

jvm运行情况预估

相关系统 jvm优化原则-CSDN博客 执行下面指令 jstat gc -pid 能计算出一些关键数据&#xff0c;有了这些数据&#xff0c;先给JVM参数一些的初始的&#xff0c;比堆内存大小、年轻代大小 、Eden和Srivivor的比例&#xff0c;老年代的大小&#xff0c;大对象的阈值&#xff0c;…

前端学习<四>JavaScript基础——05-变量的数据类型:基本数据类型和引用数据类型

数据分类 数据分为&#xff1a;静态数据、动态数据。 静态数据 静态数据是指一些永久性的数据。一般是以文件的形式存储在硬盘上&#xff0c;比如文档、照片、视频等文件。 电脑关闭后&#xff0c;静态数据仍然还在。只要不主动删掉数据或者硬盘没损坏&#xff0c;这些数据…

蓝桥杯c语言

蓝桥杯大赛是中国的一项全国性的IT竞赛&#xff0c;旨在激发大学生和中学生对计算机科学和技术的兴趣&#xff0c;提高他们的编程能力和创新思维。C语言是蓝桥杯大赛中的一个重要竞赛类别&#xff0c;通常包括程序设计、算法解决和数据结构实现等方面的内容。 ### 蓝桥杯C语言…

three.js尝试渲染gbl模型成功!(三)

参照教程&#xff1a;https://cloud.tencent.com/developer/article/2276766?areaSource102001.5&traceId88k805RaN_gYngNdKvALJ &#xff08;作者&#xff1a;九仞山&#xff09; 通过最近两天查three.js入门教程了解到 这玩应支持包括 .obj、.gltf等类型的模型结构。 g…

微服务-网关

在微服务架构中&#xff0c;每个服务都是一个可以独立开发和运行的组件&#xff0c;而一个完整的微服务架构由一系列独立运行的微服务组成。其中每个服务都只会完成特定领域的功能&#xff0c;比如订单服务提供与订单业务场景有关的功能、商品服务提供商品展示功能等。各个微服…

2.SpringBoot利用Thymeleaf实现页面的展示

什么是Thymeleaf&#xff1f; Thymeleaf是一个现代服务器端Java模板引擎&#xff0c;适用于Web和独立环境&#xff0c;能够处理HTML&#xff0c;XML&#xff0c;JavaScript&#xff0c;CSS甚至纯文本。 Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。为实现这…

斐讯E1拆机焊接TTL救砖

从老家的柜子里翻出来一台斐讯E1&#xff0c;老家在用的是斐讯K2P&#xff0c;300M宽带&#xff0c;房间和大部分位置wifi5足够跑满了&#xff0c;一直懒得升级&#xff0c;也足够用了。 不过发现部分位置信号比较弱&#xff0c;都不到50M&#xff0c;考虑插上E1做个AP中继&…

CASL Tutorial Chinese

Attribute-based access control (ABAC) Role-based access control (RBAC) Policy-based access control (PBAC) Claims-based access control (CBAC) 通过研究CASL&#xff0c;设计一款VUE的认证和权限的产品 do - name of the action (e.g., read, update). Has an alia…