OE Agent“天工”新版本发布,请前往论坛顶部查看,欢迎试用并反馈~
查看OE-Skills
专栏算法工具链【地平线J6工具链进阶教程】模型优化方案集锦

【地平线J6工具链进阶教程】模型优化方案集锦

芯链情报局2026-07-02
29
0

本文基于地平线征程6芯片的特性以及部署经验积累,将在各场景的模型设计上给出高效模型结构建议,以达到加速用户的模型部署效率和落地效果的目的。

高效backbone

为了 提供针对 J6 系列芯片专门设计的高效 backbone,结合 J6 芯片的硬件特性,设计了高效模型 HENet (Hybrid Efficient Network)。

模型介绍参考社区文章:https://developer.horizon.auto/blog/10144

代码位于:/usr/local/lib/python3.10/dist-packages/hat/models/backbones/henet.py

模型

输入大小

J6E 帧率(FPS)

J6M 帧率(FPS)

浮点精度

量化精度

数据集

resnet18

1x3x224x224

2456

3146

72.04

71.64

ImageNet

1x3x704x1280

306

391

/

/

ImageNet

resnet50

1x3x224x224

1092

1490

77.38

76.78

ImageNet

1x3x704x1280

124

168

/

/

ImageNet

efficientnet-b0

1x3x224x224

3379

4004

74.31

73.85

ImageNet

1x3x704x1280

472

620

/

/

ImageNet

mobilenetv2

1x3x224x224

4172

5988

72.63

71.47

ImageNet

1x3x704x1280

732

942

/

/

ImageNet

mixvargenet

1x3x224x224

3928

4114

71.32

70.63

ImageNet

1x3x704x1280

485

653

/

/

ImageNet

vargnetv2

1x3x224x224

2661

3307

73.93

73.17

ImageNet

1x3x704x1280

631

860

/

/

ImageNet

HENet_TinyE

1x3x224x224

2637

3268

77.67

76.92

ImageNet

1x3x704x1280

534

737

/

/

ImageNet

HENet_TinyM

1x3x224x224

2467

3114

78.38

77.62

ImageNet

1x3x704x1280

444

605

/

/

ImageNet

Transformer Attention

MSDA

地平线attention算子在保持算子逻辑等价的同时在效率上进行了优化。主要优化点有:

  • 将部分耗时较长的element-wise 类型的算子改为Linear实现(reduce_sum)

  • 去除gridsample后的reshape操作,减少translayout

  • 数值融合,量化阶段提前融合部分数值操作,将norm操作融合到sampling_offsets中,可以减少量化误差,同时提高部署效率

数值融合部分,需要先将模型转换为部署模型,准备数值融合,代码如下:

详细代码见:/usr/local/lib/python3.10/dist-packages/hat/models/task_modules/bevformer/attention.py

LSS/Bevpool 部署攻略

LSS v1

LSS为BEV转换的方式,LSS转换最重要的操作为bevpool操作,bevpool中的index操作对J6芯片硬件并不友好,因此给出替换方式,使其可以部署。

BPU不支持按index的赋值操作,因此公版的bevpool无法原生支持,参考算法版本分别对深度和feature多次grid_sample采样后相乘来替代公版实现。

完整代码见:hat/models/task_modules/view_fusion/view_transformer.py

LSS v2

bev_lss_v2版本(目前还未正式上线)相较于v1版本在采样点的选取(_gen_reference_point)上做了优化。基于v1版本的部署经验上,由于是均匀采点,可能存在近处目标多使存在漏检情况,v2版本设计了距离排序+topk的采样点选取策略,在采样点的数量不变、bev转换方式不变的情况下,增加模型对近处目标的采样,从而提升近处目标的检测精度。用户可以根据不同方案需求对采样点选取做设计,以上方案可以通过use_vtv2参数控制,以下为近处优先的采样点选取方案。
bev_lss_v2版本相比v1在采样点的选取策略上,通过use_vtv2参数控制。

v1版本是排序后取前10个点,会导致在周围的目标容易丢失

v2版本采用距离排序+topk

具体为:

Densebev性能优化方案

bevmask操作可以减少无效anchor,提高模型部署效率,动态的bevmask 在J6上无法支持,在优化方案中,我们对内外参生成BevMask的原理做了详细的分析,发现:

  1. 当相机传感器位置固定时,内外参转换矩阵即固定,轻微抖动对BevMask影响不大。

  2. 从BEV voxel 的角度来看,中心点到multi camera的映射是稀疏的,在BevFormer开源的代码和模型中,默认利用了这个特性,加速计算而不会带来任何精度损失(也就是上面说的bev_mask)

  3. 从BEV pillar 的角度来看,通常每个pillar只会映射到1-2个camera。

