InfiniTensor/optimization
YdrMaster c077a61681 fix: 改正 1x1 卷积的变换
Signed-off-by: YdrMaster <ydrml@hotmail.com>
2023-08-04 16:05:22 +08:00
..
include/optimization style: 调整结构 2023-08-04 16:05:22 +08:00
src fix: 改正 1x1 卷积的变换 2023-08-04 16:05:22 +08:00
src0 refactor: 重命名 optimization,以后可以分离为 submodule 2023-08-04 16:05:22 +08:00
test fix: 改正 1x1 卷积的变换 2023-08-04 16:05:22 +08:00
CMakeLists.txt feat: 整理子项目结构,实现一部分导入 2023-08-04 16:05:22 +08:00
Makefile refactor: 重命名 optimization,以后可以分离为 submodule 2023-08-04 16:05:22 +08:00
README.md refactor: 重命名 optimization,以后可以分离为 submodule 2023-08-04 16:05:22 +08:00

README.md

设计概述

  1. 宗旨:简化 尽量简化定义。凡是当前用不到的就去掉,以保证开发同时保持敏捷和可靠。
  2. 目标:中层接口 因为不是面向用户开发,不需要考虑接口易用性,也不需要过度考虑防御式编程。调用这些 api 的将会是第一方编写的上层代码。
  3. 文档 覆盖率应逼近 100%。

代码解析

重要的文件是 tensor.hgraph.hmutation.h

tensor.h 提供了这个图表示中张量的定义。张量的结构由形状、数据类型和数据组成,并储存了在每个图上和算子的连接关系。张量的所有权由所有连接到张量的算子共享,因此其存在的唯一形式就是 std::shared_ptr,脱离共享所有权智能指针是没有意义的。通过向工厂函数直接传递形状、数据类型和数据,直接构造智能指针的张量,一旦所有连接到张量的算子释放,算子也被释放。

算子定义和其他重要类型定义在 graph.h。算子中存储且仅存储一个算子类型其他所有信息都由其持有所有权的输入张量表示。算子类型指示了算子如何解释自己的每个输入输出张量。这样做为算子提供了充分的灵活性同时也不损失表达能力——那些决定算子如何工作的重要信息必定已经保存在张量的数据中了而算子类型会解释它们是谁。

算子的所有权属于一张图,确切地说,一张未分的或不可再分的单体图,Unigraph。每个算子由唯一的图控制多个图之间不共享算子的任何部分。由于算子的定义非常轻1 枚举 + 2 智能指针的数组),这样做不会带来大的开销,但减轻了所有权的管理难度——有且只有张量一种对象,会在算子这一种对象之间共享,其他所有东西的所有权都是独占的。

同时,Unigraph 具有只增性。只能向其中增加算子,必须以拓扑序,不能移除,也不能修改算子的顺序。因此,算子在图中的序号是唯一的,每个图则持有一个唯一的 ID。因此可以用 ID 来指示图,用序号指示算子(OpRef);用序号指示算子,再用序号指示张量(TensorPos)。图必须整体销毁,销毁时,其中所有算子控制的所有张量连接也会同时销毁。因此,不必维持不可独立存在的所有权关系。

mutation.h 的 PartitionMutationRating 三个类用于支持图的规则优化。这三个类本质是一样的,这种定义是为了对优化的不同阶段实现编译时的约束——一轮优化必须按划分→突变→评价的顺序依次执行每个操作一次。

这些类中保存的是一个 Mutant 的二维数组。每个 Mutant 是子图的一种突变体,存储了子图结构和评分。内层数组表示每个子图的多个变体,外层数组表示每张图的多个子图。显然,Partition 输入完整的图,并构建外层数组的结构,Mutation 将填充内层数组。Rating 填充每个突变体的得分,然后从高到低排序。接下来可以用序号向量指导图的重建。