面对高度复杂的智能场景对性能的严苛要求,我们推出了旨在提供模型量化部署的高效开发平台S100,作为一款ASIC,BPU包含多种专用硬件计算单元,各硬件单元在设计时为了更高的性能可能牺牲了部分灵活性,因此需要您在了解BPU的特性后,针对性地对模型做出一些更贴合硬件特点的优化,以尽可能发挥出BPU的计算优势。 下文将具体阐述在S100计算平台上设计高效模型的建议。
下方给出的优化思路,仅做指导建议,请根据实际情况多做尝试。
BPU算子本身性能远高于CPU算子,且CPU和BPU之间的异构调度还会引入量化、反量化节点,该节点的计算因为需要遍历数据,所以耗时与shape大小成正比。
基于S100的硬件特性,我们提供了高效模型HENet(Hybrid Efficient Network)。基于性能和精度考虑,我们提供了TinyE、TinyM两个量级的网络。在ImageNet数据集上,HENet高效模型的精度不仅可以达到不小于Resnet50的模型精度,性能还有成倍的提升。
以下是包含HENet在内的多个模型在分类任务上的性能表现:
模型 | 输入大小 | 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计算平台运算时有最小的对齐单位,若不满足规则时,会对Tensor自动进行padding,造成无效的算力浪费。不同的算子对齐规则有所差异,以下为适用于通用情况下的对齐建议:
在模型设计时,我们应尽量将大数据放在对齐单位较大的维度上,同时避免出现C维度过大而H和W维度过小的情况,因为这会导致H和W的padding,从而使数据量成倍增长。
算子运行时间包括访存时间和计算时间,若要提高计算/访存比,则需要减少访存时间,最常见的导致访存时间增大的操作通常为数据搬运操作。以下是一些降低数据搬运消耗,提高模型计算/访存比的优化建议:
使用GroupConv缓解带宽压力,当模型channel比较小时,我们可以利用普通的稠密卷积去发挥BPU的强大算力。而随着模型加深,channel会逐渐变大,当通道数较大时,建议使用GroupConv来缓解带宽压力。
Block间采用更小的featuremap,这样可以减少DDR与SRAM之间的数据搬运。
避免weight参数量较大,过大的kernel_size和过高的channel维度会增加weight的参数量,导致数据搬运更加频繁。对于高channel维度可以使用组卷积来增加收益。
Shortcut不宜过长,过长的shortcut会导致featuremap在SRAM里驻存的时间过长,甚至会导致数据dump到DDR上。
小图多Batch,由于S100算力较大,所以在大模型(720P及以上)上的性能表现比较好。对于小模型(分辨率 <= 256),则建议使用batch模式进行推理,可减少weight加载次数,从而能更有效地平衡计算/访存比。
减少数据transform操作,BPU是张量运算处理器,数据排布是多维表示,而Reshape,Transpose的表达语义是基于CPU/GPU的线性排布。因此,在BPU上进行数据transform操作会引入一定的耗时的。在进行reshape时,应尽量减少改动的维度,改动的维度越多,计算效率越低。