利用到上面的几个特性我们可以减少空间融合模块的复杂度,但需要引入一对gather/scatter操作,以及相关的index计算(有效点的index只和相机有关,为前处理计算,内外参不变的情况下只需要计算一次)。即先通过gather将bev空间上的有效点取出来,计算完空间特征融合后,再用scatter将其还原到Bev空间对应的位置,然后根据每个bevpillar的有效点数来算Bev空间每个点的均值即可。

整体框架如下图所示:

为了能编译成静态模型,有2个额外需要关注的设置:

  1. Bev空间映射到每个camera的最大点数。这个可以根据内外参计算得到,但为了应对一些抖动情况,可以适当放开,在Nuscenes数据集上,50*50大小的Bevsize下,我们设置为20*32。 这个数字直观理解就是,最大视场的相机在Bev空间覆盖的区域大小。

  2. 每个BEV pillar映射到的最大的camera数。目前是一个静态设置的最大值,可以根据数据统计得到,在Nuscenes数据集中,我们设定为2, 这个数字直观理解就是有视野重叠的最大camera数。

代码均在算法包位置:

hat/models/task_modules/bevformer/attention.py

BEV坐标转换量化攻略

坐标转换是将3d的点映射到2d 图像上,输入为3d坐标和转换矩阵,输出为2d点坐标,主要的做法为3d坐标和转换矩阵的点积,然后转为2D平面坐标。

易产生量化误差的操作为:

  1. 3d点和homo矩阵的matmul操作,精度不够会对结果产生直接影响

  2. 将(x,y)/z,若z非常小则会导致x,y坐标数值很大,对量化不利

对于1:

对matmul拆分,使保证高精度(或在新模版中使用双int16)

对于2:

对z做clamp,由于该坐标是用于gridsample采点,若为无效点(坐标大于featuremap)则可以在前面做clamp去除,避免无效值对量化的影响。可以参考:

将缩放操作提前,即将坐标点在前部分就缩小,操作将div放在homo计算中,将缩放直接放在矩阵中,无需在模型中做。(经验上越大的scale,转定点后掉点的风险越大,去除无效数值避免较大的scale),参考:

Sparse bev部署攻略

性能优化

  • 一阶段生成的featuremap只使用FPN的单层特征。

  • 根据场景适当减少anchor num、decoder layer、num_head,对浮点精度影响较小的配置。

  • 对模型中的update模块的topk运算若对性能影响较大则考虑去除,对浮点的影响视具体模型而定,若影响较大可以尝试使用memory bank找回。目前已支持spu的topk实现。

  • 使用henet替换Resnet50。

精度优化

  • 计算2d点时(depth = self.reciprocal_op(torch.clamp(points_2d[..., 2:3], min=1e-5))),可以根据实际情况限制最小值避免出现极大的x,y坐标(实际极大的坐标为无效值),对QAT量化不友好。
  • 对homo做缩放,避免在坐标转换时出现matmul数值过大出现量化问题。

  • anchor_project计算时为避免很大的timestamp差异(对量化不友好),可使用以下方式:
    • 若BPU执行则可以增加过滤

    • 若BPU执行则量化配置时可以通过对算子配置threshold(数值为有效值范围的最大值)来实现对离群点的过滤。

    • CPU执行,对anchor_project过程不做量化(板端CPU计算后作为模型输入)

      gen_cached_data为时序的anchor_projection计算,计算完后再做QuantStub量化。

  • project_mat的matmul计算若有精度可以做拆分或者使用双int16量化。

  • 若坐标处理中有放大值域的计算,善于使用clamp,例如将红色部分换成上面注释的部分,将clamp的min增大,对x,y可以避免出现极值,更有利于量化。

对于具有物理意义相关的数据可以自己限制范围,控制值域,更有利于量化。

对于该示例,生成的grid坐标会在图像的featuremap中取值,存在能取到值的有效点和取不到值(超过图像表示范围:±tan(fov/2))的无效点。因此,若x,y的值很大的话是取不到有效值的,所以对超出范围的无效点做处理不会影响浮点模型精度且对量化更友好。由计算可知x和y的最终坐标需要/z映射到2D图像,若z非常小会导致x,y很大,因此可以在z上做clamp使x,y的分布更均匀且不会影响物理范围。

对sparse4d部署更详细的见文章:https://developer.horizon.auto/blog/12622

算法工具链
技术深度解析征程6
评论0
0/600