高效模型设计指导

引言

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

注意

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

通用建议

使用BPU算子搭建模型

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

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

使用BPU高效Backbone

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

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

模型输入大小S100帧率(FPS)浮点精度量化精度数据集
Resnet181x3x224x224244771.6971.64ImageNet
1x3x704x1280275//ImageNet
Resnet501x3x224x224110177.0376.78ImageNet
1x3x704x1280118//ImageNet
Efficientnet-b01x3x224x224427074.3173.85ImageNet
1x3x704x1280501//ImageNet
Mobilenetv21x3x224x224465272.1771.47ImageNet
1x3x704x1280732//ImageNet
Mixvargenet1x3x224x224494770.7570.63ImageNet
1x3x704x1280436//ImageNet
Vargnetv21x3x224x224382273.4273.17ImageNet
1x3x704x1280667//ImageNet
HENet_TinyE1x3x224x224288677.6776.92ImageNet
1x3x704x1280518//ImageNet
HENet_TinyM1x3x224x224263878.3877.62ImageNet
1x3x704x1280412//ImageNet
小技巧

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

对可融合算子做融合

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

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

模型S100性能(FPS)
未fusefuse
fcos_efficientnetb0_mscoco852.26FPS1206.89FPS

遵循硬件对齐规则

在S100计算平台运算时有最小的对齐单位,若不满足规则时,会对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算力较大,所以在大模型(720P及以上)上的性能表现比较好。对于小模型(分辨率 <= 256),则建议使用batch模式进行推理,可减少weight加载次数,从而能更有效地平衡计算/访存比。

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