TensorFlow架构与设计:图模块
标签: 深度学习 人工智能 神经网络 机器学习 tensorflow
作者:刘光聪 ,中兴通讯高级系统架构师,专注机器学习算法,分布式系统架构与优化。
原文:TensorFlow架构与设计:图模块
责编:王艺 CSDN AI记者,投稿、寻求报道、深入交流请邮件[email protected]或扫描文末二维码添加微信。相关文章:
图解TensorFlow架构与设计
计算图是TensorFlow领域模型的核心。本文通过对计算图领域模型的梳理,讲述计算图构造的基本原理。
边
Edge持有前驱节点与后驱节点,从而实现了计算图的连接,也是计算图前向遍历,后向遍历的衔接点。
边上的数据以Tensor的形式传递,Tensor的标识由源节点的名称,及其所在边的src_output唯一确定。也就是说,tensor_id = op_name:src_output
src_output与dst_input
Edge持有两个重要的属性:
- src_output:表示该边为前驱节点的第src_output条输出边;
- dst_input:表示该边为后驱节点的第dst_input条输入边。

例如,存在两个前驱节点s1, s2,都存在两条输出边;存在两个后驱节点d1, d2,都存在两条输入边。

控制依赖
计算图中存在两类边,
- 普通边:用于承载Tensor,常用实线表示;
- 控制依赖:控制节点的执行顺序,常用虚线表示。
特殊地,控制依赖边,其src_output, dst_input都为-1(Graph::kControlSlot),暗喻控制依赖边不承载任何数据,仅仅表示计算的依赖关系。
bool Edge::IsControlEdge() const {
return src_output_ == Graph::kControlSlot;
}节点
Node(节点)持有零条或多条输入/输出的边,分别使用in_edges, out_edges表示。另外,Node持有NodeDef, OpDef。其中,NodeDef持有设备分配信息,及其OP的属性值集合;OpDef持有OP的元数据。

输入边
在输入边的集合中按照索引线性查找,当节点输入的边比较多时,可能会成为性能的瓶颈。依次类推,按照索引查找输出边,算法相同。
Status Node::input_edge(int idx, const Edge** e) const {
for (auto edge : in_edges()) {
if (edge->dst_input() == idx) {
*e = edge;
return Status::OK();
}
}
return errors::NotFound("not found input edge ", idx);
}前驱节点
首先通过idx索引找到输入边,然后通过输入边找到前驱节点。依次类推,按照索引查找后驱节点,算法相同。
Status Node::input_node(int idx, const Node** n) const {
const Edge* e;
TF_RETURN_IF_ERROR(input_edge(idx, &e));
if (e == nullptr) {
*n = nullptr;
} else {
*n = e->src();
}
return Status::OK();
}图
Graph(计算图)就是节点与边的集合,领域模型何其简单。计算图是一个DAG图,计算图的执行过程将按照DAG的拓扑排序,依次启动OP的运算。其中,如果存在多个入度为0的节点,TensorFlow运行时可以实现并发,同时执行多个OP的运算,提高执行效率。

空图
计算图的初始状态,并非是一个空图。实现添加了两个特殊的节点:Source与Sink节点,分别表示DAG图的起始节点与终止节点。其中,Source的id为0,Sink的id为1;依次论断,普通OP节点的id将大于1。
另外,Source与Sink之间,通过连接「控制依赖」的边,保证计算图的执行始于Source节点,终于Sink节点。它们之前连接的控制依赖边,其src_output, dst_input值都为-1。
习惯上,仅包含Source与Sink节点的计算图也常常称为空图。

Node* Graph::AddEndpoint(const char* name, int id) {
NodeDef def;
def.set_name(name);
def.set_op("NoOp");
Status status;
Node* node = AddNode(def, &status);
TF_CHECK_OK(status);
CHECK_EQ(node->id(), node_id);
return node;
}
Graph::Graph(const OpRegistryInterface* ops)
: ops_(ops), arena_(8 << 10 /* 8kB */) {
auto src = AddEndpoint("_SOURCE", kSourceId);
auto sink = AddEndpoint("_SINK", kSinkId);
AddControlEdge(src, sink);
}非空图
在前端,用户使用OP构造器,将构造任意复杂度的计算图。对于运行时,无非就是将用户构造的计算图通过控制依赖的边与Source/Sink节点连接,保证计算图执行始于Source节点,终于Sink节点。

添加边
计算图的构造过程非常简单,首先通过Graph::AddNode在图中放置节点,然后再通过Graph::AddEdge在图中放置边,实现节点之间的连接。
const Edge* Graph::AllocEdge() const {
Edge* e = nullptr;
if (free_edges_.empty()) {
e = new (arena_.Alloc(sizeof(Edge))) Edge;
} else {
e = free_edges_.back();
free_edges_.pop_back();
}
e->id_ = edges_.size();
return e;
}
const Edge* Graph::AddEdge(Node* source, int x, Node* dest, int y) {
auto e = AllocEdge();
e->src_ = source;
e->dst_ = dest;
e->src_output_ = x;
e->dst_input_ = y;
CHECK(source->out_edges_.insert(e).second);
CHECK(dest->in_edges_.insert(e).second);
edges_.push_back(e);
edge_set_.insert(e);
return e;
}添加控制依赖边,则可以转发调用Graph::AddEdge实现。
const Edge* Graph::AddControlEdge(Node* src, Node* dst) {
return AddEdge(src, kControlSlot, dst, kControlSlot);
}点击查看下一篇文章:TensorFlow架构与设计:会话生命周期


