1 指针类实现

1 intrusive_ptr_target 类

1)该类主要构建了两个计数器,且支持拷贝和移动构造。但是对于拷贝和移动构造没有执行任何动作,不改变原有计数器的数值。

2)声明了两个友元类和友元函数,其中友元函数不是类函数,还是特殊作用域下的函数。

3)当其他类继承这个类时,将自动维护两个计数器,而不需要在intrusive ptr中维护计数器。

从目前来看,intrusive_ptr想对于shared_ptr而言,其对应的引用计数的方式被修改了,并且要求对于T是继承于intrusive_ptr_target.

主要私有变量:mutable std::atomic<size_t> refcount_;mutable std::atomic<size_t> weakcount_;
友元:template <typename T, typename NullType>friend class intrusive_ptr;friend inline void raw::intrusive_ptr::incref(intrusive_ptr_target* self);template <typename T, typename NullType>friend class weak_intrusive_ptr;friend inline void raw::weak_intrusive_ptr::incref(intrusive_ptr_target* self);

2 intrusive_ptr类

1)私有函数reset_()看,只有当类中维护的指针对象的refcount_和weakcount_都减为0时,才会出发delete对象动作。(在该类的处理中,只会操作refcount_, 不会操作weakcount_)

2)建议通过make_intrusive(),reclaim() and weak_intrusive_ptr::lock()方式创建intrusive_ptr。

2.1)make_intrusive(),调用私有构造函数构造intrusive_ptr,增加refcount_和weakcount_计数

2.2)reclaim()不增加计数器,需要特别注意。(如果需要特别考虑,可以使用unsafe_reclaim_from_nonowning)

2.3)weak_intrusive_ptr::lock()

3)release()操作不会减少refcount_,所以该操作只能把获取的指针重新放回intrusive_ptr,才是安全的。

4)unsafe_steal_from_new可以调用私有构造函数构造intrusive_ptr,增加refcount_和weakcount_计数。(如果使用裸指针对象创建intrusive_ptr,debug模式会检查refcount_和weakcount_必须要为0)

5)对应的operator比较等操作,都是通过包裹对应T定义的opertor方法进行处理。

6)私有函数retain_()只会操作refcount_。

特别说明1:

  intrusive_ptr& operator=(intrusive_ptr&& rhs) & noexcept {return operator=<TTarget, NullType>(std::move(rhs)); // 调用模板函数operator=,其通过编译器static_assert函数判断,from和ttarget是可转换的类型,从而此处直接用目标类型,而不是rhs的类型检查获取。}template <class From, class FromNullType>intrusive_ptr& operator=(intrusive_ptr<From, FromNullType>&& rhs) & noexcept {static_assert(std::is_convertible<From*, TTarget*>::value,"Type mismatch. intrusive_ptr move assignment got pointer of wrong type.");intrusive_ptr tmp = std::move(rhs);swap(tmp);return *this;}

特别说明2:

  template <class TTarget,class NullType = detail::intrusive_target_default_null_type<TTarget>>class intrusive_ptr final {  ...template <class TTarget2, class NullType2>  // 可以访问特化实现对象的私有成员变量friend class intrusive_ptr;...}

3 MaybeOwnedTraits特化类MaybeOwnedTraits<c10::intrusive_ptr<T>>

逻辑上使用该类,需要非常谨慎。需要显示地销毁对应接口获得的intrusive_ptr。

1)createBorrow和assignBorrow不改变引用计数,调用reclaim进行操作。

2)destroyBorrow不改变引用基数,只是将自身置为nullptr,调用release()操作。

3)源文件路径: c10/util/MaybeOwned.h

4 weak_intrusive_ptr类

1)私有函数retain_和reset_只会操作weakcount_计数器。

2)通过intrusive_ptr构造weak_intrusive_ptr对象时,只改变weakcount_计数器。其他自身的拷贝和移动构造,常规操作。

3)release()和reclaim()函数都不改变weakcount_计数器。

代码路经:

c10/util/intrusive_ptr.h

