已关闭
[Feature]: GraphSoftMax算子优化 #227
xiangyuming创建于  5月18日关闭于  9月9日
xiangyuming
xiangyuming成员
5月18日 创建

提交提案之前,请先检索仓库内是否已有相同的提案,如已有请在同一提案中进行讨论。

💻 需求背景、当前现状、期望实现的功能内容、具体的设计方案、以及测试方案

任务描述

  1. 优化仓上GraphSoftMax算子,性能提升20%
  2. 适配产品:800T A2、800T A3

验收标准

一、任务交付件
(1) AscendC代码
(2) 测试用例UT
二、验收标准:
1)精度/性能要求
精度:符合精度标准(https://gitcode.com/Ascend/msit/blob/master/msit/docs/llm/工具-精度预检使用说明.md#33-精度标准)
性能:对比原算子提升20%
2)实践文档:
算子优化文档
3)任务完成标准
本次任务完成标准为:
精度/性能(根据实际要求)达标,PR完成合入,实践文档提交到仓库issue。

对接人

@yuansunshun

替代方案

补充说明

欢迎加入社区,感谢您对社区的贡献 🎉!

likedislike
xiangyumingxiangyuming成员
5月18日 添加了label:feature
xiangyuming
xiangyuming成员
5月18日 评论:

/label add triaged

likedislike
ascend-robotascend-robot成员
5月18日 添加了label:triaged
xiangyumingxiangyuming成员
5月18日 修改了issue 的描述
xiangyumingxiangyuming成员
5月18日 修改了issue 的描述
Ronald1995
6月11日 评论:

/label add good-first-issue

likedislike
ascend-robotascend-robot成员
6月11日 添加了label:good-first-issue
samulenzz
6月25日 评论:

认领这个任务

likedislike
Ronald1995
6月25日 评论:

认领这个任务

@samulenzz

欢迎认领任务,请参考https://gitcode.com/Ascend/DrivingSDK/issues/215 社区任务池明确该任务的:

  • 完成的截止日期
  • 开发进展反馈
  • 微信答疑群
  • 任务交付注意事项

等信息。如果您同时认领了多项任务,但无法都能进行投入,可以在部分任务中回复退出.

麻烦您加入到对应微信群,群备注名修改为"社区任务+您的gitcode账号", 后续有相关消息和问题都可以在微信群咨询答疑。 等您加入到微信群后,我这边会在社区任务池里面登记任务责任人。

likedislike
shinsekaikami
shinsekaikami
6月26日 评论:

认领 排队先来后到~

likedislike
gcw_MTeIQk9o
6月29日 评论:

认领这个任务

likedislike
samulenzz
6月29日 评论:

认领这个任务

@samulenzz

欢迎认领任务,请参考https://gitcode.com/Ascend/DrivingSDK/issues/215 社区任务池明确该任务的:

  • 完成的截止日期
  • 开发进展反馈
  • 微信答疑群
  • 任务交付注意事项

等信息。如果您同时认领了多项任务,但无法都能进行投入,可以在部分任务中回复退出.

麻烦您加入到对应微信群,群备注名修改为"社区任务+您的gitcode账号", 后续有相关消息和问题都可以在微信群咨询答疑。 等您加入到微信群后,我这边会在社区任务池里面登记任务责任人。

@Ronald1995

已添加微信群

likedislike
samulenzz
6月30日 评论:

认领这个任务

@samulenzz

欢迎认领任务,请参考https://gitcode.com/Ascend/DrivingSDK/issues/215 社区任务池明确该任务的:

  • 完成的截止日期
  • 开发进展反馈
  • 微信答疑群
  • 任务交付注意事项

等信息。如果您同时认领了多项任务,但无法都能进行投入,可以在部分任务中回复退出.

麻烦您加入到对应微信群,群备注名修改为"社区任务+您的gitcode账号", 后续有相关消息和问题都可以在微信群咨询答疑。 等您加入到微信群后,我这边会在社区任务池里面登记任务责任人。

@Ronald1995

本周进度:

  • 仓库熟悉
  • 华为云环境部署
likedislike
ascend-robotascend-robot成员
7月3日 关联了看板:MindStudio ISSUE管理
samulenzz
7月5日 评论:

认领这个任务

@samulenzz

欢迎认领任务,请参考https://gitcode.com/Ascend/DrivingSDK/issues/215 社区任务池明确该任务的:

  • 完成的截止日期
  • 开发进展反馈
  • 微信答疑群
  • 任务交付注意事项

等信息。如果您同时认领了多项任务,但无法都能进行投入,可以在部分任务中回复退出.

麻烦您加入到对应微信群,群备注名修改为"社区任务+您的gitcode账号", 后续有相关消息和问题都可以在微信群咨询答疑。 等您加入到微信群后,我这边会在社区任务池里面登记任务责任人。

@Ronald1995

本周进展baseline精度计算,以及UT测试跑通

likedislike
samulenzz
7月5日 评论:

技术方案:

三、优化策略设计

3.1 优化策略一览(按预期收益排序)

