编译概述

编译流程将Nnet和ComputationRequest作为输入,输出NnetComputation。ComputationRequest包含可用的输入索引
以及
请求的输出索引。

不提供输出索引并让编译器找出需要的输入索引的原因是,某些网络,比如RNNs,为输出给定输出,可能会消耗任意数量的输入特征

 
 

struct ComputationRequest包含除Nnet之外计算所需的所有数据。该结构体用于创建Computation。

ComputationRequest中最重要的信息是:

  1. 各个输入结点处提供的可用索引;
  2. 各个输出节点处请求的索引;
  3. 是否要执行反向传播;

相同的输入结点不能在IoSpecification数组input中出现两次,输出结点亦然;

 
 

创建计算图

详述ComputationGraph

 
 

为了提高效率,ComputationGraph会将Cindex映射为cindex_id,反之亦然。

 
 

ComputationGraph类的定义如下:

struct ComputationGraph {

//cindex_id到Cindex的映射

std::vector<Cindex> cindexes;

 
 

//is_input[cindex_id]表示cindex_id对应的Cindex是否在输入中是可用的

std::vector<bool> is_input;

 
 

// dependencies[cindex_id]表示计算cindex_id所依赖的其他cindex_id列表

std::vector<std::vector<int32> > dependencies;

private:

//Cindex到cindex_id的映射

// 必须通过GetCindexId()函数来调用

unordered_map<Cindex, int32, CindexHasher> cindex_to_cindex_id_;

};

 
 

dependencies成员的确切意义依赖于编译阶段。

在编译的初始阶段,dependencies包含函数Descriptor::GetDependencies()返回的Cindexes对应的所有cindex_ids。

之后,对dependencies进行修剪,只保留在实际计算中使用到的cindex_ids。

 
 

注意,与Descriptor类似的,Component也有GetDependencies()以及IsComputable()函数。然而,当且仅当Component是GeneralComponent时才有用。

 
 

创建计算图——ComputationGraph

详述计算图

 
 

ComputationGraphBuilder用于构建ComputationGraph。对于一个最简单的例子,从网络请求的输出开始,并沿着网络向前计算其依赖,并添加到ComputationGraph中,直至计算到输入结点。

研究所实习时,为现有DNN添加一输出层后,脚本得出无法计算的结论,就是依赖于此)。

 
 

基础算法

本算法不实际使用。

构建计算图时,需要使用如下算法来确定每个Cindex是否可以从提供的输入计算得到:

  • 调用Descriptor::GetDependencies()得到输出层处的所有依赖项;
  • 调用IsComputable()确定输入中哪些Cindexes可以用于计算,对实际不参与计算的依赖关系进行修剪
  • 检查所有请求的输出都是可计算的
  • 修脚掉所有不需要参与计算的cindex_ids

 
 

将计算组织为多步

根据拓扑顺序对Cindex排序并分组,使同组Cindexes可同时计算。

 
 

使用该算法的动机

ComputationGraphBuilder接口

 
 

 
 

将网络计算组织为一系列的步骤

介绍计算步骤序列

一旦有了计算图,那么原则上就有足够的信息来执行计算了。可以对计算图中的Cindexes以拓扑顺序排序,可以依赖关系作为输入,以单独计算每个Cindex。不幸的是,这并不十分有效,因为进行的矩阵操作不能发挥全部效率,除非矩阵相当大;使用GPU时尤其如此。所以需要将多个Cindexes合为一个批次(batch),这样同一batch中的Cindex可以同时计算。该batch被称为一个步骤step),大致对应于NnetComputation中的一个命令。

 
 

接下来将计算中所有的cindex_ids划分为一个step序列

step序列有以下属性:

  1. 给定step中所有cindex_ids对应于计算图中的一个节点(component-node)
  2. 给定step中所有cindex_ids的所有依赖以及在之前的step中计算完成了

 
 

step序列还需要满足一些额外的、模糊的属性:

  1. ComputationRequest中的任何输入Cindex或输出Cindex必须在一个step中,step序列中索引的顺序与ComputationRequest中指定的顺序相同。(注意:输入可以是kComponent或kInput类型的节点)。
  2. 如果一个step对应于kComponent类型的节点(并且不对应于ComputationRequest中的输入),那么紧接着的下一个step必须对应于kDescriptor类型的节点,并且这两个step中的索引序列必须是相同的。
  3. 如果一个step对应于kDimRange类型的节点,则必须有另一个对应与源节点的step,这两个step中的索引和顺序完全相同。(这允许我们为kDimRange节点使用子矩阵)

 
 

