Rspress

# #高效模型设计指导

## #引言

面对高度复杂的智驾场景对性能的严苛要求，我们推出了旨在提供模型量化部署的高效开发平台S100/S100p/S600，作为一款ASIC，BPU包含多种专用硬件计算单元，各硬件单元在设计时为了更高的性能可能牺牲了部分灵活性，因此需要您在了解BPU的特性后，针对性地对模型做出一些更贴合硬件特点的优化，以尽可能发挥出BPU的计算优势。 下文将具体阐述在S100/S100p/S600计算平台上设计高效模型的建议。

注意

下方给出的优化思路，仅做指导建议，请根据实际情况多做尝试。

## #通用建议

### #使用BPU算子搭建模型

BPU算子本身性能远高于CPU算子，且CPU和BPU之间的异构调度还会引入量化、反量化节点，该节点的计算因为需要遍历数据，所以耗时与shape大小成正比。

- 对于量化、反量化算子：建议手动摘除，并将相关计算合入前、后处理代码中，可节省一次数据遍历的冗余耗时。同时在模型后处理中还可考虑先完成筛选过滤的操作，仅对剩下的数据做反量化，可进一步压缩耗时。
- 对于模型中的CPU算子：可以根据算子约束列表来查看支持的公版算子，将CPU算子做替换或使用支持的算子拼出等效算子，保障模型尽可能在BPU全一段运行。

### #使用BPU高效Backbone

基于S100/S100p/S600的硬件特性，我们提供了高效模型HENet(Hybrid Efficient Network)。基于性能和精度考虑，我们提供了TinyE、TinyM两个量级的网络。在ImageNet数据集上，HENet高效模型的精度不仅可以达到不小于Resnet50的模型精度，性能还有成倍的提升。

以下是包含HENet在内的多个模型在分类任务上的性能表现：

注解

数据来源为OE包 `v3.0.22`，模型来源于`OE/samples/ai_toolchain/horizon_model_train_sample`，不同版本间可能存在些微差异，数据仅供参考。

模型 | 输入大小 | S100帧率（FPS） | 浮点精度 | 量化精度 | 数据集
--- | --- | --- | --- | --- | ---
Resnet18 | 1x3x224x224 | 2447 | 71.69 | 71.64 | ImageNet
1x3x704x1280 | 275 | / | / | ImageNet
Resnet50 | 1x3x224x224 | 1101 | 77.03 | 76.78 | ImageNet
1x3x704x1280 | 118 | / | / | ImageNet
Efficientnet-b0 | 1x3x224x224 | 4270 | 74.31 | 73.85 | ImageNet
1x3x704x1280 | 501 | / | / | ImageNet
Mobilenetv2 | 1x3x224x224 | 4652 | 72.17 | 71.47 | ImageNet
1x3x704x1280 | 732 | / | / | ImageNet
Mixvargenet | 1x3x224x224 | 4947 | 70.75 | 70.63 | ImageNet
1x3x704x1280 | 436 | / | / | ImageNet
Vargnetv2 | 1x3x224x224 | 3822 | 73.42 | 73.17 | ImageNet
1x3x704x1280 | 667 | / | / | ImageNet
HENet_TinyE | 1x3x224x224 | 2886 | 77.67 | 76.92 | ImageNet
1x3x704x1280 | 518 | / | / | ImageNet
HENet_TinyM | 1x3x224x224 | 2638 | 78.38 | 77.62 | ImageNet
1x3x704x1280 | 412 | / | / | ImageNet

小技巧

针对输入输出分辨率相近的场景，或者作为主backbone使用的场景，我们推荐直接使用TinyM/TinyE原生结构。 针对其他场景，我们建议您参考TinyM的基础block结构，灵活构建模型。

### #对可融合算子做融合

在量化阶段，针对当前模型结构的不同层会进行算子融合（fuse）。BPU硬件对常见模型的基本结构进行了优化，在计算 `Conv -> Add -> ReLU` 这样的算子组合时，会将其视为一个整体，并合并为一个`Module`（支持融合的算子组合详见量化感知训练（QAT）— 深入探索 — 算子融合 章节）。 算子融合不仅可以保留中间结果的高精度状态，还可以省去将中间结果转换为低精度表示的过程。通常，应对所有可融合的部分进行融合。

我们推荐使用jit模式，jit模式下会自动做算子融合（需注意共享算子对算子融合的影响），若出于量化精度考虑，在做拆除时注意单独算子的支持情况和模型性能表现。在保证量化精度的前提下尽可能融合，大量未融合的算子会对性能造成一点影响。

模型 | S100性能（FPS）
--- | ---
未fuse | fuse
fcos_efficientnetb0_mscoco | 852.26FPS | 1206.89FPS

### #遵循硬件对齐规则

在S100/S100p/S600计算平台运算时有最小的对齐单位，若不满足规则时，会对Tensor自动进行padding，造成无效的算力浪费。不同的算子对齐规则有所差异，以下为适用于通用情况下的对齐建议：

- 一般tensor，各维度shape对齐到2的幂次方。
- conv like使用的tensor，H对齐到8，W对齐到16，C对齐到32。

在模型设计时，我们应尽量将大数据放在对齐单位较大的维度上，同时避免出现C维度过大而H和W维度过小的情况，因为这会导致H和W的padding，从而使数据量成倍增长。

### #提高模型的计算/访存比

算子运行时间包括访存时间和计算时间，若要提高计算/访存比，则需要减少访存时间，最常见的导致访存时间增大的操作通常为数据搬运操作。以下是一些降低数据搬运消耗，提高模型计算/访存比的优化建议：

1. 使用GroupConv缓解带宽压力，当模型channel比较小时，我们可以利用普通的稠密卷积去发挥BPU的强大算力。而随着模型加深，channel会逐渐变大，当通道数较大时，建议使用GroupConv来缓解带宽压力。

2. Block间采用更小的featuremap，这样可以减少DDR与SRAM之间的数据搬运。

3. 避免weight参数量较大，过大的kernel_size和过高的channel维度会增加weight的参数量，导致数据搬运更加频繁。对于高channel维度可以使用组卷积来增加收益。

4. Shortcut不宜过长，过长的shortcut会导致featuremap在SRAM里驻存的时间过长，甚至会导致数据dump到DDR上。

5. 小图多Batch，由于S100/S100p/S600算力较大，所以在大模型（720P及以上）上的性能表现比较好。对于小模型（分辨率 <= 256），则建议使用batch模式进行推理，可减少weight加载次数，从而能更有效地平衡计算/访存比。

6. 减少数据transform操作，BPU是张量运算处理器，数据排布是多维表示，而Reshape，Transpose的表达语义是基于CPU/GPU的线性排布。因此，在BPU上进行数据transform操作会引入一定的耗时的。在进行reshape时，应尽量减少改动的维度，改动的维度越多，计算效率越低。

页面目录