编号 优化策略 修改范围 预期收益 风险
OPT-1 Double Buffer + 流水重叠 op_kernel 10-20% 低(不改变算法)
OPT-2 动态 singleLoopTaskCount op_host + op_kernel 5-10% 低
OPT-3 Gather 批量化(消除内循环 GetValue+小 DataCopy) op_kernel 10-15% 中(需重构内循环)
OPT-4 Pass2→Pass3 数据复用(消除 GM 往返) op_kernel 5-8% 中
OPT-5 Workspace 512B 对齐 op_host 3-5% 低

综合预期:OPT-1 + OPT-2 + OPT-3 组合即可达到 20%+ 提升。

3.2 OPT-1: Double Buffer + 流水重叠(核心优化)

原理:将每个 Pass 的内循环改造为 CopyIn / Compute / CopyOut 三级流水,使用 2 个 buffer 交替执行。

当前(串行):

Iter 0: [CopyIn] → [Compute] → [CopyOut]
Iter 1:                                    [CopyIn] → [Compute] → [CopyOut]

优化后(流水):

Iter 0: [CopyIn_0] → [Compute_0] → [CopyOut_0]
Iter 1:              [CopyIn_1] → [Compute_1] → [CopyOut_1]
Iter 2:                           [CopyIn_0] → [Compute_0] → ...

实现要点:

  • 将 srcBuf_、scatterMaxBuf_、indexBuf_ 的 InitBuffer 大小翻倍(乘以 2)
  • 使用 TQue<QuePosition::VECIN, 2> 和 TQue<QuePosition::VECOUT, 2> 替代 TBuf
  • 通过 EnQue/DeQue 管理 buffer 切换
  • 将 SetFlag/WaitFlag 改为基于 TQue 的自动同步

UB 空间预算:

当前: srcBuf(2360*8*4=75520) + scatterMaxBuf(75520) + indexBuf(2360*4=9440) = 160,480 bytes
翻倍: 160,480 * 2 = 320,960 bytes → 超出 192KB!

解决:减小 singleLoopTaskCount 以腾出 Double Buffer 空间
新 singleLoopTaskCount = 192*1024*0.8 / 4 / (8*2+1) / 2 ≈ 1180 (A2)
                       = 248*1024*0.8 / 4 / (8*2+1) / 2 ≈ 1530 (A3)

虽然单次处理边数减半,但流水重叠带来的收益远超批量大小下降的损失(DMA 延迟被隐藏)。

3.3 OPT-2: 动态 singleLoopTaskCount

修改位置:op_host/graph_softmax.cpp 的 TilingForGraphSoftmax 函数

当前(硬编码):

constexpr uint32_t SINGLE_LOOP_TASK = 2360;

优化后(动态计算):

uint32_t singleLoopTaskCount;
if (enableDoubleBuffer) {
    singleLoopTaskCount = ubSize / FLOAT_BYTE_SIZE / (NUM_FEATURE * 2 + 1) / 2;
} else {
    singleLoopTaskCount = ubSize / FLOAT_BYTE_SIZE / (NUM_FEATURE * 2 + 1);
}
// 向下对齐到 8 的倍数(满足 32B 对齐)
singleLoopTaskCount = (singleLoopTaskCount / 8) * 8;

同时在 tiling 结构中传递 ubSize,让 kernel 使用正确的循环边界。

3.4 OPT-3: Gather 批量化(消除逐边 GetValue + 小 DataCopy)

问题:在 Pass 2 和 Pass 3 中,内循环逐边读取 workspace:

for (uint32_t i = 0; i < taskCount; i++) {
    DataCopy(scatterMaxLocal_[i * NUM_FEATURE],
             scatterMaxResGm_[indexLocal_.GetValue(i) * NUM_FEATURE], NUM_FEATURE);
}

每次调用 GetValue(标量访问)+ DataCopy(仅 32 字节),循环 taskCount 次(最多 2360 次)。

优化方案:使用 DataCopyExtParams 批量处理 + 预计算 GM 偏移

方案 A - 预计算偏移表 + 批量 Gather:

// 预计算 byte offset 表(在 CopyIn 后一次性计算)
for (uint32_t i = 0; i < taskCount; i++) {
    offsetTable_[i] = indexLocal_.GetValue(i) * NUM_FEATURE * FLOAT_BYTE_SIZE;
}
// 使用 Gather 批量读取
Gather(scatterMaxLocal_, scatterMaxResGm_, offsetTable_, 0, taskCount * NUM_FEATURE);

方案 B - 分块连续化:

  • 对 index 数组进行局部排序(在 UB 中),将指向同一节点的边聚集在一起
  • 对聚集的边做一次大块 DataCopy
  • 这需要额外 UB 空间存排序索引,且增加计算复杂度,适合边密度高场景

推荐方案 A:Gather 方式更直接,不改变算法逻辑,实现风险低。

注意:Scatter 写操作(atomic max/add)无法批量化(因为是原子操作),但 Gather 读操作可以显著优化。

3.5 OPT-4: Pass2→Pass3 数据复用

问题:Pass 2 计算完 exp(src-max) 后写入 softmaxResultGm_(GM),Pass 3 再从 GM 读回。这造成了一次完整的 GM 写+读往返。