规则b是确保Component可以直接以Descriptor的输出作为其输入,而无需任何额外的重排或重组(因为按照设计,这样的重排或重组需要Descriptor来完成)。由于这个规则,原则上,一个来自于kDescriptor节点的cindex_id可以出现在多个step中,尽管这只有在使用非简单组件时才会发生。此外,为了确保满足规则c,我们偶尔可能需要在计算图中添加新的cindex_ids。

 
 

创建计算步骤序列(基础算法)

这里,介绍一个用于创建step序列的基本算法(但不实际使用),只用于为稍后介绍的实际算法做铺垫。这个基本算法分为以下几步:

  • 首先保留对应于输入和输出节点的Cindex;将它们按节点索引分开;将这些step按照ComputationRequests中相同顺序排序。
  • 接下来处理非输入或输出的中间Cindex:
    • 将中间Cindex按神经网络层的依赖关系划分为多个"阶段"(phase,其中第一个phase包含仅依赖于输入的所有Cindex;并且通常第n阶段包含仅依赖于小于第n个phase的Cindex
    • 从每个phase移除所有不对应于kComponent节点的Cindexes(这些Cindexes将在稍后处理)。
    • 使用struct Index的排序运算符对step进行排序。
    • 按如下方式创建component-input(组件输入)节点的step
      • 对于kComponent类型的每个step,使用ComputationGraph的dependencies成员计算其所依赖的Cindex的集合。
      • 使用struct Index的排序运算符对上述每个step的集合进行排序。(对于简单的组件,这确保它们与组件的输出的顺序相同)。
      • (模糊特征):此时非简单组件的输入进行重排(如果需要);具体请参阅Component::ReorderIndexes()。
      • 将该组件输入节点的step防止在Component的对应step之前。
    • 按如下方式创建dim-range节点的step
      • 从网络图中取对应于dim-range节点的所有Cindex,并得出其输入所属的step
      • 注意,对于每个现有step,拥有Cindex的dim-range节点的集合从该step中获取输入。
      • 对于每个现有步骤s,对于拥有从该step获取输入的现有Cindex的每个dim-range节点,创建包含与step s相同的索引序列的step,并将新step放在step s之后。
  • 对所有step排序:输入step、中间step、输出step

 
 

上述算法最终将将它最终将Cindexes分成许多step

例如,假设我们有一个RNN层,后接一个标准的前馈层。RNN层必须将Cindexs分成与时间索引一样多step,但是上述算法也会将完连接层的计算分成多个step,因为RNN输出Cindexes后,全连接层对应的Cindexes就立即可计算。我们希望能够先完成RNN层的所有计算,然后再完成全连接层的计算。

 
 

创建计算步骤序列(实际算法)

class Compiler

介绍class Compiler

创建网络计算

设定位置信息

检查是否需要梯度

计算StepInfo

计算input_output_info

分配矩阵空间

前向计算

反向计算

释放矩阵空间

添加调试信息

快捷编译

Kaldi版本5.1提供的功能,并默认启用。

条件是:

  1. ComputationRequest中有两个以上不同的"n"索引;
  2. 对于每个索引,请求的"t"和"x"索引是相同且有序的

 
 

和1);

编译mini_request,得到mini_computation

根据mini_computation,将所有原始计算请求的编译结果推导出来;

 
 

快捷方式编译能显着缩短编译时间。

