前言
在上一篇帖子【【QAT查表算子调优-1】如何定位引起误差的查表算子】当中,我们针对定位引起误差的查表算子展开了细致且全面的讨论,详细地阐述了其中所涉及的思路以及具体的方法。在实际的工作场景里,准确且高效地定位到引发误差的查表算子,能够为后续的调优工作奠定坚实的基础。当我们通过特定的流程和手段,成功地锁定了具体的查表算子之后,接下来需要面对的关键问题便是:应该怎样对这些查表算子进行调优呢?
这篇文章将选取一些在实际应用中较为常见的查表算子softmax、cos/sin作为具体的案例,逐步剖析并说明针对这些算子进行优化的具体思路以及切实可行的方法。我们会结合实际的操作流程与技巧,为大家说明一套系统且具有可操作性的调优方案。
查表算子调优
目前,J6工具链已经针对定点查表算子的精度问题进行了专门的优化。不过,在实际的使用场景中,尽管已经做了优化,但仍不能完全排除存在一些特殊情况(即corner case),在这些特殊情况下定点查表算子可能依然无法达到理想的精度表现。
鉴于此,为了让用户能够获得更好的使用体验以及更精准的计算结果,我们给出以下建议:
首先,强烈建议用户对horizon_plugin_pytorch进行升级操作。在最新版本的horizon_plugin_pytorch中,集成了最新的优化策略,这些策略经过了精心的设计和测试,能够进一步提升定点查表算子的精度,帮助用户在使用过程中减少可能出现的误差。
其次,在完成升级之后,如果依然存在比较严重的定点查表误差问题,那么用户需要针对可能出现的特殊情况进行细致的调优。
接下来,笔者将围绕那些可能会出现误差的查表算子展开详细说明。这些算子主要包括softmax、cos/sin。在后续内容中,会着重介绍针对这些算子常见的调优手段,帮助用户更好地应对可能出现的精度问题。
Softmax
Softmax 是深度学习中常用的激活函数,通常用于分类任务的输出层。其作用是将一个实数向量转换为一个概率分布,使得:
每个输出值在 (0, 1) 之间;
所有输出值的和为 1。
公式如下:

softmax常见查表方式为:
- 预先量化输入范围:将输入 减去最大值(提升数值稳定性)后,限定在某个固定范围内;
- 构建 exp 函数查找表:把这个范围离散成 N个点,计算这些点的 e^x 值,保存在查找表中。
- 通过查表 + 插值估算:推理时将输入值映射到最近的查表索引并查找。
表的点数越少,间隔越大,近似误差越大;
即使插值(如线性插值)也不能完美还原原函数。
了解了查表误差等大概原因后,那么我们就提供具体的调优手段。
配置auto_divide_strategy="mix"(首推)
单算子配置方式:
prepare之前,对softmax算子配置reciprocal_kwargs,如下所示:
全局配置方式:
修改 softmax的 dividing_points
在上面我们讲到了查表范围的划分对误差影响比较大,这里提供了手动对softmax算子配置dividing_points的方法。
prepare之前,配置softmax的dividing_points,如下所示:
修改完成后可以在prepare以后打印确定是否已经修改成功,如下所示:
那么,dividing_points如何确定呢?dividing_points的确定严格依赖于实验结果,这里讲述一下具体的过程:
构建reciprocal单算子测试样例,其输入为 精度debug工具保存下来的op_info;
绘制在修改dividing_points前后,查表转定点后输出的误差分布图,可以包括绝对误差、相对误差;
根据误差在每个输入范围的情况来划分dividing_points,比如[-50,50]范围内的绝对误差比较大,那么就可以进一步精细划分这部分。
修改 input_range
修改 input_rang的场景包括工具统计的不准确或者是存在badcase,这里先提供修改的方式,然后再讲一下如何确定input_range。
prepare之前,配置softmax的input_range,如下所示:
debug工具如何运行可以参考上一篇帖子。
cos/sin
cos/sin算子与softmax算子有所不同,它是具有周期性和对称性的,所以如果没有正确处理,可能会引起较大的误差。
若未处理角度周期性,如输入角度 > 2*pi,需要进行模运算,若实现不当,模运算精度误差也可能导致查错位置。
有些实现只查 [0, pi/2]并利用对称性计算其他象限,如果符号处理或镜像不准确,也会引入误差。
针对这种情况,工具链支持对cos/sin配置single_period=True,不过,这里有两点要特别注意,也可以说这种配置方式的不足:
- 需要将模型中的cos/sin替换为horizon_plugin_pytorch的实现,示例代码如下所示:
模型需要重新做calib/qat,时间和经济代价会比较高;