优化方案:在 Pass 3 中不从 softmaxResultGm_ 读取 exp 值,而是重新计算:

// Pass 3 优化:重新从 srcGm_ 读取原始 src,读取 max 后重算 exp
DataCopy(srcLocal_, srcGm_[offset * NUM_FEATURE], NUM_FEATURE * taskCount);
// 读取 scatter max
for (i) DataCopy(scatterMaxLocal_[i*8], scatterMaxResGm_[index[i]*8], 8);
// 重算 exp
Sub(srcLocal_, srcLocal_, scatterMaxLocal_, taskCount * NUM_FEATURE);
Exp(srcLocal_, srcLocal_, taskCount * NUM_FEATURE);
// 读取 scatter sum 并 normalize
...

收益:消除 Pass 2 中写 softmaxResultGm_ 的 MTE3 开销 + Pass 3 中读 softmaxResultGm_ 的 MTE2 开销。
代价:Pass 3 多一次 Sub + Exp 计算。但 Vector 计算通常远快于 GM 搬运,净收益为正。

3.6 OPT-5: Workspace 512B 对齐

修改位置:op_host/graph_softmax.cpp 的 workspace 分配

// 确保 workspace 中 scatterMax 和 scatterSum 的起始地址 512B 对齐
size_t scatterMaxSize = AlignUp(totalWorkspace * numFeature * sizeof(float), 512);
size_t scatterSumSize = AlignUp(totalWorkspace * numFeature * sizeof(float), 512);
size_t usrWorkSpaceSize = scatterMaxSize + scatterSumSize;
likedislike
jayhuajayhua成员
7月8日 添加了label:resolved
jayhuajayhua成员
7月8日 关联了里程碑:MindSpeed 26.2.0
samulenzz
7月12日 评论:

优化完成,带精度脚本与性能脚本验证

likedislike
samulenzz
7月19日 评论:

本周进度,利用官方脚本,性能验证中

likedislike
Ssamulenzz
7月26日 关联了pull request:⚡️ perf(graph-softmax): optimize grouped softmax execution
ascend-robot
ascend-robot成员
7月26日 评论:

您好,当前Issue标记为resolved且有一段时间未进一步更新,因此我们将其标记为'stale'(闲置)状态。若您认为这是误操作,可通过添加任意评论来去除'stale'标签。标记为stale的Issue在4天内无更新活动将自动关闭。

likedislike
ascend-robotascend-robot成员
7月26日 添加了label:stale
samulenzz
7月27日 评论:

本周进度,已提交 pr

likedislike
qiuqiu成员
7月29日 评论:

@samulenzz 采用op_perf脚本对UT文件中的47个case进行测试后,发现存在性能提升未到20%的情况。附上我的测试结果(见附件)
0b2c0706131e4a398d7674f2be49f4ea.zip
测试环境:910B2;
CANN:9.1.0.beta3社区版(获取链接:https://www.hiascend.com/developer/download/community/result?module=cann&cann=9.1.0-beta.3 )
torchNPU:torch2.7.1.post8 (获取链接:https://gitcode.com/Ascend/pytorch/releases,release v26.1.0-pytorch2.7.1)
Python:3.11
基线版本(附件中的baseline):DrivingSDK git8cbc979
优化版本(附件中的optimize):你所提交的分支代码

likedislike
samulenzz
7月31日 评论:

@samulenzz 采用op_perf脚本对UT文件中的47个case进行测试后,发现存在性能提升未到20%的情况。附上我的测试结果(见附件)
0b2c0706131e4a398d7674f2be49f4ea.zip
测试环境:910B2;
CANN:9.1.0.beta3社区版(获取链接:https://www.hiascend.com/developer/download/community/result?module=cann&cann=9.1.0-beta.3 )
torchNPU:torch2.7.1.post8 (获取链接:https://gitcode.com/Ascend/pytorch/releases,release v26.1.0-pytorch2.7.1)
Python:3.11
基线版本(附件中的baseline):DrivingSDK git8cbc979
优化版本(附件中的optimize):你所提交的分支代码

@qiucan4

您好,由于上个版本我的测试代码提前进行了dtype转换导致了错误,现已重新更新了pr中的代码,(⚡️ perf(graph-softmax): optimize grouped softmax execution)
本地复测UT文件中的47个case,性能提升,31.2%
辛苦再次验证
测试环境:hidevLab, Ascend910_9382
镜像:26.0.0-cann9.0.0-a3-ubuntu22.04

likedislike
samulenzz
8月2日 评论:
qiuqiu成员
8月5日 评论:

@samulenzz 精度和性能测试结果已达标 需要对检视意见进行闭环。

likedislike
samulenzz
8月5日 评论:

@samulenzz 精度和性能测试结果已达标 需要对检视意见进行闭环。

@qiucan4

你好pr中所有的评审意见,我均已修改完毕

likedislike
jayhuajayhua成员
9月9日 issue状态由 TODO 改变为 DONE
jayhuajayhua成员
9月9日 关闭了 issue