c10/util/intrusive_ptr.cpp

2 使用案例

c10::intrusive_ptr 的初始化需要 intrusive_ptr_target 或者其子类。
TensorImpl 和 StorageImpl 两个类分别为intrusive_ptr_target 的子类,然后StorageImpl 主要负责 tensor 的实际物理内存相关的操作,设置空间配置器,获取数据指针,以及占用物理空间大小等; Storage 仅仅是对 StorageImpl 直接包了一下,直接调用的是 StorageImpl 的相关成员函数。TensorImpl 是 Tensor 类实现的主要依赖类,,其初始化就需要依赖 Storage 类,所以上面说:Tensor = TensorImpl + StorgaeImpl。

上述文字及图片截图链接:[Pytorch 源码阅读] —— Tensor C++相关实现_c++ tensor_Chris_zhangrx的博客-CSDN博客

1 StorageImpl类

代码路经: c10/core/StorageImpl.h

1)其继承于intrusive_ptr_target,其构造的时候,默认调用intrusive_ptr_target的默认构造,增加其refcount_和weakcount_的引用计数。

2)其中主要的私有变量为: DataPtr, SymInt, Allocator*, resizable_。

2.1)DataPtr结构体主要为一个智能指针 + 设备信息;

2.1.1)智能指针为UniqueVoidPtr,其主要包含一个ptr和unique_ptr(ptr + deleter function); ----为什么这么设计?

2.1.2)设备信息就是设备类型和设备index。

2.2)SymInt就是一个long数据类型的包装。

2.3)resizable_ 可否被resize?

3)支持移动构造,不支持拷贝构造。不支持默认构造,默认的稀构。

4)存在接口可以直接通过裸指针构造,UniqueStorageShareExternalPointer。

2)Storage类

代码路经:c10/core/Storage.h

1)protected成员变量为c10::intrusive_ptr<StorageImpl> storage_impl_。

2)本质就是对storage_impl的再次封装。但由于其包裹的是storage_impl的智能指针,其可以做更多的事情,比如拷贝构造,空构造,拷贝赋值等处理。

3)TensorImpl类

代码路经: c10/core/TensorImpl.h

1)不支持移动和复制构造,也不支持移动和赋值操作;

2)只支持storage的右值构造,而storage主要是一个intrusive_ptr包裹的stroage_impl; 或者dispatch_key的一个构造函数。其他均不支持。

3)新增了police的控制策略,用户可以自定义size,stride等metadata的行为。

辅助类介绍:

1)SizesAndStrides:用于存储tensor的size和stride信息。当size<=5时,存储在栈空间inlineStorage_,当超过5时,存储在堆outOfLineStorage_上。(大小分别都是2×size_)

2)VariableVersion:主要是一个intrusive_ptr包裹的atomic计数器。其实用来记录saved variable是否被修改。当进行inplace操作或者set_data或者.data的操作后,其计数器会增长。

3)AutogradMetaInterface:父类定义,后续AutogradMeta对其进行真实的实现。 这么处理的原因是AutogradMeta定义在单独的编译单元,TensorImpl无法对其进行实例化。故通过父类接口完成对于子类实现的调用。

4)AutogradMetaFactory:父类定义,后续ConcreteAutogradMetaFactory对其进行真实的实现。其中ConcreteAutogradMetaFactory通过注册类AutogradMetaFactoryRegisterer,完成ConcreteAutogradMetaFactory对象到AutogradMetaFactory类中注册,后续调用接口都是基于ConcreteAutogradMetaFactory的对象完成。调用impl::GetAutogradMetaFactory()→make()获取AutogradMeta的对象指针。

具体关系如下:

