深度学习编译中间件之NNVM(十三)NNVM源代码阅读2

2023-10-29 05:08

本文主要是介绍深度学习编译中间件之NNVM(十三)NNVM源代码阅读2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考文档

  1. 深度学习编译中间件之NNVM(十二)NNVM源代码阅读1

本系列文档涉及NNVM源代码阅读理解,本篇主要介绍一些NNVM的基础数据结构。

使用的C++命令空间为nnvm

相关代码位于
1. include/nnvm
2. src/core

class Op

代码位于

  • include/nnvm/op.h
  • include/nnvm/op_attr_types.h
  • src/core/op.cc

Op类主要用于记录操作符的一些信息

// 代码只是节选
class NNVM_DLL Op {
public:std::string name; // 操作符名称std::string description; // 操作符详细解释,可用于文档生成std::vector<ParamFieldInfo> arguments; // 带文字描述的参数数组uint32_t num_inputs = 1; // 操作符的输入数据个数uint32_t num_outputs = 1; // 操作符的输出数据个数uint32_t support_level = 10; // 支持优先级,数字越小越优先std::function<uint32_t(const NodeAttrs& attrs)> get_num_outputs = nullptr;std::function<uint32_t(const NodeAttrs& attrs)> get_num_inputs = nullptr;std::function<void(NodeAttrs* attrs)> attr_parser = nullptr;inline Op& describe(const std::string& descr);inline Op& add_argument(const std::string &name,const std::string &type,const std::string &description);inline Op& add_arguments(const std::vector<ParamFieldInfo> &args);inline Op& set_num_inputs(uint32_t n); inline Op& set_support_level(uint32_t level);inline Op& set_num_inputs(std::function<uint32_t (const NodeAttrs& attr)> fn);  inline Op& set_num_outputs(uint32_t n);inline Op& set_num_outputs(std::function<uint32_t (const NodeAttrs& attr)> fn);inline Op& set_attr_parser(std::function<void (NodeAttrs* attrs)> fn);template<typename ValueType>inline Op& set_attr(const std::string& attr_name, const ValueType& value,int plevel = 10);Op& add_alias(const std::string& alias); Op& include(const std::string& group_name);static const Op* Get(const std::string& op_name);template<typename ValueType>static const OpMap<ValueType>& GetAttr(const std::string& attr_name);private:template<typename ValueType>friend class OpMap;friend class OpGroup;friend class dmlc::Registry<Op>;uint32_t index_{0}; // 唯一操作符索引,用于OpManager区分Op
};

另外include/nnvm/op_attr_types.h中提供了操作符支持的属性类型定义

// 代码节选
using FInferShape = FInferNodeEntryAttr<TShape>;
using FInferType = FInferNodeEntryAttr<int>;// 得到操作符节点的梯度节点,这个函数用于生成反向传播计算图
using FGradient = std::function<std::vector<NodeEntry>(const NodePtr& nodeptr,const std::vector<NodeEntry>& out_grads)>;
...

class Node

代码位于

  • include/nnvm/node.h
  • src/core/node.cc

Node类用于在一个计算图中表示一个操作

class NNVM_DLL Node {
public:NodeAttrs attrs; // 节点属性std::vector<NodeEntry> inputs; // 节点输入向量 std::vector<NodePtr> control_deps; // 依赖节点,用于控制流依赖any info; // 节点额外信息inline const Op* op() const; // 返回节点包含的操作inline bool is_variable() const; // 判断节点是否是占位变量(即节点内不含操作,节点的作用只是占用)inline uint32_t num_outputs() const; inline uint32_t num_inputs() const;static NodePtr Create(); // 创建一个空节点(静态方法)
};

class Graph

代码位于

  • include/nnvm/graph.h
  • src/core/graph.cc

Graph类用于表示一个计算图,它是一个为了进行优化Pass的中间表示。

