Huawei Summary 1: Mindspore

工作总结1 : Mindspore

EAI的工作交付完成后有一段时间空闲期,没有实际的活儿,和浩哥一起学了一些程序分析相关的东西。浩哥技术不错,也乐于组织一些技术分享,经常带着我们一群编译器小白讲解概念和“结对编程”(其实是边写代码边给我们将思路)。这期间最大的收获就是学了一些source 2 source转换和ANTLR的一些知识。记得当时准备一个链接器专利需要自动改写linker script,于是准备用ANTLR做source 2 source的转换,但是当时能找到的只有一个ANTLR2 语法的linker script语法文件,为了让ANTLR4的运行时能正确解析,还套娃去找了一个将ANTLR2语法文件转换成ANTLR4语法文件的工具hhh。

TIK算子实现

空闲的状态没有持续太久,我们组就打包卖给海思图灵去写vector core和scalar core的算子。我当时主要是负责vector core算子的编写,vector core开发用的是TIK(Tensor Iterator Kernel), 是一个Python开发框架,框架会将我们写的TIK代码转换为CCE-C代码,然后用CCE-C的编译器编译出device侧的二进制。开发流程十分传统厚重,感受了一把原汁原味的瀑布式开发流程,每个算子实现都要写概要设计文档、详细设计文档,然后设计文档也有集体检视,文档检视还有缺陷率的要求(>5%)。

负责实现的第一个算子是SGBM,用于作双目视差计算的,最高需要支持1080p的灰度图作为输入。这个算法比较复杂,主要分为4个步骤:

  1. 预处理:水平Sobel算子处理后得到图像的梯度信息
  2. 代价计算:原图像SAD代价+梯度图中的梯度代价
  3. 动态规划:代价由左上角向右下角传播,OpenCV默认使用四条传播路径
  4. 后处理:唯一性检测、亚像素插值、左右一致性检测etc

算法根据上面步骤分给了三个人做,我主要负责动态规划部分的实现。动态规划计算时,每个像素依赖当前行和上一行中的像素,但是无法一次容纳最大size的两行像素。因此我们需要同时对行和列进行tiling切分,每次处理两行x64个像素,先从左向右传播,后从上向下传播。这样的tiling切分会导致host到device的数据搬运和后续处理的流水线效率不高,最后算法整体测试时结果也验证了这一点。但这是算法特性(下一行依赖上一行)决定的,最后算法要不要异构下放到vector core这个需求又回去重新评估了。。

后面又负责了WarpAffineWarpPerspective两个算子的实现,这两个算子数学公式看起来都很简单,只是简单的双线性内插值。但是OpenCV的实现却用了3000行+,其中用到了很多巧妙的优化小技巧,例如对小方格进行量化切分成NxN的小格,每个格子中直接存放了周围四个像素点的权重。这两个算法分析好优化方案之后就无甚可书了,tiling按照行搬入即可,写到最后我的代码补全工具比我还要懂TIK,写几个字母能直接补全一两行。

ME开发

ME(Mindspore前端)的主要工作之前已经汇总过了,可以看这篇

/!-- -->