已合并
AdaLayerNormV2、AdaLayerNormQuant支持A5和性能优化 #912
陈海杰创建于 1月22日
AdaLayerNormV2、AdaLayerNormQuant支持A5和性能优化 #912
已合并
陈海杰创建于 1月22日
陈海杰成员
1月22日

描述

关联的Issue

测试

文档更新

类型标签

likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 陈海杰 的贡献)
CANN-robotCANN-robot成员
1月22日 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
1月22日 评论:

CLA Signature Pass

chenhaijie1423, thanks for your pull request. All authors of the commits have signed the CLA. 👍

likedislike
CANN-robot
CANN-robot成员
1月22日 评论:

🔵 source code change are detected, tasks labels is removed in this pull request!

likedislike
陈海杰成员
1月22日 评论:

compile

likedislike
CANN-robotCANN-robot成员
1月22日 添加了label:ci-pipeline-running
CANN-robot
CANN-robot成员
1月22日 评论:

流水线任务触发成功,任务链接 [3e9361e4c78440d88d6724de983f57a1]

任务名称状态日志下载链接
codecheck ✅ SUCCESS >>>>>
anti_virus ✅ SUCCESS >>>>>
Check_Pr ✅ SUCCESS >>>>>
Compile_Ascend_X86 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_mobile_station ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_single ✅ SUCCESS >>>>> >>>>>
API_Check ⚠️ WARNING >>>>>
UT_Test_ophost ✅ SUCCESS
UT_Test_opapi ✅ SUCCESS
UT_Test_kernel ✅ SUCCESS
Smoke_A900 ✅ SUCCESS >>>>> >>>>>

[2026-01-22 17:36:34]    CI执行结束

likedislike
CANN-robotCANN-robot成员
1月22日 添加了label:api-check-failed
CANN-robot
CANN-robot成员
1月22日 评论:

问题/功能描述

本次PR对AdaLayerNorm算子进行了全面的功能增强、平台适配和代码重构。核心目标是优化算子在Regbase架构(如Ascend 910B)上的Tiling(分片)策略,以解决原有逻辑在特定硬件和输入维度下缓冲区计算不准确、核数分配不完善的问题,确保算子高效稳定运行。同时,通过代码重构和模块化设计,提升了代码的可维护性和复用性,并为算子扩展了对新硬件平台(ascend910_95)、更多数据类型(如多种FP8格式)以及量化功能的支持。

修改方案描述

修改方案围绕Tiling优化、代码重构和功能扩展三个核心展开。首先,在Tiling策略中新增了对Regbase架构的识别,并引入专门的DoLayerNormTiling函数精确计算临时缓冲区大小,优化核数分配与对齐逻辑。其次,通过新增工具头文件(ada_layer_norm_util.hada_layer_norm_common.h)和重构内核实现,将大量重复的常量、工具函数和数据拷贝逻辑模块化,简化了事件同步与计算流程,提升了代码清晰度。最后,为AdaLayerNormQuantAdaLayerNormV2算子新增了针对ascend910_95平台的配置、内核实现(apt文件)及二进制接口定义,扩展了其对多种低精度数据格式(INT8/FP8)的支持,并补充了相应的单元测试以验证功能正确性。

