已关闭
AdaptiveAvgPoo2dGrad性能优化不达标 #3743
小王!创建于 7月1日关闭于 7月2日
小王!
7月1日 评论:
7月1日 评论:
/assign


7月1日 将 qq_52056150 设为负责人
yuning_chen
7月1日 评论:
7月1日 评论:
/assign @qq_52056150


CANN-robot
7月1日 评论:
7月1日 评论:
7月1日 修改标题为 “AdaptiveAvgPoo2dGrad性能优化不达标”,原标题为“AdaptiveAvgPoo2dGrad性能优化”
7月1日 修改了issue 的描述
7月2日 关闭了 issue
7月2日 添加了label:resolved
优化方案如下
一、SIMT 模板的性能优化:
1、针对 H 方向输出尺寸大于输入尺寸、W 方向输出尺寸较小且输入 W 较宽的场景,新增
SmallOutWSegFast快路径分支。该分支主要覆盖hOut > hIn且wOut为 2、3、4 的场景,并根据wIn设置不同的命中阈值。原通用路径是按每个gradX[n,c,h,w]元素逐点反查对应的gradY窗口,多个相邻输入 W 位置会重复读取和累加相同或高度相似的gradY数据。优化后改为按row + W segment组织任务,每个任务处理一个(n,c,h,segment),先计算该 segment 对应的梯度值,再批量写回连续的输入 W 区间,从而减少重复读 GM、重复计算窗口边界和重复累加的开销。2、针对 W 方向输出很小但输入 W 较宽的场景,在
SmallOutWSegFast中将输入 W 维度按照输出窗口覆盖关系拆成多个连续 segment。对于OUT_W个输出窗口,最多拆成2 * OUT_W - 1个 segment,其中普通 segment 只由一个输出 W 窗口贡献,边界 segment 由相邻两个输出 W 窗口共同贡献。每个 segment 预先记录startW、endW、kW0、kW1等信息,计算时无需每个输入 W 位置都重复计算owStart、owEnd、iw0、iw1和kW。segment 内的gradX值相同或由固定的相邻输出窗口组合得到,因此可以一次计算后批量写回[startW, endW)连续区间。3、针对 H 方向扩张场景,
SmallOutWSegFast利用 adaptive avg pool 的窗口覆盖规律对 H 方向计算进行了简化。在hOut > hIn的情况下,大多数输出 H 窗口只覆盖一个输入 H 位置,只有输入 H 的左右边界附近可能出现跨输入窗口的情况。优化路径不再对每个oh都反复计算ih0、ih1、kH,而是通过leftCross、rightCross判断首尾是否跨界:边界位置使用0.5f权重处理,中间位置直接累加。这样可以减少大量快除、窗口起止计算和标量除法开销。4、针对输入 H 为 1 的退化场景,新增
HInOne专用分支。该场景下输入高度只有一行,所有输出 H 方向的梯度都会累加到同一个输入 H 位置,因此不需要再计算 H 方向的ohStart、ohEnd、ih0、ih1和kH。该分支将计算规模从n * c * inH * inW简化为n * c * inW,只保留 W 方向的窗口反推和所有输出 H 的累加,降低了循环复杂度和重复边界计算开销。5、针对小
outW且wIn较小的场景,保留并细化了SmallOutWRow行级聚合分支。该分支以一整行(n,c,h)为任务粒度,先对每个输出 W 聚合 H 方向贡献,得到owSum[OUT_W],再遍历输入 W,根据每个输入 W 是否落在对应输出窗口覆盖范围内完成写回。对于wIn较小的 shape,这种行级聚合方式可以避免任务拆得过细导致调度开销变大,同时复用同一行上的gradY读取结果,减少多个输入 W 位置重复读取同一批输出梯度。6、针对 H 方向极端扩张且
wOut == 2、wIn较小的场景,新增HExpandW2SmallFast快路径。当hOut远大于hIn时,如果仍采用行级聚合,一个线程需要处理很长的 H 方向累加,单线程工作量过大、并行度不足。因此该分支重新按输入元素维度并行,同时针对wOut == 2的固定结构进行手写优化:直接根据输入 W 判断当前点只由ow0贡献、只由ow1贡献,还是由两个输出窗口共同贡献,避免通用路径中反复计算 W 方向窗口边界。H 方向中间部分采用循环展开累加,边界位置使用半权重处理,以降低极端 H 扩张场景下的计算开销。7、针对固定 H 扩张比例的特殊场景,新增
HExpandExactOutWSmallFast<12>分支。该分支命中hIn == 2且hOut == 24的场景,此时每个输入 H 精确对应 12 个输出 H。代码中直接使用固定的H_SCALE = 12进行展开累加,省去了通用路径中对ohStart、ohEnd、ih0、ih1、kH的动态计算。该优化属于特定 shape 的定制快路径,适合固定比例扩张场景下提升性能。8、针对 H 方向输入尺寸大于输出尺寸、W 方向输出尺寸大幅大于输入尺寸的场景,新增
HReduceWExpandFast分支。该分支覆盖hIn > hOut且wOut >= wIn * 4的情况。此类场景下,一个输入 W 位置可能被多个输出 W 窗口覆盖,通用路径会对每个ow都计算iw0、iw1和kW。优化后将 W 方向覆盖区间拆成首、中、尾三部分:首尾位置保留真实kW计算,中间大部分窗口通常只覆盖一个输入 W 位置,可以直接累加,从而减少 W 方向大量重复的窗口边界计算和除法操作。9、在通用路径和各类快路径中还做了细粒度标量优化。首先,将 N 和 C 两个维度合并为
nc进行索引计算,避免在热路径中额外拆分n和c;其次,提前计算base = nc * outHW,减少内层循环中的重复乘法;再次,将部分除法改为预先计算倒数后使用乘法,例如invKH、invKW;最后,在 segment 批量写回时,先将浮点梯度转换为VALUE_T,再写回连续 W 区间,避免同一个梯度值重复进行类型转换。这些优化不改变原有计算语义,但可以降低 SIMT 热路径中的标量计算、快除和类型转换开销。10、对于未命中特殊 shape 的场景,保留优化后的通用
Nchwfallback 路径,保证功能覆盖完整。通用路径仍然按照每个gradX元素反查对应的输出窗口并累加gradY / (kH * kW),但相比原始实现,已经合并了n/c索引、提前计算outHW和base,并在 H 方向提前计算invKH,因此即使不走特殊快路径,也能减少部分重复计算。二、small kernel 模板的性能优化:
1、针对极端 resize、小 W、大比例 H/W 扩张或压缩的场景,新增 small kernel 规避逻辑。此类 shape 更适合 SIMT 快路径处理,small kernel 不再强行命中,避免因 UB 转置、窗口反推和重复累加带来额外开销。
2、针对原 tiling 只满足 UB 和核数即可返回的问题,新增代价模型搜索。优化后会遍历
highAxisInner、hOutputInner、wOutputInner,综合评估 buffer 开销、block 数、core 利用率、highAxis padding 和尾块 VL 利用率,选择更优切分。3、针对 H/W 切分回退策略,新增严格收缩的
ShrinkInnerStrict逻辑。相比原来通过增加 outer 间接调整 inner,新逻辑直接保证 inner 逐步变小,避免切分停滞,使 UB 占用和核数并行度更容易同时满足。4、针对计算阶段 H 方向仍走标量反推的问题,新增 H 方向窗口信息向量化预计算。优化后 H/W 两个方向都批量计算
start/end/cover,并缓存到 UB 临时 buffer,减少内层循环中的整数除法、边界 clamp 和函数调用开销。5、针对 highAxis 尾块不规整和重复除法问题,新增
highAxisLocalStride_对齐本地高轴,并预计算invCoverW。计算时用invCoverH * invCoverW得到 scale,减少逐点浮点除法,同时让转置、cast 和 MicroAPI 累加访问更规整。