class Graph {
public:std::vector<NodeEntry> outputs; // 计算图的输出节点std::unordered_map<std::string, std::shared_ptr<any> > attrs; // 计算图属性集合template<typename T>inline const T& GetAttr(const std::string& attr_name) const;inline bool HasAttr(const std::string& attr_name) const;template<typename T>inline T MoveCopyAttr(const std::string& attr_name);const IndexedGraph& indexed_graph() const; // 获取当前计算图的索引图,如果不存在就按需创建
private:mutable std::shared_ptr<const IndexedGraph> indexed_graph_;
}// 下面介绍Graph的辅助类IndexedGraph/*!* IndexedGraph用于提供索引一个计算图的辅助数据结构* 它将图内部的节点们映射到一个连续整型变量node_id,而且将输出节点映射到一个连续整型变量entry_id。* 这样的方式允许将计算图的内部节点和输出节点存储在一个紧凑的向量结构中,并且可以做到快速存取* 节点的node_id和entry_id是和保存的JSON文件的顺序是一致的*/
class IndexedGraph {
public:/* 表示计算图中的一个数据 */struct NodeEntry {uint32_t node_id;uint32_t index;uint32_t version;};/* 表示计算图中的一个节点 */struct Node {const nnvm::Node* source; // 指向源节点的指针array_view<NodeEntry> inputs; // 节点的输入数据array_view<uint32_t> control_deps;std::weak_ptr<nnvm::Node> weak_ref; // 指向节点的弱引用};inline uint32_t entry_id(uint32_t node_id, uint32_t index); // 获取一个唯一的entry_idinline uint32_t entry_id(const NodeEntry& e); inline const std::vector<uint32_t>& input_nodes(); // 返回argument节点列表
private:friend class Graph;}

class PassFunctionReg

代码位于

  • include/nnvm/pass.h
  • src/core/pass.cc

PassFunctionReg类为DataIterator工厂函数提供注册入口

// PassFunctionReg继承自dmlc::FunctionRegEntryBase,这个类主要用于函数注册。
// PassFunctionReg在FunctionRegEntryBase类注册普通函数的基础上增加和Pass相关的属性和函数struct PassFunctionReg: public dmlc::FunctionRegEntryBase<PassFunctionReg,PassFunction> {bool change_graph{false}; // 标记pass是否会改变计算图的结构std::vector<std::string> graph_attr_dependency; // 记录pass在被应用之前哪些计算图属性必须处于可用std::vector<std::string> graph_attr_targets; // 记录pass在被应用之后将生成哪些计算图属性
}// 下面介绍一些辅助数据结构和函数/*!* \brief 一个PassFunction表示一个针对计算图所做的操作* 这个函数处理一个源计算图,返回一个目标计算图,这两个计算图可能一致也可能不一致* 一个PassFunction可能会改变图结构,也可能会增加图属性*/
typedef std::function<Graph (Graph src)> PassFunction;// 针对输入计算图应用一系列pass
Graph ApplyPasses(Graph src, const std::vector<std::string>& passes);

class Symbol

代码位于

  • include/nnvm/symbolic.h
  • src/core/symbolic.cc

Symbol类是一个帮助类,用于表示计算图中的操作节点。

Symbol类拥有一个利用Group/Functor/Variable这些组件来创建计算图的接口,Symbol类也会被导出到NNVM的Python前端,用于方便进行快速测试和部署。后面将有专门的文档讲解NNVM的Python接口的部分。

// 代码节选
class NNVM_DLL Symbol {
public:std::vector<NodeEntry> outputs;Symbol Copy() const;void Print(std::ostream &os) const;std::vector<NodePtr> ListInputs(ListInputOption option) const;std::vector<std::string> ListInputNames(ListInputOption option) const;std::vector<std::string> ListOutputNames() const;// 创建Symbol/Variable/Group Symbolstatic Symbol CreateFunctor(const Op* op,std::unordered_map<std::string, std::string> attrs);static Symbol CreateFunctor(const NodeAttrs& attrs);static Symbol CreateVariable(const std::string& name);static Symbol CreateGroup(const std::vector<Symbol>& symbols);
}

class Layout

代码位于

  • include/nnvm/layout.h

Layout类用于处理Layout表达式

layout由大写字母、小写字母和数字组成,其中大写字母表示一个维度,大写字母对应的小写字母表示一个split之后的子维度,小写字母之前的数字则表示split块的数量。

例如:NCHW16c

表示:[batch_size, channel, height, width, channel_block], channel_block=16

至此NNVM的基础数据结构就介绍完了,接下来的文档将会具体分析NNVM的重要组件

这篇关于深度学习编译中间件之NNVM(十三)NNVM源代码阅读2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/298424

相关文章

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

Python3中Sanic中间件的使用

《Python3中Sanic中间件的使用》Sanic框架中的中间件是一种强大的工具,本文就来介绍Python3中Sanic中间件的使用,具有一定的参考价值,感兴趣的可以了解一下... 目录Sanic 中间件的工作流程中间件的使用1. 全局中间件2. 路由中间件3. 异常处理中间件4. 异步中间件5. 优先级

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用