likedislike
CANN-robot
CANN-robot成员1月22日进行代码检视1
norm/ada_layer_norm/op_host/ada_layer_norm_tiling.cpp
@@ -119,30 +127,30 @@
119127 epsilon = *tilingContext->GetAttrs()->GetAttrPointer<float>(0);
120128 
121129 auto compileInfo = reinterpret_cast<const AdaLayerNormCompileInfo*>(tilingContext->GetCompileInfo());
122130 int32_t coreNumPlatform = compileInfo->coreNum;
123131 int32_t needCoreNum = SplitCore(coreNumPlatform);
132+ if (compileInfo->isRegBase) {
133+ DoLayerNormTiling();
134+ }
135+ 
124136 size_t* workspaces = tilingContext->GetWorkspaceSizes(1);
125137 if (opCode == QUANT_OP_CODE && hiddenDim > SINGLE_ROW_SIZE) {
126138 workspaces[0] = WORK_SPACE_SIZE + needCoreNum * hiddenDimCeil * sizeof(float);
@@ -128,12 +140,8 @@ ge::graphStatus AdaLayerNormTiling::RunBigKernelTiling()
128140 workspaces[0] = WORK_SPACE_SIZE;
129141 }
130142 
131- tilingContext->SetBlockDim(coreNumPlatform);
132- if (opCode == BASE_V2_OP_CODE && isWeightFloat) {
133- tilingContext->SetTilingKey(TILING_KEY_TWO);
134- } else {
135- tilingContext->SetTilingKey(TILING_KEY_ONE);
136- }
143+ tilingContext->SetBlockDim(needCoreNum);
144+ tilingContext->SetTilingKey(GetTilingKey(compileInfo->isRegBase));
137145 FillTilingData();
138146 return ge::GRAPH_SUCCESS;
139147}
@@ -147,6 +155,7 @@ int32_t AdaLayerNormTiling::SplitCore(int32_t coreNumPlatform)
147155 } else if (hiddenDim > SINGLE_ROW_SIZE) {
148156 int64_t batch = CeilA2B(hiddenDim, SINGLE_ROW_SIZE);
149157 sliceSize = CeilA2B(hiddenDim, batch);
CANN-robot
CANN-robot1月22日评论:

逻辑错误: 在Init函数中,当hasBias为true且biasTensor的数据类型不是DT_FLOAT时,将isWeightFloat设置为false。这个变量名isWeightFloat容易引起误解,因为它不仅检查weight,还检查bias。而且当hasWeight为false但hasBias为true时,这个变量的命名就不准确了。

问题类型: 逻辑错误
文件路径: norm/ada_layer_norm/op_host/ada_layer_norm_tiling.cpp
行号: 95
问题代码:

if (hasBias && biasTensor->GetDataType() != ge::DataType::DT_FLOAT) {
    isWeightFloat = false;
}

修改建议:

建议将变量名改为更准确的名称,如isWeightBiasFloat或isOptionalParamsFloat。或者分开处理weight和bias的浮点类型检查。更好的做法是:bool isWeightFloat = hasWeight ? (weightTensor->GetDataType() == ge::DataType::DT_FLOAT) : true; bool isBiasFloat = hasBias ? (biasTensor->GetDataType() == ge::DataType::DT_FLOAT) : true; 然后根据需要使用这两个变量。

此评论由代码审查工具自动生成

likedislike
CANN-robot
CANN-robot成员1月22日进行代码检视1
norm/ada_layer_norm/op_kernel/ada_layer_norm_base.h
@@ -541,4 +484,4 @@
541484 
542485 xGm.SetGlobalBuffer((__gm__ X_DTYPE*)gmAddr->x);
543486 scaleGm.SetGlobalBuffer((__gm__ X_DTYPE*)gmAddr->scale);
544487 shiftGm.SetGlobalBuffer((__gm__ X_DTYPE*)gmAddr->shift);
CANN-robot
CANN-robot1月22日评论:

代码结构与可维护性: 第338行调用 CopyOut(quantOutGm[range.rowStart * hiddenDim], yInt, range.actualRowNum, hiddenDim);,但 CopyOut 函数未在类中声明或定义(仅在第56-59行有 BaseCopyOutCopyScaleOutCopyMeanRstdOut)。这可能是来自 ada_layer_norm_util.h 的通用函数,但在此上下文中使用不一致,降低了代码可读性和维护性。

问题类型: 代码结构与可维护性
文件路径: norm/ada_layer_norm/op_kernel/ada_layer_norm_base.h
行号: 338
问题代码:

            CopyOut(quantOutGm[range.rowStart * hiddenDim], yInt, range.actualRowNum, hiddenDim);

修改建议:

建议统一拷贝函数命名或添加类内声明。如果 `CopyOut` 是外部函数,应在头文件中添加注释说明其来源和用途,或考虑封装为类方法以保持接口一致性。

此评论由代码审查工具自动生成

likedislike
CANN-robot
CANN-robot成员1月22日进行代码检视1
norm/ada_layer_norm/op_kernel/ada_layer_norm_base_v1.h
@@ -702,4 +643,4 @@
702643 Add(yFloat, yFloat, biasFloat, hiddenDim);
703644 PipeBarrier<PIPE_V>();
704645 }
705646}
CANN-robot
CANN-robot1月22日评论:

代码可维护性: 在 CopyMeanRstdOut 函数中,动态获取 eventIdVToMte3 事件 ID:event_t eventIdVToMte3 = static_cast<event_t>(pipe.FetchEventID(HardEvent::V_MTE3));。如果 pipe.FetchEventID 返回的值与之前使用的静态事件 ID 不一致,可能导致同步错误。

问题类型: 代码可维护性
文件路径: norm/ada_layer_norm/op_kernel/ada_layer_norm_base_v1.h
行号: 434
问题代码:

event_t eventIdVToMte3 = static_cast<event_t>(pipe.FetchEventID(HardEvent::V_MTE3));

修改建议:

确保动态获取事件 ID 的方式与代码中其他事件同步保持一致。如果其他地方使用了静态事件 ID,建议统一为一种方式,以避免混淆和潜在的错误。

此评论由代码审查工具自动生成

likedislike
CANN-robot
CANN-robot成员1月22日进行代码检视1
norm/ada_layer_norm/op_kernel/arch35/ada_layer_norm_common.h
@@ -0,0 +46,4 @@
46+constexpr LayerNormConfig hasGammaBetaConfig = {false, false, false};
47+constexpr LayerNormConfig hasGammaNoBetaConfig = {true, false, false};
48+constexpr LayerNormConfig noGammaHasBetaConfig = {false, true, false};
49+constexpr LayerNormConfig noGammaNoBetaConfig = {true, true, false};
CANN-robot
CANN-robot1月22日评论:

代码结构与可维护性: noGammaNoBetaConfig常量的初始化值与命名存在矛盾。常量名'noGammaNoBetaConfig'暗示没有Gamma和Beta,但其初始化值却为{true, true, false},前两个布尔值(通常对应hasGamma和hasBeta)被设置为true,这与命名相悖。从上下文看,第46-49行定义了四个配置,分别对应Gamma和Beta的有无组合。根据命名惯例,'hasGammaBetaConfig'表示两者都有(false, false, false?这里需要查看LayerNormConfig结构定义),但当前初始化值逻辑不清晰,容易导致使用错误。

问题类型: 代码结构与可维护性
文件路径: norm/ada_layer_norm/op_kernel/arch35/ada_layer_norm_common.h
行号: 49
问题代码:

constexpr LayerNormConfig noGammaNoBetaConfig = {true, true, false};

修改建议:

1. 检查LayerNormConfig结构体的定义,明确各布尔成员的含义(例如,是否是hasGamma, hasBeta, 或其他)。
2. 根据结构体成员的实际含义,修正noGammaNoBetaConfig的初始化值,使其与命名一致。例如,如果前两个成员分别表示hasGamma和hasBeta,则应改为{false, false, false}。
3. 同样,检查并修正其他三个配置常量(hasGammaBetaConfig, hasGammaNoBetaConfig, noGammaHasBetaConfig)的初始化值,确保其与命名匹配。
4. 在常量定义处添加注释,说明每个布尔值的具体含义。

此评论由代码审查工具自动生成