pytorch基于intrusive_ptr_target实现的核心数据结构介绍相关推荐

  1. 基于pytorch的sque2suqe with attention实现与介绍

    基于pytorch的sque2suqe with attention实现与介绍 上一篇文章<基于pytorch的ConvGRU神经网络的实现与介绍>https://blog.csdn.ne ...

  2. OpenCV实战(2)——OpenCV核心数据结构

    OpenCV实战(2)--OpenCV核心数据结构 0. 前言 1. cv::Mat 数据结构 1.1 cv::Mat 简介 1.2 cv::Mat 属性 1.3 完整代码示例 2. 探索 cv::M ...

  3. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  4. NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成...

    原文:NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成 本篇内容属于非实用性(拿来即用)介绍,如对框架设计没兴趣的朋友,请略过. 快一个月没有写博 ...

  5. 国产主可控的嵌入式仿真测试软件SkyEye与可信编译器L2C的核心翻译介绍

    为了满足国内某安全攸关领域的需求, L2C编译器的开发始于2010年9月, 其目标是设计实现一个经过形式化验证的可信编译器, 其源语言是面向领域的同步数据流语言Lustre*(Lustre语言的一个变 ...

  6. Spark入门必读:核心概念介绍及常用RDD操作

    导读:Spark是由加州大学伯克利分校AMP实验室开源的分布式大规模数据处理通用引擎,具有高吞吐.低延时.通用易扩展.高容错等特点.Spark内部提供了丰富的开发库,集成了数据分析引擎Spark SQ ...

  7. redis学习(二) redis数据结构介绍以及常用命令

    redis数据结构介绍 我们已经知道redis是一个基于key-value数据存储的数据结构数据库,这里的key指的是string类型,而对应的value则可以是多样的数据结构.其中包括下面五种类型: ...

  8. (d2l-ai/d2l-zh)《动手学深度学习》pytorch 笔记(3)前言(介绍各种机器学习问题)以及数据操作预备知识Ⅲ(概率)

    开源项目地址:d2l-ai/d2l-zh 教材官网:https://zh.d2l.ai/ 书介绍:https://zh-v2.d2l.ai/ 笔记基于2021年7月26日发布的版本,书及代码下载地址在 ...

  9. 解密电商系统-Spring boot快速开始及核心功能介绍(下)

    上次说了Spring boot快速开始及核心功能介绍,本次说说配置文件相关的. Spring Boot属性配置文件详解(一) 修改端口 # application.properties: server ...

最新文章

  1. 大数据文件的批量写入方式
  2. Linux基础命令使用
  3. RBAC(Role-Based Access Control,基于角色的权限访问控制)—权限管理设计
  4. 设置html可打印区域,一个或多个页边距被设置到可打印区域之外,是否继续?...
  5. 如何蒸螃蟹?教你蒸螃蟹3个小窍门
  6. Windows创建类似.project只有后缀名的文件的方法
  7. java ee编译器_Java EE 8 MVC:控制器的详细介绍
  8. 具有GlassFish和一致性的高性能JPA –第1部分
  9. 个人第三次软件工程作业-效能分析
  10. 堆排序(java实现)
  11. 如何让textarea不可拖拽变化大小
  12. WIN32汇编列表框的使用
  13. 【MySQL】——数据库基础入门知识
  14. 在线二进制转文本字符工具
  15. 有些路,只能一个人走。
  16. 秋意浪漫风景如画 诗情画意 谁能读懂一个浪子的心
  17. 数据分析面试题--SQL面试题
  18. 【DBC专题】-2-CAN Signal信号的Multiplexor多路复用在DBC中实现
  19. 推荐:常用的代码编辑器!
  20. 分布式Session共享和单点登录实现

热门文章

  1. 广东计算机应用专业,广东地区计算机应用技术专业报考热门高校你造吗
  2. 华为笔记本MateBook D14 开箱
  3. Linux IO模式及select、poll、epoll实现nio详解
  4. unity头顶状态制作_unity实现头顶血条
  5. 【Altium designer】Ctrl+M测量的尺寸数据无法清除
  6. syscall指令_linux syscall详细介绍
  7. visio2003中、origin中、matlab中,字体的大小以pt为单位,与word中的几号字大小是如何对应
  8. DV7.0变量参考列表
  9. 计算机软考初级程序员考试范围
  10. Latex参考文献在文中引用格式为author et al. [number]