智能推荐
TensorFlow on Kubernetes的架构与实践
这两年,Kubernetes在企业中的DevOps、微服务领域取得了出色的成绩,从2017年开始,将Kubernetes应用到HPC、AI等领域也成了技术热点。这里我给大家分享一下Kubernetes在AI中的落地经验,内容包括TensorFlow on Kubernetes的架构与实践,以及线上经验和坑。 都是玩容器的老司机,都知道Kubernetes这两年非常火,截止目前在GitHub上31K...
冒泡排序,及改进方式,性能优化400%>>>附图解加源码
首先源码附上,源码中带有注释,看不懂没关系,源码后面附带图解,最后附上代码效率提升图 源码如下: 方案一:其实实现很简单,两层循环,每次内层迭代出最大的一个值,将其放入数组最后一个位置,外层循环的末端便往前移一位。其原理如下图 方案一代码块: 方案二:优化改进 仔细观察上面的图,我们不难发现当迭代到图下这样的情况时,其实已经全排序好了,但是我们还是需要对它进行1,2,3,4,5,6的迭代,这些情况...
css3常用选择器
先介绍一下基本选择器,如下几种 *:通配符。选择页面的所有元素 E:元素选择器。对页面的一些元素进行选择,如p,div,li等 .class:类选择器 #id:id选择器。一个Id在一个页面中只能选择,这是和类选择器的区别 E F:后代选择器。如ul li。选中ul下的li E>F:子元素选择器。如下,可以用 h1 > strong {color:red;}使h1的子元素strong变...
python is not set from command line or npm configuration
问题 猜测原因 python版本冲突 解决方案 去官网找到最新版本python 点击下载,注意记住你下载的目录,下载好以后,打开这个目录下的文件夹,Python310, 整个文件夹复制一下 在项目里运行npm config list --json 找到python的路径 我的是 C:\\Python27\\python.exe 说明项目里用的还是py...
Java8 Stream流操作
前言 我们常常需要将一个容器转化成另一个容器,或是对这个容器中的数据进行批量处理,这时使用Stream流可以大大减少我们的工作量。 1 Stream概述 Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利。 那么什么是Stream? Stream将要处理的元素集合看作一种流,在流的过程中,借助St...
猜你喜欢
带你玩转Visual Studio——带你跳出坑爹的Runtime Library坑
在Windows下进行C++的开发,不可避免的要与Windows的底层库进行交互,然而VS下的一项设置MT、MTd、MD和MDd却经常让人搞迷糊,相信不少人都被他坑过,特别是你工程使用了很多第三库的时候,及容易出现各种链接问题。看一下下面这个错误提示: LIBCMT.lib(_file.obj) : error LNK2005: ___initstdio already defined...
git 设置 gitignore 忽略 __pycache__
清除git缓存中的pycache 直接删掉硬盘上的文件 如果我想保留硬盘上的这个文件,而只删除版本管理中的文件,就需要加入--cached参数。 切换分支出现问题 尽管我已经删除了__pycache__,硬盘也没有了,但是切换分支的时候依然是会提示本地重写的情况。 提示:需要我在切换分支之前,提交一次更新。 提交了更新之后,再来尝试切换分支,如下: 成功了,说明当做了任何变更之后,切换分支前需要执...
人生苦短,我用Python(二)— 爬取会议网站 EasyChair Smart CFP
寒假留校帮学长写了个爬虫,抓取会议网站上一些CFP信息。想着把一些知识点、坑点记下来,一来做个小总结给工作收收尾,二是以后再遇到好从容应对。 这是我写的第二个比较完善的爬虫了,比第一个要简单许多,完全过程化的代码,而且easychair这个网站页面布局比较友好,适合python新手、前端小白入门练习。但这个网站反爬比较厉害,写爬虫的过程中就被ban了好几次…… 制定抓取...
(三)Single Threaded Execution模式
一、定义 一个线程执行。有时也称为Critical Section(临界区)。 二、模式案例 案例: 假设有三个人,频繁地通过一扇门,规定每次只能通过一个人,当通过一个人时,程序会将通过的总人次加1,同时记录该次通过人的姓名和出生地。 门的定义: 人的定义 测试类 多次执行后发现可能出现以下结果: &...
Linux服务管理之系统管理员需要掌握的命令
为什么80%的码农都做不了架构师?>>> systemd的主要命令行工具是systemctl。大多数Linux系统管理员应该都已经非常熟悉系统服务和init系统管理,比如service,chkconfig和telinit命令的使用。systemd也完成同样的管理任务,只是命令工具systemctl的语法有所不同而已。 1. sysvinit和system...