likedislike
CANN-robot
CANN-robot成员1月22日进行代码检视1
norm/ada_layer_norm/op_kernel/arch35/ada_layer_norm_full_load.h
@@ -0,0 +339,4 @@
339+ if constexpr (OP_CODE == QUANT_OP_CODE) {
340+ quantOutLocal = quantOutQueue.AllocTensor<Y>();
341+ quantOutAddr = (__ubuf__ Y*)quantOutLocal.GetPhyAddr();
342+ smoothAddr = (__ubuf__ T*)smoothLocal.GetPhyAddr();
CANN-robot
CANN-robot1月22日评论:

指针与引用安全: 在Adaption函数中,当OP_CODE == QUANT_OP_CODE时,smoothAddr被赋值为(ubuf T*)smoothLocal.GetPhyAddr()。但smoothLocal仅在hasSmooth为真时才从smoothQueue.DeQue()获取(见Process函数第176行)。如果hasSmooth为假,smoothLocal可能未初始化或无效,而smoothAddr仍被使用(第399-403行),导致未定义行为。

问题类型: 指针与引用安全
文件路径: norm/ada_layer_norm/op_kernel/arch35/ada_layer_norm_full_load.h
行号: 342
问题代码:

smoothAddr = (__ubuf__ T*)smoothLocal.GetPhyAddr();

修改建议:

将smoothAddr的赋值和smoothLocal的使用包裹在if (hasSmooth)条件内,或者确保当hasSmooth为假时,smoothAddr不被使用。

此评论由代码审查工具自动生成

likedislike
CANN-robot
CANN-robot成员1月22日进行代码检视1
norm/ada_layer_norm_quant/op_host/ada_layer_norm_quant_def.cpp
@@ -68,0 +22,4 @@
22+ ge::DT_FLOAT8_E5M2, ge::DT_FLOAT8_E5M2};
23+static const std::vector<ge::DataType> scaleDataType = {ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT,
24+ ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT};
25+static const std::vector<ge::Format> format = {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
CANN-robot
CANN-robot1月22日评论:

代码结构与可维护性: format数组包含8个相同的FORMAT_ND格式。这种重复的硬编码同样属于'魔数'问题,且与数组长度8紧密耦合。如果未来配置数量变化,需要同步修改多个地方。

问题类型: 代码结构与可维护性
文件路径: norm/ada_layer_norm_quant/op_host/ada_layer_norm_quant_def.cpp
行号: 25
问题代码:

static const std::vector<ge::Format> format = {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
                                               ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND};

修改建议:

使用常量定义数组长度,并通过循环或std::fill初始化format数组。或者考虑是否真的需要8个相同的格式配置,或许可以简化为单个格式的配置。

此评论由代码审查工具自动生成

likedislike
CANN-robotCANN-robot成员
1月22日 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
1月22日 添加了label:ci-pipeline-running
CANN-robotCANN-robot成员
1月22日 删除了label:api-check-failed
CANN-robotCANN-robot成员
1月22日 添加了label:api-check-failed
CANN-robotCANN-robot成员
1月22日 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
1月22日 添加了label:ci-pipeline-passed
tang-lei01成员
1月22日 评论:

/approve

likedislike
胡碧霞成员
1月22日 评论:

/approve

likedislike
CANN-robotCANN-robot成员
1月22日 添加了label:approved
於欣洁成员
1月22日 评论:

/lgtm

likedislike
陈海杰成员
1月22日 评论:

/check-pr

likedislike
CANN-robot
CANN-robot成员
1月22日 评论:

The following label is not ready.

lgtm: Please wait for reviewers to review the code.

likedislike
liubo75成员
1月22日 评论:

/lgtm

likedislike
CANN-robotCANN-robot成员
1月22日 添加了label:lgtm
CANN-robot
CANN-robot成员
1月22日 评论:

Review Guide

This Pull-Request Passes Review.
Committers who wrote a comment of /approve are: crystalhu, tang-lei01.
Reviewers who wrote a comment of /lgtm are: liubo75, crystalhu, tang-lei01.

likedislike
CANN-robotCANN-robot成员
1月22日 合入了pull request