nnet3配置中的“编译”的更多相关文章

  1. nnet3配置中的上下文和chunk(块)大小

    Nnet3配置中的上下文和块大小 简介 本页讨论了nnet3配置中关于解码和训练的块大小以及左右上下文的某些术语.这将有助于理解一些脚本.目前,从脚本角度来看,没有任何关于nnet3的"概述 ...

  2. 如何在MyEclipse中配置jre的编译运行环境

    由于在MyEclipse中已经自带了jre编译环境,但由于版本太低,所以有时候需要将编译环境配置为系统的jre版本.在MyEclipse中配置jre的编译运行环境很简单,只需要全局配置一次,则所有项目 ...

  3. Webpack 2 视频教程 019 - Webpack 2 中配置多页面编译

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  4. 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“项目-域名信息” http://www.mysite.com 不在以下 request 合法域名列表中

    报错如图 报错文字如下: 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“项目-域名信息” http://www.mysite.net 不在以下 request 合法域名列表中 ...

  5. GDAL1.9.1 IN VS2008 C#中的编译及使用

    下载gdal1.9.1到官网:http://www.gdal.org/ GDAL库的简洁.高效深受开发人员的喜爱,很多开源的GIS软件甚至是商业GIS软件都使用了这个库.GDAL使用C++,在Visu ...

  6. Ubuntu下安装并配置VS Code编译C++

    作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7069091.html Ubuntu下安装并配置VS Code编译C++ 安装 ...

  7. Openfire4源码部署到eclipse中并编译

    Openfire4源码部署到eclipse中并编译 概述 Openfire是众所周知的基于xmpp协议的IM开源服务,所有操作,配置,监控,调试等以B/S方式进行展示,非常的方便管理员进行管理.它的强 ...

  8. jenkins自动部署应用到tomcat中,编译后shell脚本的简单示例

    jenkins的安装这里就不做描述了,很简单的  百度搜索一下即可 这里安装的jenkins-2.39-1.1 wget http://pkg.jenkins-ci.org/redhat/jenkin ...

  9. Windows下为 Eclipse 配置 C/C++ 编译环境(转)

    1.Eclipse及CDT的安装 CDT的全称是C/C++ DevelopmentTools,CDT使得Eclipse能够支持C/C++的开发.直接下载 eclipse CDT 集成版 下载地址:ht ...

随机推荐

  1. KERBEROS PROTOCOL TUTORIAL

    KERBEROS PROTOCOL TUTORIAL   This tutorial was written by Fulvio Ricciardi and is reprinted here wit ...

  2. Configuring Apache Kafka for Performance and Resource Management

    Apache Kafka is optimized for small messages. According to benchmarks, the best performance occurs w ...

  3. STM32 FSMC使用笔记

    最近在使用STM32的FSMC与FPGA做并行通信总线控制,做一下总结 1,利用FSMC读取写入16位数据时的封装函数如下,不这样使用的话在与FPGA进行通信的过程中可能会出现不可预知的错误. #de ...

  4. day2 and day3 总结-python基础-坚持就是胜利

    今日份快捷键学习,pycharm中按CTRL+ALT+L 自动规范化操作,不过和QQ的快捷键会有冲突,建议更改QQ的 知识点: 1.编码 2.while循环 3.运算符 4.数字int 5.布尔值 6 ...

  5. 第1章 初始Docker容器

    1.1 什么是Docker slogan:Build Ship Run Any App Anywher.关键在于Ship,通过把程序和程序运行所需要的环境一起交付. Linux容器技术: Docker ...

  6. SpringBoot打包成war

    关于SpringBoot打成jar包以及jar包如何在Linux持久运行,我在前面已经说过了,所以本次不再赘述. 关于SpringBoot打包成war,其实步骤特别简单,如下图所示(如果是jar,通常 ...

  7. SpringBoot标准Properties

    # =================================================================== # COMMON SPRING BOOT PROPERTIE ...

  8. SQL Server中NULL的一个测试

    我们都知道SQL Server中NULL是一个很特殊的存在,因为NULL不会等于任何值,且NULL也不会不等于任何值.对于NULL我们只能使用IS或IS NOT关键字来进行比较. 我们先来看看下面一个 ...

  9. 基于HTML5 的互联网+地铁行业

    前言 近几年,互联网与交通运输的融合,改变了交易模式,影响着运输组织和经营方式,改变了运输主体的市场结构.模糊了运营与非营运的界限,也更好的实现了交通资源的集约共享,同时使得更多依靠外力和企业推动交通 ...

  10. cookie跨域共享

    domain和path属性,domain就是当前域,默认为请求的地址,如网址为www.jb51.net/test/test.aspx,那么domain默认为www.jb51.net,path默认就是当 ...