diff --git a/00Others/01Editors.md b/00Others/01Editors.md
index 215c3ef4..1feeb301 100644
--- a/00Others/01Editors.md
+++ b/00Others/01Editors.md
@@ -14,7 +14,7 @@ AI 硬件体系架构:[苏统华教授](https://homepage.hit.edu.cn/tonghuasu)
AI 编译原理:[苏统华教授](https://homepage.hit.edu.cn/tonghuasu), [ZOMI 酱](https://github.com/chenzomi12), [@史家兴](), [@宋一帆](https://github.com/sfs999), [@韩昊知](https://github.com/haozhihan), [@李行](), [@武震卿](), [@张浩](), [@陈庚天](),
-推理引擎系列:[苏统华教授](https://homepage.hit.edu.cn/tonghuasu), [ZOMI 酱](https://github.com/chenzomi12), [高鑫淼](), [何伟](), [刘旭斌](), [杨璇](), [徐宏博](), [栾少](), [谢迎](), [刘欣楠](), [李行](), [江典恒]()
+推理引擎系列:[苏统华教授](https://homepage.hit.edu.cn/tonghuasu), [ZOMI 酱](https://github.com/chenzomi12), [高鑫淼](), [何伟](), [刘旭斌](), [杨璇](https://github.com/CSXuanYang), [徐宏博](), [栾少](), [谢迎](), [刘欣楠](), [李行](), [江典恒]()
AI 框架:[苏统华教授](https://homepage.hit.edu.cn/tonghuasu), [ZOMI 酱](https://github.com/chenzomi12), [金傲群](https://github.com/AoqunJin)
diff --git a/01Introduction/01present.md b/01Introduction/01present.md
index f3012eaa..82271a3c 100644
--- a/01Introduction/01present.md
+++ b/01Introduction/01present.md
@@ -137,7 +137,7 @@
![](images/01Present09.png)
-截至到 2012 年这个时间点,基础架构的线索中,以英伟达(NVIDIA)为代表的芯片厂商已经连续发布了 Tesla,Fermi,[Kepler](https://en.wikipedia.org/wiki/Kepler_(microarchitecture)) 架构系列商用 GPU 和多款消费级 GPU,这些 GPU 已经开始被研究工作引用加速 AI 算法与模型的研究,被业界公司用于人工智能产品。但同时从 AlexNet 工作中看到,作还基于 CUDA API 进行编程实现了[cuda-convnet](https://code.谷歌.com/archive/p/cuda-convnet),AI 系统与工具伴随着 AI 算法与模型的突破与需求呼之欲出,在后面的章节中将会总结和展望 AI 系统本身的脉络,现状与发展。
+截至到 2012 年这个时间点,基础架构的线索中,以英伟达(NVIDIA)为代表的芯片厂商已经连续发布了 Tesla,Fermi,[Kepler](https://en.wikipedia.org/wiki/Kepler_(microarchitecture)) 架构系列商用 GPU 和多款消费级 GPU,这些 GPU 已经开始被研究工作引用加速 AI 算法与模型的研究,被业界公司用于人工智能产品。但同时从 AlexNet 工作中看到,作者还基于 CUDA API 进行编程实现了[cuda-convnet](https://code.谷歌.com/archive/p/cuda-convnet),AI 系统与工具伴随着 AI 算法与模型的突破与需求呼之欲出,在后面的章节中将会总结和展望 AI 系统本身的脉络,现状与发展。
在之后的时间里,以 [ImageNet](https://www.image-net.org/),等公开的各领域(例如,计算机视觉,自然语言处理)数据集为代表的各个应用领域的公开数据集或基准测试,驱动着以卷积神经网络 CNN,循环神经网络 RNN,Transformer,图神经网络 GNN 为代表的 AI 模型网络结构的发展和创新。
diff --git a/02Hardware/06Domestic/07AscendBase.md b/02Hardware/06Domestic/07AscendBase.md
index 0e88d68a..f33744f7 100644
--- a/02Hardware/06Domestic/07AscendBase.md
+++ b/02Hardware/06Domestic/07AscendBase.md
@@ -38,6 +38,19 @@
数字视觉预处理模块主要完成图像视频的编解码,视频处理,对图像支持 JPEG 和 PNG 等格式的处理。来自主机端存储器或网络的视频和图像数据,在进入昇腾 AI 处理器的计算引擎处理之前,需要生成满足处理要求的输入格式、分辨率等,因此需要调用数字视觉预处理模块进行预处理以实现格式和精度转换等要求。数字视觉预处理模块主要实现视频解码(Video Decoder,VDEC),视频编码(Video Encoder,VENC),JPEG 编解码(JPEG Decoder/Encoder,JPEGD/E),PNG 解码(PNG Decoder,PNGD)和视觉预处理(Vision Pre-Processing Core,VPC)等功能。图像预处理可以完成对输入图像的上/下采样、裁剪、色调转换等多种功能。数字视觉预处理模块采用了专用定制电路的方式来实现高效率的图像处理功能,对应于每一种不同的功能都会设计一个相应的硬件电路模块来完成计算工作。在数字视觉预处理模块收到图像视频处理任务后,会读取需要处理的图像视频数据并分发到内部对应的处理模块进行处理,待处理完成后将数据写回到内存中等待后续步骤。
+### 昇腾910
+![昇腾 AI 处理器逻辑图](images/ascendarch18.png)
+
+昇腾910处理器的目标场景是云端的推理和训练,其架构如上图所示,包含Davinci Core、DVPP、HBM、DDR4等组件。昇腾910处理器采用了芯粒(chiplet)技术,包含六个die: 1个计算芯粒(包含32个Davinci Core、16个CPU Core和4个DVDP),1个IO芯粒,和4个HBM芯粒(总计1.2TB/s带宽)。针对云端训练和推理场景,昇腾910处理器做的优化包括:
+1. 高算力: 训练场景通常使用的Batch Size较大,因此采用最高规格的Ascend-Max,每个Core每个周期可以完成16*16*16=4096次FP16乘累加
+2. 高Load/Store带宽: 训练场景下计算反向SGD时,会有大量对Last Level Cache和片外缓存的访问,因此需要配备较高的Load/Store带宽,因此昇腾910除了DDR还采用了HBM技术。
+3. 100G NIC: 随着DNN的模型尺寸愈发庞大,单机单卡甚至单机多卡已经不能满足云端训练的需求,为了支持多卡多机组成集群,昇腾910集成了支持ROCE V2协议的100G NIC用于跨服务器传递数据,使得可以使用昇腾910组成万卡集群。
+4. 高吞吐率的数字视觉与处理器(DVPP): DVPP用于JPEG、PNG格式图像编解码、图像预处理(对输入图像上下采样、裁剪、色调转换等)、视频编解码,为了适配云端推理场景,DVPP最高支持128路1080P视频解码。
+
+### 昇腾310
+![昇腾 AI 处理器逻辑图](images/ascendarch17.png)
+昇腾310处理器的目标场景是边缘推理,比如智慧城市、智慧新零售、机器人、工业制造等,其架构如上图所示,主要包含Davinci Core、DVPP、LPDDR4等组件。相比昇腾910,昇腾310的定制化IP相对较少,但是提供了更多外设接口。由于在边缘推理场景下batch size通常只有1,因此昇腾310选择了较小的矩阵计算维度(m = 4, n = 16, k = 16)以实现$C_{mn} = A_{mk}\times B_{kn}$。由于在矩阵运算中$M = batch\_size \times output\_hight \times output\_width$, 当batch size = 1时,将m设置成4可以提升乘累加利用率。
+
## 卷积加速原理
在深度神经网络中,卷积计算一直扮演着至关重要的角色。在一个多层的卷积神经网络中,卷积计算的计算量往往是决定性的,将直接影响到系统运行的实际性能。昇腾 AI 处理器作为人工智能加速器自然也不会忽略这一点,并且从软硬件架构上都对卷积计算进行了深度的优化。
diff --git a/04Inference/02Mobilenet/02Cnn.md b/04Inference/02Mobilenet/02Cnn.md
new file mode 100644
index 00000000..ed3a2741
--- /dev/null
+++ b/04Inference/02Mobilenet/02Cnn.md
@@ -0,0 +1,215 @@
+
+
+# CNN 模型小型化(上)
+
+深度神经网络模型被广泛的应用于工业领域,并取得了巨大成功。然而,由于存储空间以及算力的限制,大而复杂的神经网络模型是难以被应用的。首先由于模型过于庞大,计算参数多(如下图所示),面临内存不足的问题。其次某些场景要求低延迟,或者响应要快。所以,研究小而高效的 CNN 模型至关重要。
+
+本章将介绍一些常见的 CNN 小型化结构,如:SqueezeNet 系列(2016),ShuffleNet 系列(2017),MobileNet 系列(2017),ESPNet 系列(2018),FBNet 系列(2018),EfficientNet 系列(2019),GhostNet 系列(2019)。
+
+![CNN](./images/02Cnn01.png)
+
+## SqueezeNet 系列
+
+### SqueezeNet
+
+**SqueezeNet**:是轻量化主干网络中比较著名的,它发表于 ICLR 2017,在达到了 AlexNet 相同的精度的同时,只用了 AlexNet 1/50 的参数量。SqueezeNet 核心贡献在于使用 **Fire Module**(如下图所示),即使用 $1\times 1$ 卷积降低通道数目(squeeze),然后用 $1 \times 1$ 和 $3 \times 3$卷积提升通道数(expand)。
+
+![Cnn](./images/02Cnn02.png)
+
+SqueezeNet 算法的主要目标是构建轻量参数的 CNN 架构,同时不损失精度。为了实现这一目标,作者总共采用了三种策略来设计 CNN 架构,具体如下:
+
+- **将 $3 \times 3$卷积替换成 $1 \times 1$ 卷积,可以使参数量减少 9 倍**。
+
+- **减少 $3\times 3 $卷积的通道数,一个 $3 \times 3 $卷积的计算量是 $3 \times 3 \times M \times N$ ,通过将 M 和 N 减少以降低参数数量**。
+
+- **将下采样操作延后,这样卷积层就有了大的激活图,保留更多信息**。
+
+在**Fire Module**的基础上搭建 SqueezeNet 神经网络,构如下图所示。它以卷积层开始,后面是 8 个 Fire Module,最后以卷积层结束,每个 Fire Module 中的通道数目逐渐增加,另外网络在 conv1、fire4、fire8、conv10 的后面使用了 最大池化。
+
+![Cnn](./images/02cnn/02Cnn03.png)
+
+### SqueezeNext
+
+**SqueezeNext**:设计基于残差结构并使用了分离卷积,采用了降低参数的策略:
+
+- 采用 **two-stage bottleneck modules**来减少权值参数,即采用两个 $1 \times 1$ 的 Conv,使得参数显著减少。
+
+- **Low Rank Filters** 低秩分解的核心思想就是将大矩阵分解成多个小矩阵,这里使用 Canonical Polyadic Decomposition,将 KxK 卷积,参数量能从$k^2$降为 2K,在 SqueezeNext 中也加入了 Shortut Connection。
+
+![Cnn](./images/02Cnn04.png)
+
+SqueezeNext 的 block,下图所示
+
+- **两个 $1\times 1$ 的 Conv 以减少参数**。
+
+- **$3\times 3 $卷积变成 $1\times 3$ 卷积与 $3\times 1$ 卷积的组合**。
+
+![Cnn](./images/02Cnn05.png)
+
+## ShuffleNet 系列
+
+### ShuffleNet
+
+**ShuffleNet**: 发表于 CVPR2018,针对极小的网络上的计算效率依然不高,$1\times 1 $卷积又特别消耗计算资源。它的贡献在于,使用 Point-Wise 分组卷积和 Channel Shuffle 两个操作,在降低计算量同时保持准确率。网络使用更多的通道来帮助编码阶段提取更多的信息,同时又针对小网络提出了 ShuffleNet Unit,要策略如下:
+
+- **使用 Pointwise Group Convolution 卷积来降低 $1\times 1 $卷积的计算量**。
+
+- **使用 Channel Shuffle 让不同通道的进行信息交互**。
+
+- **使用 ShuffleNet Unit 来构建小模型**。
+
+#### Pointwise Group Convolution 与 Channel Shuffle
+
+一般采用更稀疏的通道策略来解决 $1\times1$ 卷积带来的计算量问题,比如在 $1\times 1$ 卷积内部也使用分组卷积。但由于 $1\times1$ 卷积的输出会是下一层 block 的输入,当在 $1\times1$ 卷积中使用分组策略,则 $1\times1$ 瓶颈层的输出特征的每个通道并没有接收其他前面的所有输入(如图 a)。为了解决图 a 中的问题,将每个组再细分,细分后放入不同的组内(图 b),这个过程可以叫做 Channel Shuffle,打乱后如图 c 所示。
+
+![Cnn](./images/02Cnn06.png)
+
+#### ShuffleNet单元
+
+基于残差块(residual block)和 通道洗牌(channel shuffle)设计的 `ShuffleNet Unit` :
+
+- **深度卷积 **。
+
+- **逐点分组卷积**。
+
+- **逐点分组卷积 ( stride=2 )**。
+
+![Cnn](./images/02Cnn07.png)
+
+### ShuffleNet V2
+
+**ShuffleNet V2**:在 V1 的 Channel Shuffle 的基础上,又提出了 Channel Split,增强特征的重用性的同时也减少了计算量,并提出了 4 条设计高效网络的方法:
+
+- **G1:输入输出通道相同的时候,MAC 最小,模型最快**。
+
+- **G2:当分组卷积的分组数增大时(保持 FLOPs 不变时),MAC 也会增大,所以建议针对不同的硬件和需求,更好的设计对应的分组数,而非盲目的增加**。
+
+- **G3:网络设计的碎片化程度越高,速度越慢**。
+
+- **G4:不要过多的使用逐点运算**。
+
+ShuffleNet V2 中提出了 Channel Split,如图 c、d 所示。在每个单元的开始将通道拆分为 2 个分支,一个分支做恒等映射,另一个分支经过多层卷积保证输入通道数与输出通道数相同。不同于 ShuffleNet V1 ,ShuffleNet V2 的 1×1 没有再使用分组卷积,两条分支最后使用通道级联 concatenate 操作,没有使用 TensorAdd。
+
+![Cnn](./images/02Cnn08.png)
+
+## MobileNet 系列
+
+**MobileNet**系列:主要是为了在保持模型性能的前提下降低模型大小,同时可以提升模型速度,主要有 V1,V2,V3 版本。
+
+### MobileNet v1
+
+**MobileNet V1**:主要贡献在于提出了 Depthwise Separable Convolutions(深度可分离卷积),深度可分离卷积主要包括两种卷积变体,逐通道卷积(Depthwise Convolution)和逐点卷积(Pointwise Convolution)。
+
+#### 逐通道卷积(Depthwise Convolution)
+
+Depthwise Convolution 的一个卷积核只有一个通道,输入信息的一个通道只被一个卷积核卷积,这个过程产生的 feature map 通道数和输入的通道数完全一样,如下图所示:
+
+![Cnn](./images/02Cnn09.png)
+
+#### 逐点卷积(Pointwise Convolution)
+
+Pointwise Convolution 的本质就是 1X1 的卷积,它的卷积核的尺寸为 1×1×M,M 为上一层输出信息的通道数。所以这里 Pointwise Convolution 的每个卷积核会将上一步的特征图在通道方向上进行加权组合,生成新的特征图,如下图所示:
+![Cnn](./images/02Cnn10.png)
+
+#### MBconv模块
+
+MBconv 由 Depthwise Convolution,BN,ReLU 组成,基本结构如下图右面所示:
+
+![Cnn](./images/02Cnn11.png)
+
+整体网络就是通过不断堆叠 MBconv 组件,这种深度可分离卷积的操作方式在减少计算量的同时保持了模型的表达能力。
+
+#### 分别是宽度乘子(α)和分辨率乘子(ρ)
+
+宽度和分辨率调整系数用于调整模型的大小和计算复杂性。
+- **宽度系数(α):宽度系数是一个介于 0 和 1 之间的比例因子。通过降低每个卷积层的通道数,可以减少模型中的参数数量和计算量,从而使模型更轻量化**。
+- **分辨率系数(ρ):分辨率系数是一个介于 0 和 1 之间的比例因子。通过降低输入图像的分辨率,可以减少卷积操作的计算量和内存消耗**。
+
+### MobileNet V2
+
+**MobileNet V2**:2018 年在 MobileNet V1 的基础上又提出了改进版本 MobileNet V2,V2 中主要用到了 Inverted Residuals 和 Linear Bottlnecks。
+
+#### Inverted Residuals
+
+在 Inverted Residual block 中,$3 \times 3 $卷积变成 Depthwise 了,计算量更少了,通过 $1\times 1 $卷积先提升通道数,再 Depthwise 3x3 卷积,最后用 1x1 卷积降低通道数。两端的通道数都很小,所以整体计算量并不大。
+
+![Cnn](./images/02Cnn12.png)
+
+#### Linear Bottleneck
+
+Linear Bottlnecks 上面的 Inverted Residuals block 中的 bottleneck 处的 ReLU 去掉。整体的网络模型就是由堆叠下图右图的 Bottlenecks 搭建成的。
+
+![Cnn](./images/02Cnn13.png)
+
+#### 关于 ReLU6
+
+卷积之后通常会接一个 ReLU 非线性激活,在 MobileNet 中使用 ReLU6。ReLU6 在普通的 ReLU 基础上限制最大输出为 6,这是为了在移动端设备 float16/int8 的低精度的时候也能有很好的数值分辨率。如果对 ReLU 的激活范围不加限制,输出范围为 0 到正无穷,如果激活值非常大,分布在一个很大的范围内,则低精度的 float16/int8 无法很好地精确描述如此大范围的数值,带来精度损失。
+
+### MobileNet V3
+
+**MobileNetV3**: 整体架构基本沿用了 MobileNetV2 的设计,采用了轻量级的深度可分离卷积和残差块等结构,依然是由多个模块组成,但是每个模块得到了优化和升级。主要贡献点在于:
+
+- **神经网络搜索技术:由资源受限的 NAS 执行模块级搜索,NetAdapt 执行局部搜索**。
+
+- **网络结构改进:将最后一步的平均池化层前移并移除最后一个卷积层,引入 h-swish 激活函数**。
+
+#### SE 结构
+
+首先使用一个全局池化层将每个通道变成一个具体的数值,然后接两个全连接层,最后通过一个 H-Sigmoid 函数获取最终的权重,赋值给最初的特征图。
+
+![Cnn](./images/02Cnn14.png)
+
+#### 重新设计耗时层结构
+
+首先,减少网络第一个卷积层的卷积核个数,从 32 减到 16,然后精简了最后的 Stage,将原来搜索到的最后阶段的人工精简,删除了多余的卷积层,将延迟较少了 7 毫秒,将近全部运行时间的 11%,并减少了 3000 万的乘加操作次数,几乎没有损失准确性。
+
+![Cnn](./images/02Cnn15.png)
+
+#### 重新设计激活函数
+
+引入新的非线性激活函数:h-swish。swish 公式:
+
+$$
+Swish x = x*α(x)
+$$
+
+这里σ(x)是 sigmoid 函数。swish 虽然提高了精度,但 sigmoid 函数计算是极为昂贵的,在嵌入式移动端不适合它的存在,因此,MobileNet_V3 提出了计算更为简便的 h-swish 函数,其定义如下:
+
+$$
+h-swish[x] = x\frac{ReLU6(x+3)}{6}
+$$
+
+#### NAS 搜索全局结构(Block-wise Search)
+
+采用 NSA 方法来搜寻全局网络结构,另外需要针对轻量模型进行优化,用一个多目标奖励。
+
+$$
+{ACC(m)x[LAT(m)/TAR]}^{w}
+$$
+
+来近似 pareto 最优解,根据目标延迟 TAR 为每个模型 m 平衡模型精度 ACC(m)和延迟 LAT(m)。用较小的权重因子 w =-0.15 来弥补不同的延迟的更大精度变化。从头训练了一个新的架构搜索,找到了初始的 seed 模型,然后应用 NetAdapt 和其他优化来获得最终的 MobilenetV3-Small 模型。
+
+#### NetAdapt 搜索层结构(Layer-wise Search)
+
+$$
+\frac{ΔACC}{ΔLatency}
+$$
+
+给定一个 K conv and FC layers 的网络 Net,在每一步的结构更改中,需要减少一个给定个值 deltaR,然后调整每层的卷积核数,生成一个 Net_simp 集合,从中找到目标延时的网络。保持循环,直到满足给定条件后 finetune 网络。V3 用了两种减少延迟的方法来产生网络:
+
+- **减少 expansion layer 的 size**。
+
+- **减少所有共享相同 bottleneck size 模块的瓶颈**。
+
+## 小结与思考
+
+- SqueezeNet系列,ShuffleNet系列是从人工去设计网络中的重要模块去轻量化模型;
+
+- MobileNet系列除了一些轻量化的模块设计,还结合了流行的Nas搜索技术去设计去更轻量化,准确率更高的模型;
+
+
+
+
+
+
+
diff --git a/04Inference/02Mobilenet/03Cnn.md b/04Inference/02Mobilenet/03Cnn.md
new file mode 100644
index 00000000..f2f696c7
--- /dev/null
+++ b/04Inference/02Mobilenet/03Cnn.md
@@ -0,0 +1,248 @@
+
+
+# CNN 模型小型化(下)
+
+在本章节会接着介绍CNN模型的小型化,除了第二节提到的三个模型外,在本章节会继续介绍ESPNet系列,FBNet系列,EfficientNet系列和GhostNet系列。
+
+## ESPNet系列
+
+### ESPNetV1
+
+**ESPNet V1**:应用在高分辨图像下的语义分割,在计算、内存占用、功耗方面都非常高效。主要贡献在于基于传统卷积模块,提出高效空间金子塔卷积模块(ESP Module),有助于减少模型运算量和内存、功率消耗,来提升终端设备适用性,方便部署到移动端。
+
+#### ESP 模块
+
+基于卷积因子分解的原则,ESP(Efficient spatial pyramid)模块将标准卷积分解成 point-wise 卷积和空洞卷积金字塔(spatial pyramid of dilated convolutions)。point-wise 卷积将输入的特征映射到低维特征空间,即采用 K 个 1x1xM 的小卷积核对输入的特征进行卷积操作,1x1 卷积的作用其实就是为了降低维度,这样就可以减少参数。空洞卷积金字塔使用 K 组空洞卷积的同时下采样得到低维特征,这种分解方法能够大量减少 ESP 模块的参数和内存,并且保证了较大的感受野(如下图 a 所示)。
+
+![Cnn](images/03Cnn01.png)
+
+#### HFF 特性
+
+虽然将扩张卷积的输出拼接在一起会给 ESP 模块带来一个较大的有效感受野,但也会引入不必要的棋盘或网格假象,如下图所示。
+
+![Cnn](images/03Cnn02.png)
+
+上图(a)举例说明一个网格伪像,其中单个活动像素(红色)与膨胀率 r = 2 的 3×3 膨胀卷积核卷积。
+
+上图(b)具有和不具有层次特征融合(Hierarchical feature fusion,HFF)的 ESP 模块特征图可视化。ESP 中的 HFF 消除了网格伪影。彩色观看效果最佳。
+
+为了解决 ESP 中的网格问题,使用不同膨胀率的核获得的特征映射在拼接之前会进行层次化添加(上图b中的 HFF)。该解决方案简单有效,且不会增加 ESP 模块的复杂性,这与现有方法不同,现有方法通过使用膨胀率较小的卷积核学习更多参数来消除网格误差[Dilated residual networks,Understanding convolution for semantic segmentation]。为了改善网络内部的梯度流动,ESP 模块的输入和输出特征映射使用元素求和[Deep residual learning for image recognition]进行组合。
+
+### ESPNetV2
+
+### EESP 模块
+
+EESP 模块结构如下图,图 b 中相比于 ESPNet,输入层采用分组卷积,DDConv+Conv1x1 取代标准空洞卷积,依然采用 HFF 的融合方式,(c)是(b)的等价模式。当输入通道数 M=240,g=K=4, d=M/K=60,EESP 比 ESP 少 7 倍的参数。
+
+![Cnn](images/03Cnn03.png)
+
+描述了一个新的网络模块 EESP,它利用深度可分离扩张和组逐点卷积设计,专为边缘设备而设计。该模块受 ESPNet 架构的启发,基于 ESP 模块构建,使用了减少-分割-变换-合并的策略。通过组逐点和深度可分离扩张卷积,该模块的计算复杂度得到了显著的降低。进一步,描述了一种带有捷径连接到输入图像的分层 EESP 模块,以更有效地学习多尺度的表示。
+
+如上图中 b 所示,能够降低 $\frac{Md+n^{2}d^{2}K}{\frac{Md}{g}+(n^{2}+d)dK}$ 倍计算复杂度,K 为空洞卷积金字塔层数。考虑到单独计算 K 个 point-wise 卷积等同于单个分组数为 K 的 point-wise 分组卷积,而分组卷积的在实现上更高效,于是改进为上图 c 的最终结构。
+
+## FBNet系列
+
+### FBNet V1
+
+**FBNetV1**:完全基于 NAS 搜索的轻量级网络系列,结合了 DNAS 和资源约束。采用梯度优化的方法优化卷积结构,避免像以前的方法那样分别枚举和训练各个体系结构。FBNets-B 在 ImageNet 上 top-1 准确率为 74.1%,295M FLOPs。
+
+#### DNAS 方法
+
+FBNet v1 的训练方法和构建网络的方法基本上沿用了 DARTS 的方法,不同的是 DARTS 的 Super net 主要体现在 Cell 结构里,搜索空间包括 cell 内部的连接和路径上的操作;而 FBNet 体现在整个网络的主体里,连接是确定的,只搜索路径上的操作。流程如下图所示。DNAS 方法将整体的搜索空间表示为超网,将寻找最优网络结构问题转换为寻找最优的候选 block 分布,通过梯度下降来训练 block 的分布,而且可以为网络每层选择不同的 block。为了更好的估计网络的时延,预先测量并记录了每个候选 block 的实际时延,在估算时直接根据网络结构和对应的时延累计即可。
+
+DNAS 将网络结构搜索问题公式化为:
+
+$$\underset {a∈A}{min} \underset {w_{a}}{min} L(a,w_{a}) \tag{1}$$
+
+给定结构空间 A,寻找最优的结构 $a∈A$,在训练好权值后 $w_{a}$,可以满足最小化损失 $L(a,w_{a})$,论文主要集中于 3 个因素:搜索空间、考虑实际时延的损失函数以及高效的搜索算法。
+
+![Cnn](images/03Cnn04.png)
+
+#### Latency-Aware 损失函数
+
+公式 1 中的损失函数不仅要反映准确率,也要反应目标硬件上的时延。因此,定义以下损失函数:
+
+$$L(a,w_{a}) = CE(a,w_{a})\cdot αlog(LAT(a)^{β})\tag{2}$$
+
+$CE(a,w_{a})$ 表示交叉熵损失,LAT(a)表示当前结构在目标硬件上的时延,α控制整体损失函数的幅值,β调整时延项的幅值。时延的计算可能比较耗时,论文使用 block 的时延 lookup 表格来估计网络的的整体:
+
+$$LAT(a) = \sum_{l}LAT(b_{l}^{(a)})\tag{3} $$
+
+其中 $b_{l}^{(a)}$ 为结构 a 中 l 层的 block,这种估计方法假设 block 间的计算相互独立,对 CPUs 和 DSPs 等串行计算设备有效,通过这种方法,能够快速估计 $10^{21}$ 种网络的实际时延。
+
+
+### FBNet V2
+
+**FBNetV2**: 提出了 DMaskingNAS,将 channel 数和输入分辨率分别以 mask 和采样的方式加入到超网中,在带来少量内存和计算量的情况下,大幅增加搜索空间。同时采用一种用于特征映射重用的屏蔽机制,使得随着搜索空间的扩大,存储和计算成本几乎保持不变。此外,本文采用有效的形状传播来最大化每个触发器或每个参数的精度。与所有以前的架构相比,搜索到的 FBNetV2s 具有一流的性能。
+
+### 通道搜索
+
+把不同的 channel 加入搜索空间,之前的 DNAS 方法就是把不同的选项融进超网,这样会带来接近 o(N2)种选择的可能。为了减少搜索 channel 时候的计算量,作者构造了 channel masking 的机制,把不同 channel 的最终输出,表征为和一个 mask 相乘的形式,如下图所示。
+
+![Cnn](images/03Cnn05.png)
+
+其中右边那个灰色的长方体表示一个 shape 为(c, h, w)的 tensor,和左边的 mask 向量 M 相乘的结果。M 可以拆解为多个 mask,m1,m2,m3...和对应 3 的 Gumbel Softmax 的系数 g1,g2,g3...的乘积和。通过调节左边的 mask,就能得到等价的不同 channel 的结果。相当于对一个大的 tensor,mask 掉额外的 channel,得到相应的别的 channel 的结果。
+
+在通道搜索中,作者假设不同的每一层的通道路径都共享一个卷积核参数,不同 channel 的输出取决于一个叫做 mask 的向量。比如图中 g1 g2 和 g3 是不同 channel 选择的架构参数,对应的白蓝条状是 mask 向量,其中白色表示 1,蓝色表示 0,分别和卷积相乘,那么白色对应的部分表示该路径上的输出 channel 个数,蓝色部分表示该路径上没有这部分 channel,但是在整体计算上维度是保持一致的,不同 mask 向量分别和卷积核参数相乘,再用 channel 的架构参数加权和。这样在搜索的过程中,通过架构参数就可以知道每个 stage 中的卷积核该选择多少个输出 channel。
+
+想要进行加权和,首先就会遇到下图 Step A 中的问题:channel 不同,对应的 tensor shape 不同,无法直接相加。为了解决这个问题,可以引入 Step B 中的方法:对输出做 zero padding,使之 shape 对齐(图中蓝色部分),然后加权求和。Step B 和 Step C 是等价的,Step C 相当于对卷积的 filter 进行 mask,随后作者又进行了一个简化的假设,假设所有的 weighting 共享,也就是 Step D 的形式。Step E 和 Step D 是等效的,即为最终的 channel masking 机制。
+
+给定输入 x,Gumbel Softmax 输出如下,Gumbel 权重为 gi:
+
+$$
+y = \sum^{k}_{i=1}g_{i}P_{AD}(b_{i}(x),k) \tag{1}
+$$
+
+注意,这相当于将所有卷积的滤波器数量增加到 k,并屏蔽掉额外的通道(下图,步骤 C)。$l_{i} \in R^{k}$ 是一个列向量,I 以 1 开头,k-i 以 0 结尾。注意,搜索方法对于 1 和 0 的排序是不变的。由于所有块 bi 具有相同数量的滤波器,可以通过共享权重来近似,使得 bi = b(下图,步骤 D):
+
+$$
+y = \sum^{k}_{i=1}g_{i}(b(x)\circ l_{i}) \tag{2}
+$$
+
+最后,利用这种近似,可以处理原始信道搜索方法的计算复杂性:这相当于计算集合掩码并且只运行块 b 一次(下图,步骤 E)
+
+$$
+y=b(x)\circ \underbrace{\sum^{k}_{i=1}g_{i}l_{i}}_{M} \tag{3}
+$$
+
+这种近似只需要一个正向传递和一个特征映射,除了等式 3 中可忽略的 M 项之外,不会引起额外的 FLOP 或存储器成本。(图 Channel Masking for channel search(DMaskingNAS),通道屏蔽)。此外,这种近似并不等价,只是因为权重是共享的,这在 DNAS 被证明可以减少训练时间和提高准确性[Single-path nas: Device-aware efficient convnet design]。这使本文能够搜索任何模块的输出通道数,包括相关的架构决策,如反向残差模块中的扩展速率。
+
+![Cnn](images/03Cnn06.png)
+
+#### FBNetV3
+
+**FBNetV3**:论文认为目前的 NAS 方法大都只满足网络结构的搜索,而没有在意网络性能验证时的训练参数的设置是否合适,这可能导致模型性能下降。为此,论文提出 JointNAS,在资源约束的情况下,搜索最准确的训练参数以及网络结构。
+
+### 联合搜索
+
+JointNAS,分粗粒度和细粒度两个阶段,对网络架构和训练超参都进行搜索。JointNAS 优化目标可公式化为:
+
+$$
+\underset{(A,h)∈Ω}{max} acc(A,h),subject to g_{i}(A)\leqslant C_{i} for i=1,..,τ \tag{1}
+$$
+
+A,h,Ω分别表示网络架构、训练策略以及搜索空间;$g_{i}(A)$,$τ$ 分别表示资源约束信息资源消耗计算和资源数量,acc 计算当前结构和训练参数下的准确率。
+
+- **粗粒度阶段(coarse-grained):**该阶段主要迭代式地寻找高性能的候选网络结构-超参数对以及训练准确率预测器。
+
+- **细粒度阶段(fine-grained):**借助粗粒度阶段训练的准确率预测器,对候选网络进行快速的进化算法搜索,该搜索集成了论文提出的超参数优化器 Auto Train。
+
+## EfficientNet系列
+
+### EfficientNet V1
+
+**EfficientNetV1**:重点分析了卷积网络的深度,宽度和输入图像大小对卷积网络性能表现的影响,提出了一种混合模型尺度的方法,通过设置一定的参数值平衡调节卷积网络的深度,宽度和输入图像大小,使卷积网络的表现达到最好。
+
+#### 复合缩放
+
+为了追求更好的精度和效率,在连续网络缩放过程中平衡网络宽度、深度和分辨率的所有维度是至关重要的。如下图所示。
+
+![Cnn](images/03Cnn07.png)
+
+不同维度的 Scaling 并不相互独立,需要协调和平衡不同维度的 Scaling,而不是常规的单维度 Scaling。EfficientNet 提出了 compound scaling method(复合缩放方法),这种方法是通过一个复合系数φ去统一缩放网络的宽度,深度和分辨率,公式表示如下:
+$$
+depth:d=α^{φ}
+$$
+
+$$
+width:w=β^{φ}
+$$
+
+$$
+resolution:r=γ^{φ}
+$$
+
+$$
+s.t. α\cdotβ^{2}\cotγ^{2}\approx 2
+$$
+
+$$
+α\geq1,β\geq1,γ\geq1
+$$
+其中,α、β以及γ是常数,可以通过在 baseline 上做 small grid search 来得到。ϕ 是用户指定的系数,用于控制有多少其他计算资源可用于模型缩放,而 α,β,γ 指定如何分别将这些额外资源分配给网络宽度,深度和分辨率。
+
+需要注意的是:常规卷积运算的 FLOPS 与 d,$w^{2}$,$r^{2}$ 成正比,即网络深度增加 1 倍会使 FLOPS 增加 1 倍,网络宽度或分辨率增加 1 倍会使 FLOPS 增加 4 倍。
+
+由于卷积运算通常在 ConvNets 中占主导地位,因此根据上述的等式,缩放 ConvNets 将使总 FLOPS 大约增加 $(α⋅β^{2}⋅γ^{2})ϕ$。在本文中,作者做了 $α⋅β^{2}⋅γ^{2}≈2$ 的约束,这样对于任何新的 ϕ ,总 FLOPS 大约会增加 $2^{ϕ}$
+
+### EfficientNet V2
+
+#### 训练感知 NAS 和缩放
+
+**NAS 搜索**
+
+这里采用的是 trainning-aware NAS framework,搜索工作主要还是基于之前的 Mnasnet 以及 EfficientNet. 但是这次的优化目标联合了 accuracy、parameter efficiency 以及 trainning efficiency 三个维度。这里是以 EfficientNet 作为 backbone,设计空间包含:
+
+- convolutional operation type : MBConv, Fused-MBConv
+
+- number of layer
+
+- kernel size : 3x3, 5x5
+
+- expansion ratio : 1, 4, 6
+
+另外,作者通过以下方法来减小搜索空间的范围:
+
+移除不需要的搜索选项,重用 EfficientNet 中搜索的 channel sizes,接着在搜索空间中随机采样了 1000 个模型,并针对每个模型训练 10 个 epochs(使用较小的图像尺度)。搜索奖励结合了模型准确率 A,标准训练一个 step 所需时间 S 以及模型参数大小 P,奖励函数可写成:
+$$
+A \cdot S^{w}\cdot P^{v}
+$$
+
+其中,A 是模型精度、S 是归一化训练时长,P 是参数量,w=-0.07 和 v=-005。
+
+与 V1 的不同:
+
+ 1.除了使用 MBConv 之外还使用了 Fused-MBConv 模块,加快训练速度与提升性能。
+
+ 2.使用较小的 expansion ratio (之前是 6),从而减少内存的访问量。
+
+ 3.趋向于选择 kernel 大小为 3 的卷积核,但是会增加多个卷积用以提升感受野。
+
+ 4.移除了最后一个 stride 为 1 的 stage,从而减少部分参数和内存访问。
+
+**EfficientNetV2 缩放**
+
+作者在 EfficientNetV2-S 的基础上采用类似 EfficientNet 的复合缩放,并添加几个额外的优化,得到 EfficientNetV2-M/L。
+
+额外的优化描述如下:
+
+ 1.限制最大推理图像尺寸为 480。
+
+ 2.在网络的后期添加更多的层提升模型容量且不引入过多耗时。
+
+## GhostNet 系列
+
+### GhostNet V1
+
+**GhostNet V1**:提供了一个全新的 Ghost Module,旨在通过廉价操作生成更多的特征图。基于一组原始的特征图,作者应用一系列廉价的线性变换(cheap linear operations),以很小的代价生成许多能从原始特征发掘所需信息的 Ghost 特征图。该 Ghost 模块即插即用,通过堆叠 Ghost Module 得出 Ghost bottleneck,进而搭建轻量级神经网络——GhostNet。在 ImageNet 分类任务,GhostNet 在相似计算量情况下 Top-1 正确率达 75.7%,高于 MobileNetV3 的 75.2%。
+
+#### Ghost Module
+
+利用`Ghost Module`生成与普通卷积层相同数量的特征图,我们可以轻松地将`Ghost Module`替换卷积层,集成到现有设计好的神经网络结构中,以减少计算成本。第一、先通过普通的 conv 生成一些特征图。第二、对生成的特征图进行 cheap 操作生成冗余特征图,这步使用的卷积是 DW 卷积。第三将 conv 生成的特征图与 cheap 操作生成的特征图进行 concat 操作。如下图(b)所示,展示了 Ghost 模块和普通卷积的过程。
+
+![Cnn](images/03Cnn08.png)
+
+### GhostNet V2
+
+**GhostNet V2**:GhostV2 的主要工作就是在 Ghost module 的基础上,添加了一个改进的注意力块。文中称为解耦全连接注意力机制 DFC(Decouplod fully connected)。它不仅可以在普通硬件上快速执行,还可以捕获远程像素之间的依赖关系。大量的实验表明,GhostNetV2 优于现有的体系结构。例如,它在具有 167M FLOPs 的 ImageNet 上实现了 75.3%的 top-1 精度,显著高于 GhostNetV1 (74.5%),但计算成本相似。
+
+#### 解耦全连接注意力机制DFC
+
+虽然自注意力操作可以很好地建模长距离依赖,但是部署效率低。相比自注意力机制,具有固定权重的 FC 层更简单,更容易实现,也可以用于生成具有全局感受野的 attention maps。
+
+给定特征图 $Z ∈ R ^{H \times W\times C}$,它可以看作 hw 的 tokens,记作 $z_{i}\in R^{C}$,也就是 $Z={z_{11},z_{12},...,z_{hw}}$。FC 层生成 attention map 的公式表达如下:
+
+$$
+a_{hw} = \sum_{h',w'} F_{h,w,h',w'}\odot z_{h',w'}\tag{1}
+$$
+
+其中,$\odot$ 表示 element-wise multiplication,F 是 FC 层中可学习的权重,$A={a_{11},a_{12},...,a_{HW}}$。根据上述公式,将所有 tokens 与可学习的权重聚合在一起以提取全局信息,该过程比经典的自注意力简单的多。然而,该过程的计算复杂度仍然是二次方,特征图的大小为 $ \mathcal{O}({H^{2}W^{2}})$,这在实际情况下是不可接受的,特别是当输入的图像是高分辨率时。
+
+## 总结
+
+- ESPNet与GhostNet系列延续了SqueezeNet等系列,从模型结构的改进来进行参数量计算量的减少;
+- FBNet与EfficientNet系列则是利用并优化了NAS搜索技术从而获得了轻量化的模型结构;
+
+## 本节视频
+
+
diff --git a/04Inference/02Mobilenet/04Transformer.md b/04Inference/02Mobilenet/04Transformer.md
new file mode 100644
index 00000000..8a30ea2c
--- /dev/null
+++ b/04Inference/02Mobilenet/04Transformer.md
@@ -0,0 +1,154 @@
+
+
+# Transformer模型小型化
+
+自 Vision Transformer 出现之后,人们发现 Transformer 也可以应用在计算机视觉领域,并且效果还是非常不错的。但是基于 Transformer 的网络模型通常具有数十亿或数百亿个参数,这使得它们的模型文件非常大,不仅占用大量存储空间,而且在训练和部署过程中也需要更多的计算资源。所以在本节中会介绍关于 Transformer 一些轻量化工作。
+
+## MobileVit 系列
+
+### MobileVit V1
+
+**MobileVit V1** :MobileViT 是一种基于 ViT(Vision Transformer)架构的轻量级视觉模型,旨在适用于移动设备和嵌入式系统。ViT 是一种非常成功的神经网络模型,用于图像分类和其他计算机视觉任务,但通常需要大量的计算资源和参数。MobileViT 的目标是在保持高性能的同时,减少模型的大小和计算需求,以便在移动设备上运行,据作者介绍,这是第一次基于轻量级 CNN 网络性能的轻量级 ViT 工作,性能 SOTA。性能优于 MobileNetV3、CrossviT 等网络。
+
+#### Mobile ViT 块
+
+标准卷积涉及三个操作:展开+局部处理+折叠,利用 Transformer 将卷积中的局部建模替换为全局建模,这使得 MobileViT 具有 CNN 和 ViT 的性质。MobileViT Block 如下图所示:
+
+![MobileVit](images/04Transformer01.png)
+
+从上面的模型可以看出,首先将特征图通过一个卷积层,卷积核大小为 $n\times n$,然后再通过一个卷积核大小为 $1\times 1$ 的卷积层进行通道调整,接着依次通过 Unfold、Transformer、Fold 结构进行全局特征建模,然后再通过一个卷积核大小为 $1\times 1$ 的卷积层将通道调整为原始大小,接着通过 shortcut 捷径分支与原始输入特征图按通道 concat 拼接,最后再通过一个卷积核大小为 $n\times n$ 的卷积层进行特征融合得到最终的输出。
+
+#### 多尺度采样训练
+
+给定一系列排序的空间分辨率$S = {(H_{1}, W_{1}), ··· , (H_{n}, W_{n})}$,最大空间分辨率有最小的batch,加快优化更新;在每个GPU第t次迭代中随机抽样一个空间分辨率,然后计算迭代大小;相较于以前多尺度采样,这次它不需要自己每隔几个iteration微调得到新的空间分辨率,并且改变batch提高了训练速度;使用多GPU进行训练(我猜不同空间分辨率在不同的GPU上运行)这个可以提高网络的泛化能力,减少训练和验证之间差距;并且适用于其他网络训练。
+
+![MobileVit](images/04Transformer02.png)
+
+## MobileFormer系列
+
+### MobileFormer
+
+**MobileFormer**:一种通过双线桥将 MobileNet 和 Transformer 并行的结构。这种方式融合了 MobileNet 局部性表达能力和 Transformer 全局表达能力的优点,这个桥能将局部性和全局性双向融合。和现有 Transformer 不同,Mobile-Former 使用很少的 tokens(例如 6 个或者更少)随机初始化学习全局先验,计算量更小。
+
+### 并行结构
+
+Mobile-Former 将 MobileNet 和 Transformer 并行化,并通过双向交叉注意力连接(下见图)。Mobile(指 MobileNet)采用图像作为输入($X\in R^{HW \times 3}$),并应用反向瓶颈块提取局部特征。Former(指 Transformers)将可学习的参数(或 tokens)作为输入,表示为 $Z\in R^{M\times d}$,其中 M 和 d 分别是 tokens 的数量和维度,这些 tokens 随机初始化。与视觉 Transformer(ViT)不同,其中 tokens 将局部图像 patch 线性化,Former 的 tokens 明显较少(M≤6),每个代表图像的全局先验知识。这使得计算成本大大降低。
+
+![MobileFormer](images/04Transformer03.png)
+
+### 低成本双线桥
+
+Mobile 和 Former 通过双线桥将局部和全局特征双向融合。这两个方向分别表示为 Mobile→Former 和 Mobile←Former。我们提出了一种轻量级的交叉注意力模型,其中映射($W^{Q}$,$W^{K}$,$W^{V}$)从 Mobile 中移除,以节省计算,但在 Former 中保留。在通道数较少的 Mobile 瓶颈处计算交叉注意力。具体而言,从局部特征图 X 到全局 tokens Z 的轻量级交叉注意力计算如下:
+
+$$
+A_{X->Z} = [Attn(\widetilde{z_{i}}W_{i}^{Q},\widetilde{x_{i}},\widetilde{x_{i}})]_{i=1:h}W^{o}\tag{1}
+$$
+
+其中局部特征 X 和全局 tokens Z 被拆分进入 h 个头,即 $X=[\widetilde{x_{1}}...\widetilde{x_{h}}],Z=[\widetilde{z_{1}}...\widetilde{z_{h}}]$ 表示多头注意力。第 i 个头的拆分 $\widetilde{z_{1}}\in R^{M \times \frac {d}{h} }$ 与第 i 个 token$\widetilde{z_{1}}\in R^{d}$ 不同。$W_{i}^{Q}$ 是第 i 个头的查询映射矩阵。$W^{O}$ 用于将多个头组合在一起。Attn(Q,K,V)是查询 Q、键 K 和值 V 的标准注意力函数,即 :
+
+$$
+softmax(\frac{QK^{T}}{\sqrt{d_{k}}})
+$$
+其中 $[.]_{1:h}$ 表示将 h 个元素 concat 到一起。需要注意的是,键和值的映射矩阵从 Mobile 中移除,而查询的映射矩阵 $W_{i}^{Q}$ 在 Former 中保留。类似地从全局到局部的交叉注意力计算如下:
+$$
+A_{Z->X} = [Attn(\widetilde{x_{i}},\widetilde{z_{i}}\odot W_{i}^{K},\widetilde{z_{i}}\odot W_{i}^{V})]_{i=1:h}\tag{2}
+$$
+
+其中 $W_{i}^{K}$ 和 $W_{i}^{V}$ 分别是 Former 中键和值的映射矩阵。而查询的映射矩阵从 Mobile 中移除。
+
+### Mobile-Former 块
+
+Mobile-Former 由 Mobile-Former 块组成。每个块包含四部分:Mobile 子块、Former 子块以及双向交叉注意力 Mobile←Former 和 Mobile→Former(如下图所示)。
+
+![MobileFormer](images/04Transformer04.png)
+
+输入和输出:Mobile-Former 块有两个输入:(a) 局部特征图 $X\in R^{HW\times C}$,为 C 通道、高度 H 和宽度 W,以及(b) 全局 tokens $Z\in R^{M\times d}$,其中 M 和 d 是分别是 tokens 的数量和维度,M 和 d 在所有块中一样。Mobile-Former 块输出更新的局部特征图 $X$ 和全局 tokens$Z$,用作下一个块的输入。
+
+Mobile 子块:如上图所示,Mobile 子块将特征图 $X$ 作为输入,并将其输出作为 Mobile←Former 的输入。这和反向瓶颈块略有不同,其用动态 ReLU 替换 ReLU 作为激活函数。不同于原始的动态 ReLU,在平均池化特征图上应用两个 MLP 以生成参数。我们从 Former 的第一个全局 tokens 的输出 $z'_{1}$ 应用两个 MLP 层(上图中的θ)保存平均池化。其中所有块的 depth-wise 卷积的核大小为 3×3。
+
+## EfficientFormer系列
+
+### EfficientFormer V1
+
+**EfficientFormer V1**:基于 ViT 的模型中使用的网络架构和具体的算子,找到端侧低效的原因。然后引入了维度一致的 Transformer Block 作为设计范式。最后,通过网络模型搜索获得不同系列的模型 —— EfficientFormer。
+
+#### EfficientFormer 结构
+
+![EfficientFormer](images/04Transformer05.png)
+
+基于延迟分析,作者提出了 EfficientFormer 的设计,如上图所示。该网络由 patch 嵌入(PatchEmbed)和 meta transformer 块堆栈组成,表示为 MB:
+$$
+y = \prod_{i}^{m}MB_{i}(PatchEmbed(X_{0}^{B,3,H,W}))
+$$
+
+其中 $X_{0}$ 是 Batch 大小为 B、空间大小为 $[H,W]$ 的输入图像,$y$ 是所需输出,$m$ 是块的总数(深度)。$MB$ 由未指定的 token 混合器(TokenMixer)和一个 MLP 块组成,可以表示为:
+
+$$
+X_{i+1} = MB_{i}(X_{i})=MLP(TokenMixer(X_{i}))
+$$
+
+其中,$X_{i|i>0}$ 是输入到第 $i$ 个 $MB$ 的中间特征。作者进一步将 Stage(或 S)定义为多个 MetaBlocks 的堆栈,这些 MetaBlocks 处理具有相同空间大小的特征,如上图中的 $N1×$ 表示 $S1$ 具有 $N1$ 个 MetaBlocks。该网络包括 4 个阶段。在每个阶段中,都有一个嵌入操作来投影嵌入维度和下采样 token 长度,如上图所示。在上述架构中,EfficientFormer 是一个完全基于 Transformer 的模型,无需集成 MobileNet 结构。接下来,作者深入研究了网络设计的细节。
+
+#### Dimension-consistent Design
+
+作者提出了一种维度一致性设计,该设计将网络分割为 4D 分区,其中操作符以卷积网络样式实现(MB4D),以及一个 3D 分区,其中线性投影和注意力在 3D 张量上执行,以在不牺牲效率的情况下享受 MHSA 的全局建模能力(MB3D),如上图所示。具体来说,网络从 4D 分区开始,而 3D 分区应用于最后阶段。注意,上图只是一个实例,4D 和 3D 分区的实际长度稍后通过架构搜索指定。
+
+首先,输入图像由一个具有两个步长为 2,感受野为 3×3 卷积的 Conv stem 处理:
+
+$$
+X_{1}^{B,C_{j|j=1,\frac{H}{4},\frac{W}{4}}} = PatchEmbed(X_{0}^{B,3,H,W})
+$$
+
+其中,$C_{j}$ 是第 j 级的通道数量。然后,网络从 MB4D 开始,使用一个简单的池化混合器来提取低级特征:
+
+$$
+I_{i} = Pool(X_{i}^{B,C,\frac{H}{2^{j+1}},\frac{W}{2^{j+1}}})+X_{i}^{B,C,\frac{H}{2^{j+1}},\frac{W}{2^{j+1}}}
+$$
+
+$$
+X_{i+1}^{B,C,\frac{H}{2^{j+1}},\frac{W}{2^{j+1}}}=Conv_{B}(Conv_{B,G(I_{i}))}+I_{i}
+$$
+
+其中,$Conv_{B,G}$ 表示卷积后分别接 BN 和 GeLU。注意,这里作者没有在池化混合器之前使用 LN,因为 4D 分区是基于 CONV-BN 的设计,因此每个池化混合器前面都有一个 BN。
+
+在处理完所有 MB4D 块后,作者执行一次 reshape 以变换特征大小并进入 3D 分区。MB3D 遵循传统 ViT 结构,如上图所示:
+
+$$
+I_{i} = Linear(MHSA(Linear(LN(X_{i}^{B,\frac{HW}{4^{j+1}},C_{j}}))))+X_{i}^{B,\frac{HW}{4^{j+1}},C_{j}}
+$$
+
+$$
+X_{i+1}^{B,\frac{HW}{4^{j+1}},C_{j}} = Linear(Linear_{G}(LN(I_{i})))+I_{i}
+$$
+
+其中,$Linear_{G}$ 表示线性,后跟 GeLU。
+
+$$
+MHSA(Q,K,V) = Softamax(\frac{Q\odot K^{T}}{\sqrt{C_{j}}}). V
+$$
+
+其中 Q、K、V 表示通过线性投影学习的查询、键和值,b 表示作为位置编码的参数化注意力 bias。
+
+## 小结与思考
+
+- MobileVit系列,MobileFormer系列是从模型结构上进行轻量化设计,在MobileNet的基础上,针对Transformer注意力模块去设计轻量化模型;
+
+- EfficientFormer系列在Vit基础上结合了搜索算法设计轻量化的模型;
+
+## 本节视频
+
+
+
+
+
+# 轻量化网络总结
+
+## 如何选择轻量化网络
+
+- 不同网络架构,即使FLOPs相同,但其MAC也可能差异巨大;
+
+- FLOPs低不等于latency低,结合具体硬件架构具体分析;
+
+- 多数时候加速芯片算力的瓶颈在于访存带宽;
+
+- 不同硬件平台部署轻量级模型需要根据具体业务选择对应指标;
diff --git a/04Inference/02Mobilenet/images/02Cnn01.png b/04Inference/02Mobilenet/images/02Cnn01.png
new file mode 100644
index 00000000..06ef552a
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn01.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn02.png b/04Inference/02Mobilenet/images/02Cnn02.png
new file mode 100644
index 00000000..170be124
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn02.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn03.png b/04Inference/02Mobilenet/images/02Cnn03.png
new file mode 100644
index 00000000..7f8507f3
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn03.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn04.png b/04Inference/02Mobilenet/images/02Cnn04.png
new file mode 100644
index 00000000..b5937ed1
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn04.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn05.png b/04Inference/02Mobilenet/images/02Cnn05.png
new file mode 100644
index 00000000..555aaab8
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn05.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn06.png b/04Inference/02Mobilenet/images/02Cnn06.png
new file mode 100644
index 00000000..271d550e
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn06.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn07.png b/04Inference/02Mobilenet/images/02Cnn07.png
new file mode 100644
index 00000000..11699dc2
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn07.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn08.png b/04Inference/02Mobilenet/images/02Cnn08.png
new file mode 100644
index 00000000..4ab7a8f1
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn08.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn09.png b/04Inference/02Mobilenet/images/02Cnn09.png
new file mode 100644
index 00000000..2d07d17c
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn09.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn10.png b/04Inference/02Mobilenet/images/02Cnn10.png
new file mode 100644
index 00000000..c24a67f5
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn10.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn11.png b/04Inference/02Mobilenet/images/02Cnn11.png
new file mode 100644
index 00000000..414a402d
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn11.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn12.png b/04Inference/02Mobilenet/images/02Cnn12.png
new file mode 100644
index 00000000..852ce37c
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn12.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn13.png b/04Inference/02Mobilenet/images/02Cnn13.png
new file mode 100644
index 00000000..316f5d35
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn13.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn14.png b/04Inference/02Mobilenet/images/02Cnn14.png
new file mode 100644
index 00000000..3b10075d
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn14.png differ
diff --git a/04Inference/02Mobilenet/images/02Cnn15.png b/04Inference/02Mobilenet/images/02Cnn15.png
new file mode 100644
index 00000000..ba92246f
Binary files /dev/null and b/04Inference/02Mobilenet/images/02Cnn15.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn01.png b/04Inference/02Mobilenet/images/03Cnn01.png
new file mode 100644
index 00000000..3655fe77
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn01.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn02.png b/04Inference/02Mobilenet/images/03Cnn02.png
new file mode 100644
index 00000000..891027cd
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn02.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn03.png b/04Inference/02Mobilenet/images/03Cnn03.png
new file mode 100644
index 00000000..21af0950
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn03.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn04.png b/04Inference/02Mobilenet/images/03Cnn04.png
new file mode 100644
index 00000000..fb41c5c1
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn04.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn05.png b/04Inference/02Mobilenet/images/03Cnn05.png
new file mode 100644
index 00000000..62e0ac5b
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn05.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn06.png b/04Inference/02Mobilenet/images/03Cnn06.png
new file mode 100644
index 00000000..f875c392
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn06.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn07.png b/04Inference/02Mobilenet/images/03Cnn07.png
new file mode 100644
index 00000000..a2aac433
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn07.png differ
diff --git a/04Inference/02Mobilenet/images/03Cnn08.png b/04Inference/02Mobilenet/images/03Cnn08.png
new file mode 100644
index 00000000..619ab93f
Binary files /dev/null and b/04Inference/02Mobilenet/images/03Cnn08.png differ
diff --git a/04Inference/02Mobilenet/images/04Transformer01.png b/04Inference/02Mobilenet/images/04Transformer01.png
new file mode 100644
index 00000000..b06b4c9a
Binary files /dev/null and b/04Inference/02Mobilenet/images/04Transformer01.png differ
diff --git a/04Inference/02Mobilenet/images/04Transformer02.png b/04Inference/02Mobilenet/images/04Transformer02.png
new file mode 100644
index 00000000..8ce45626
Binary files /dev/null and b/04Inference/02Mobilenet/images/04Transformer02.png differ
diff --git a/04Inference/02Mobilenet/images/04Transformer03 .png b/04Inference/02Mobilenet/images/04Transformer03 .png
new file mode 100644
index 00000000..2f50787a
Binary files /dev/null and b/04Inference/02Mobilenet/images/04Transformer03 .png differ
diff --git a/04Inference/02Mobilenet/images/04Transformer04.png b/04Inference/02Mobilenet/images/04Transformer04.png
new file mode 100644
index 00000000..3edd569a
Binary files /dev/null and b/04Inference/02Mobilenet/images/04Transformer04.png differ
diff --git a/04Inference/02Mobilenet/images/04Transformer05.png b/04Inference/02Mobilenet/images/04Transformer05.png
new file mode 100644
index 00000000..f70373f4
Binary files /dev/null and b/04Inference/02Mobilenet/images/04Transformer05.png differ
diff --git a/04Inference/06Kernel/06Memory.md b/04Inference/06Kernel/06Memory.md
index 58db78af..366ff823 100644
--- a/04Inference/06Kernel/06Memory.md
+++ b/04Inference/06Kernel/06Memory.md
@@ -2,110 +2,98 @@
# 推理内存布局
-从前文的简单介绍中,我们提到了可以从内存布局上对推理引擎的 Kernel 进行优化,接下来,我们将从内存,内存布局方面采用的多种经典方法来详细介绍。
+从前文的简单介绍中,我们提到了可以从内存布局上对推理引擎的Kernel进行优化,接下来,我们将先介绍CPU和GPU的基础内存知识,NCHWX内存排布格式以及详细展开描述MNN这个针对移动应用量身定制的通用高效推理引擎中通过数据内存重新排布进行的内核优化。
-========== 在推理引擎的内存布局,有一个很重要的事情就是主要是运行在推理卡,或者 CPU 上面。所以可以重点看看在推理芯片上是内存布局有哪些格式优化点。CPU 也是,我看过一些文章,你也可以重点多看看相关的论文。
+## 内存
-https://blog.csdn.net/hsqyc/article/details/115602310
-https://discuss.tf.wiki/t/topic/872
-https://github.com/alibaba-developer/Ali-Open-Source/blob/master/%E9%98%BF%E9%87%8C%E5%BC%80%E6%BA%90%EF%BC%81%E8%BD%BB%E9%87%8F%E7%BA%A7%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0%E7%AB%AF%E4%BE%A7%E6%8E%A8%E7%90%86%E5%BC%95%E6%93%8E%20MNN.md
+CPU内存主要架构图如下图所示,其中比较关键的是有主存,以及其上的多级缓存架构,CPU运行的速度太快,相对而言内存的读写速度就非常慢。如果CPU每次都要等内存操作完成,才可以继续后续的操作,那效率会非常低下。由此设计出了多级缓存架构,缓存级别越小,越靠近CPU,同样也意味着速度越快,但是对应的容量越少。
+![CPU架构示意图](images/06Memory01.png)
-## CPU 系统内存
+当CPU需要取数据时,如果通过索引得知缓存中没有该数据,那么此时CPU需要从RAM主存中先获取数据,然后将该数据及其临近数据加载到Cache缓存中,以便利用访问局部性提升访问命中率。当然多级缓存也会带来问题,即数据同步问题,当出现多核和乱序时,如何保证数据同步也需要提供一种内存屏障的规则。
-CPU 内存主要架构图如下图所示,其中比较关键的是有主存,以及其上的多级缓存架构,CPU 运行的速度太快,相对而言内存的读写速度就非常慢。如果 CPU 每次都要等内存操作完成,才可以继续后续的操作,那效率会非常低下。由此设计出了多级缓存架构,缓存级别越小,越靠近 CPU,同样也意味着速度越快,但是对应的容量越少。
+GPU内存主要架构图如下图所示,在主缓存等主要架构上,与CPU没太多的区别,也是多级缓存架构,其调度执行模式主要是按照SIMT模式进行,由许多 SM 组成。
-当 CPU 需要取数据时,如果通过索引得知缓存中没有该数据,那么此时 CPU 需要从 RAM 主存中先获取数据,然后将该数据及其临近数据加载到 Cache 缓存中,以便利用访问局部性提升访问命中率。当然多级缓存也会带来问题,即数据同步问题,当出现多核和乱序时,如何保证数据同步也需要提供一种内存屏障的规则。
+![GPU架构示意图](images/06Memory02.png)
-![CPU 内存架构示意图](images/06Memory01.png)
+SM(Streaming Multiprocessors):可以理解为一个 GPU 计算单元的小集合,好比多核 CPU 的一个核 —— 但 CPU 的一个核一般运行一个线程,而 SM 能够运行多个轻量线程,每一个 SM 有自己的 Wrap scheduler 、寄存器(Register)、指令缓存、L1缓存、共享内存。Wrap scheduler:运算规划器,可以理解为运算时一个 warp 抓一把线程扔进了 cores 里面进行计算。
-GPU 内存主要架构图如下图所示,在主缓存等主要架构上,与 CPU 没太多的区别,也是多级缓存架构,其调度执行模式主要是按照 SIMT 模式进行,由许多 SM 组成。SM(Streaming Multiprocessors):可以理解为一个 GPU 计算单元的小集合,好比多核 CPU 的一个核 —— 但 CPU 的一个核一般运行一个线程,而 SM 能够运行多个轻量线程,每一个 SM 有自己的 Wrap scheduler 、寄存器(Register)、指令缓存、L1 缓存、共享内存。
+GPU互相之间一般是通过PCIe桥直接传输数据,或者是通过NVLink这种专用的超高速数据传输通道来传输数据。
-Wrap scheduler:运算规划器,可以理解为运算时一个 warp 抓一把线程扔进了 cores 里面进行计算。GPU 互相之间一般是通过 PCIe 桥直接传输数据,或者是通过 NVLink 这种专用的超高速数据传输通道来传输数据。
+## NCHWX
-![GPU 内存架构示意图](images/06Memory02.png)
+在推理引擎中,或者底层Kernel层实际上为了更加适配到DSA或者ASIC专用芯片会使用NCHWX内存排布格式,那么下面我们来详细了解一下NCHWX数据排布格式。
-### 内存对齐方式
+由于典型的卷积神经网络随着层数的增加,其特征图在下采样后的长和宽逐渐减小,但是通道数随着卷积的过滤器的个数不断增大是越来越大的,经常会出现通道数为128,256等很深的特征图。这些很深的特征图与过滤器数很多的卷积层进行运算的运算量很大。为了充分利用有限的矩阵计算单元,进行了通道维度的拆分是很有必要的。根据不同数据结构特点,常见的有分别对Channel维进行了Channel/4,Channel/32和Channel/64的拆分,下图为NCHWX的物理存储结构。
-如下图所示,右侧代表着数据,左侧代表着内存的多个地址,数据存放在内存的某个地址中。内存对齐指的是数据元素按照一定的规则在空间上排列,而不是顺序的一个接一个的排放。数据在内存中存储时相对于起始地址的偏移量是数据大小的整数倍,称为自然对齐,相对应的通过编译器或语言的指令强制变量按照特定的对齐方式存储,称为强制对齐。
+![NCHWX示意图](images/06Memory03.png)
-![内存中数据示意图](images/04LayoutPrinc01.png)
+具体来说,先取Channel方向的数据,按照NCHW4来进行举例,先取17/13/X,再取W方向的数据,再取H方向的数据。
-内存对齐的原因:从硬件的层面来看,虽然数据在内存中是按照字节进行存储,但是处理器从内存中读取数据是通过总线通讯,总线默认传输的是字,即处理器按照字节块的方式读取内存,举个例子,比如 32 位系统从内存中以 4 字节为粒度进行读取,64 位系统从内存中以 8 字节为粒度进行读取,所以当在处理器上进行未对齐的地址访问时,处理器将读取多个字,还有些处理器平台不支持访问任意地址上的任意数据。
-
-![无内存对齐机制示意图](images/04LayoutPrinc02.png)
-
-详细的举例子展开来讲,以 4 字节存取粒度的处理器为例,如上图所示,我们现在要读取一个 int 变量,其有 4 个字节,假如没有内存对齐机制,将一个 int 放在地址为 1 的位置,那么我们需要读取的有地址 1234,具体操作时首先需要从地址 0 开始读取,然后取其较高的三位 123,剔除首字节 0,第二次从地址 4 开始读取,然后只取其较低的一位 4,之后将两个数据合并,总体上来说,如果有内存对齐,如下图所示,我们只需读取一次,而没有内存对齐机制,将导致访问请求数据所需的内存事务数增加至 2 倍。
-
-![内存对齐机制示意图](images/04LayoutPrinc03.png)
-
-总结一下,现代处理器上的内存子系统仅限于以其字大小的粒度和对齐方式访问内存。下面我们来总结一下内存中字粒度访问和内存对齐的原因。
-
-原因一为速度问题,现代处理器具有多个级别的高速缓存,数据必须通过这些缓存;支持单字节读取将使内存子系统的吞吐量与执行单元的吞吐量紧密地绑定,会消耗大量 CPU 资源,成为瓶颈。CPU 总是以其字的大小进行内存读取,进行未对齐的内存访问时,处理器将读取多个字,需要读取变量所跨越内存的所有字,同时进行处理。将导致访问请求数据所需要的内存事务增加 2 倍。
-
-原因二为原子性,CPU 可以在一个对齐的内存字上操作,意味着没有指令可以中断该操作。这对于许多无锁数据结构和其他并发范式的正确性至关重要。除此之外,内存对齐还可以用于优化缓存和 SIMD 指令,内存对齐有助于利用缓存行的特性。
-
-缓存通常以固定大小的缓存行存储数据,如果数据按照缓存行对齐,可以最大程度地减少对内存的访问次数,提高缓存的命中率。对齐的内存访问对于使用 SIMD 指令集的操作更为重要。这些指令集通常要求数据在内存中按照一定的对齐方式排列,以便能够一次性处理多个数据。
-
-## Tensor 内存布局
-
-Tensor 是神经网络中的一个基本数据结构,可以看作是一个多维数组,其在内存中排布为按字节存储。他的重要属性有形状和基本数据类型,形状能够决定张量的维度,以及各个维度的数量组成方式。基本数据类型决定了其每个元素占用内存的字节数,以及存在的方式。其在内存中索引占据的范围由其形状决定。
-
-零维张量只有一个数,一维张量有多个数,二维张量是一个矩阵,也是用来表达一个黑白图片常用的,三维张量常用于表达彩色图片,四维张量常用于表达多张彩色图片,五维六维等一般是因为硬件方便处理等原因对维度再次进行了分割。
-
-在深度学习领域中,多维数据通过多维数组存储,比如卷积神经网络的特征图通常用四维数组保存:四个维度分别为“N”batch 批量大小,一般指图像数量,“C”channels 特征图通道数,“H”height 特征图的高度,和“W”width 特征图的宽度。比如自然语言领域,数据通常用三维数组保存,三个维度分别为“N”batch 批量大小,“S”sequece 句子数量,“W”word 单词数量。
+由于典型的卷积神经网络随着层数的增加,其特征图在下采样后的长和宽逐渐减小,但是通道数随着卷积的过滤器的个数不断增大是越来越大的,经常会出现通道数为 128,256 等很深的特征图。这些很深的特征图与过滤器数很多的卷积层进行运算的运算量很大。
-在计算机内存里存储的时候,是线性的存储,根据排列顺序的区别,行为主序的称为行优先存储,列为主序的称为列优先存储。
+为了充分利用有限的矩阵计算单元,进行了通道维度的拆分是很有必要的。根据不同数据结构特点,常见的有分别对 Channel 维进行了 Channel/4,Channel/32 和 Channel/64 的拆分,下图为 NCHWX 的物理存储结构。具体来说,先取 Channel 方向的数据,按照 NCHW4 来进行举例,先取 17/13/X,再取 W 方向的数据,再取 H 方向的数据。
-行优先存储和列优先存储并没有绝对的好坏关系,相对比较通用的结论是:对于行优先遍历的,使用行优先存储,对于列优先遍历的,使用列优先存储。相邻操作访存地址应该尽可能接近。
+## MNN
-通常根据这个原则去排布数据能够得到较优的访存。这是由缓存的结构决定的。这个原则被称为访存的空间局部性,也即相近的代码(指令)最好访问相邻的数据,这样硬件能够提供更好的性能。
+MNN 是一个轻量级的深度学习端侧推理引擎,核心解决深度神经网络模型在端侧推理运行问题,涵盖深度神经网络模型的优化、转换和推理。
-### NCHW 格式
+其对WinoGrad卷积计算进行内核优化,重新排布了其数据格式,下面我们来进行详细介绍。
-如下图所示,这个例子中的图片分为红绿蓝三个通道,假设我们使用的是"NCHW"的数据排布方式,这里我们先将各方向的定义在这个图中详细说明,1 2 3 这个方向为 W,1 4 这个方向为 H,1 7 13 这个方向为 C,N 方向只有一个图片,暂时不讨论,"NCHW"的数据排布方式,是先取 W 方向的数据,即 123,再取 H 方向的数据,即 123 456,再取 C 方向的数据,即 123456 789/10/11/12 13/14/15/16/17/18,在计算机中存储时即为图示下侧的序列。
+### WinoGrad卷积计算
-简单地来说,也就是先在一个通道中,按照 W 方向/H 方向存储数据,接着再到剩余通道中按同样方式存储数据,其突出特点是同一个通道的数值连续排布,更适合需要对每个通道单独运算的操作,如 MaxPooling 最大池化操作,"NCHW"的计算时需要的存储更多,一次存储对应一个通道的数据,适合 GPU 运算,正好利用了 GPU 内存带宽较大并且并行性强的特点,其访存与计算的控制逻辑相对简单。
+首先我们先给出针对WinoGrad二维卷积计算的公式:
-![NCHW 示意图](images/04LayoutPrinc08.png)
+$$
+\begin{align}
+Y = A^T[[GWG^T]\odot[B^XB]]A
+\end{align}
+$$
-如下图所示,按照"NCHW"的数据排布方式,我们的目标是计算灰度值,那么我们需要先将通道一的数据加载进内存,乘以 0.299,然后每次计算都可能需要加载一整个完整通道的数据,通道二所有数据值乘以 0.587,通道三所有数据值乘以 0.114,最后将三个通道结果相加得到灰度值,三个操作是独立的,可以在 GPU 上并行完成。
+其中,$W$ 为 $r \times r$ 的卷积核,$X$ 为 $(m + r -1) \times (m + r -1)$ 的图像块。
-![NCHW 计算灰度值示意图](images/04LayoutPrinc09.png)
+可以看出Hadamard 积是 Winograd 卷积中必不可少的步骤(见上公式)。但它存在内存访问耗时较长的问题,拖累了整个计算过程。
-### NHWC 格式
+事实上,对Hadamard 积的求和可以转换为点积。
-![NHWC 示意图](images/04LayoutPrinc10.png)
+将多个点积组合在一起可以得到矩阵乘法,这是并行性和分摊内存访问开销的不错的方式。
-同样的图片,假设我们使用的是"NHWC"的数据排布方式,按照上文定义的方向,我们先取 C 方向的数据,即 17/13,再取 W 方向的数据,即 17/13 28/14 39/15,再取 H 方向的数据,即 17/13 28/14 39/15 4/10/16 5/11/17 6/12/18,在计算机中存储时即为上所图示下侧的序列。
+通过这种方式,我们在数据布局重新排序的基础上将 Hadamard 积转换为矩阵乘法。
-简单地来说,先把不同通道中同一位置的元素存储,再按照 W 方向/H 方向按照同样方式存储数据,其突出特点为不同通道中的同一位置元素顺序存储,因此更适合那些需要对不同通道的同一数据做某种运算的操作,比如“Conv1x1”1x1 卷积操作。"NHWC"更适合多核 CPU 运算,CPU 的内存带宽相对较小,每个像素计算的时延较低,临时空间也很小,有时计算机采取异步的方式边读边算来减小访存时间,计算控制灵活且复杂。
+MNN在WinoGrad卷积计算优化中使用的数据排布格式为NC4HW4。它将 4个数据元素拆分为一个单元,为张量创建一个新维度。4个元素连续放置在内存中,以便利用 CPU 中的矢量寄存器在单个指令(即 SIMD)中计算这4个数据。
-![NHWC 示意图](images/04LayoutPrinc11.png)
+MNN中数据重新排布后,对WinoGrad卷积的计算如下图所示:
-如下图所示,按照"NHWC"的数据排布方式,我们的目标是计算灰度值,假设我们现在有 3 个 cpu 的核,那么就可以通过 3 个核分别并行处理这三个通道的同一位置元素,最后进行累加得到灰度值。
+![MNN中WinoGrad卷积计算示意图](images/06Memory04.png)
-### NCHWX 格式
+我们看数据格式重新排布后的重要计算公式:
-由于典型的卷积神经网络随着层数的增加,其特征图在下采样后的长和宽逐渐减小,但是通道数随着卷积的过滤器的个数不断增大是越来越大的,经常会出现通道数为 128,256 等很深的特征图。这些很深的特征图与过滤器数很多的卷积层进行运算的运算量很大。
+$$
+\begin{align}
+Y’_{ij}[z] = \sum_kX’_{ij}[k]\ast W’_{ij}[k][z]
+\end{align}
+$$
-为了充分利用有限的矩阵计算单元,进行了通道维度的拆分是很有必要的。根据不同数据结构特点,常见的有分别对 Channel 维进行了 Channel/4,Channel/32 和 Channel/64 的拆分,下图为 NCHWX 的物理存储结构。具体来说,先取 Channel 方向的数据,按照 NCHW4 来进行举例,先取 17/13/X,再取 W 方向的数据,再取 H 方向的数据。
+令参与计算的X’矩阵与W’矩阵以及中间矩阵Y’的前两个维度都为4。
-![NCHWX 示意图](images/06Memory03.png)
+CPU 中的矢量寄存器在单个指令中能够一次计算4组在内存中连续存储的数据,一个指令就可以计算4次matrix mul,充分利用了SIMD的并行计算能力。
-NCHWX 的格式能够更好的适配 SIMT,其中 Cuda 的 DP4A 模块计算时执行两个 4 元素向量 A(int8)和 B(int8)(每个向量包含存储在 32 位字中的 4 个单字节值)之间的向量点积,将结果存储为 32 位整数,这个过程与 NCHW4 十分适配,一次正好取出 4 个元素进行计算。
+总结一下,MNN对数据格式进行 NC4HW4 重排后,可以充分利用 ARM CPU 指令集的特性,实现对卷积等操作进行加速;同时可以较少 cache miss,提高内存命中率。
-为了最大化 CUDA 的 Tensor core 计算单元的卷积算子的吞吐,NCHW32 和 NCHW64 分别针对 int8 和 int4 数据类型进行计算,对 Cache 更友好,减少 Cache 未命中的概率;Kernel 实现层面易进行 Padding,减少边界分支判断,代码逻辑简单。
+当然,对于较大的 feature 特征图,如果其 channel 不是 4 的倍数,则会导致补充 0 过多,导致内存占用过高,同时也相应的增加计算量。
-## 小结与思考
+## 小结
在本节中我们介绍了
1.CPU 和 GPU 内存中都有重要的多级缓存架构,来保证 CPU/GPU 核要访问内存时,不用每次都等内存操作完成,才可以继续后续的操作,可以从缓存中读取。
-2.张量在内存中的数据布局排布方式相当多,常见的有行优先存储和列优先存储,我们应该根据硬件特点来选择其数据排布方式能够优化性能。
+2.NCHWX 的格式能够更好的适配SIMT,为了充分利用有限的矩阵计算单元,进行了通道维度的拆分,还对Cache更友好,减少Cache未命中的概率;Kernel实现层面易进行Padding,减少边界分支判断,代码逻辑简单。
-3.卷积神经网络的特征图通常用四维数组保存,有两种常见的数据排布方式,"NHWC"更适合多核 CPU 运算,"NCHW"更适合在 GPU 上并行完成。
+3.MNN中针对WinoGrad卷积计算进行内核优化,重新排布了其数据格式为NC4HW4,CPU 中的矢量寄存器在单个指令中能够一次计算4组在内存中连续存储的数据,充分利用了SIMD的并行计算能力。
-3.NCHWX 的格式能够更好的适配 SIMT,为了充分利用有限的矩阵计算单元,进行了通道维度的拆分,还对 Cache 更友好,减少 Cache 未命中的概率;Kernel 实现层面易进行 Padding,减少边界分支判断,代码逻辑简单。
+## 本节视频
+
+
+
diff --git a/04Inference/06Kernel/images/06Memory04.png b/04Inference/06Kernel/images/06Memory04.png
new file mode 100644
index 00000000..bfed0ad3
Binary files /dev/null and b/04Inference/06Kernel/images/06Memory04.png differ