当前位置: 首页 > news >正文

【精度】【核内同步】applyTopKTopPWithSorted算子精度问题定位

1. 精度异常表现

在进行applyTopKTopPWithSorted算子泛化验证时有少部分用例遇到精度问题,如下图所示,遇到的异常值精度误差极大:
![请添加图片描述](https://i-blog.csdnimg.cn/direct/c0bf7f59b986468d85ea5364c620b8ce.png
其中-200.0为实际为-inf值,为了避免精度比较失败特意做的修正。

applyTopKTopPWithSorted算子功能说明文档:https://gitcode.com/cann/ops-nn/blob/master/index/apply_top_k_top_p_with_sorted/README.md
功能介绍:算子通过升序排序后依次经过k和p两个条件做过滤取保留其中较大值,其他值涂成-inf,计算流程图如下:

2. 猜想,实验与现象

此类输出精度异常值差距极大,通常是有脏数据引入,比如输出的张量未初始化值,或者计算过程中获取到错误数据计算,这种错误数据一般来自初始化、数据踩踏和同步问题。
初始化是一种常见赋值操作,比如这个算子的输出就是保留部分较大值,其他值填充成-inf,那么kernel中的计算逻辑就会先把输出的所有值初始化成-inf,这样后续只需要计算哪些是保留的有效值并进行搬出就可以,不需要保留的值已经默认是-inf了。
数据踩踏一般是因为索引计算错误出现越界现象,比如A和B是两块相邻连续空间且本应互不相干,但是因为索引计算错误把B中部分数据干扰到A,或者反过来,在某些计算场景下这样的数据错乱就会导致结果异常。
同步问题则是前后数据计算之间有依赖,比如add,mul,reduceSum等vec操作,他们不是串行执行而是异步发射执行,如果指令间不插入同步,A变量可能在前一个vec函数还没有计算完情况下变已经传入到后续计算中处理,这样也会获取到错误数据计算导致异常。

2.1 初始化问题

初始化问题比较容易验证,笔者注直接释掉最后计算结果中红框部分的搬出操作接口,重新运行用例,输出全为-200(-inf),表明初始化没有问题。

2.2.数据踩踏和同步问题

数据踩踏和同步问题就稍微复杂些,通常需要跟着kernel实现流程进行分析。索引计算会更加复杂,所以笔者首先尝试定位是否是同步问题。
定位同步问题过程中,我们没办法一下子找到异常点,也没有查询到可以增加全局同步的方式。于是笔者用AI模型自制的一个小脚本,加载当下路径1.cpp文件内容逐行判断,在任意两行之间插入PipeBarrier<PIPE_ALL>()生成为1_modified.cpp,快速确认是否有核内同步问题存在。脚本如下,关键词是一些声明、赋值、变量创建等等不需要插入PIPE_ALL同步的相关语句(可能会引入报错),因此这些行都不增加PIPE_ALL。

# -*- coding: utf-8 -*- import re # 定义需要检查的关键词列表 keywords = ["constexpr", "using", "namespace", "__aicore__", "void", "SetFlag", "WaitFlag", "TQue<", "TBuf<", "void", "uint32_t ", "int64_t ", "float ", "inputT ", "GlobalTensor<", "LocalTensor<", "BinaryRepeatParams", "DataCopyExtParams", "for", " = ", "InitBuffer", "SetGlobalBuffer", " < ", " > ", "FreeTensor", "TPipe", "GM_ADDR", "continue", "+=", "//", "PIPE_ALL"] # 输入输出文件路径 input_file = "1.cpp" output_file = "1_modified.cpp" # 编译正则表达式以提高效率(忽略大小写) pattern = re.compile(r'|'.join(re.escape(kw) for kw in keywords), re.IGNORECASE) # 用于存储修改后的行 modified_lines = [] # 读取原始文件 with open(input_file, 'r', encoding='utf-8') as f: lines = f.readlines() # 遍历每一行 for line_num, line in enumerate(lines, start=1): # 去掉行尾换行符,处理时用 stripped_line = line.rstrip('\n') # 检查是否包含关键词(不区分大小写) if pattern.search(stripped_line) or len(stripped_line) < 5: # 包含关键词,原样保留 modified_lines.append(line) else: # 不包含关键词,检查是否包含 ";" if ';' in stripped_line: # 替换所有分号为 "; PipeBarrier<PIPE_ALL>();" # 注意:这里我们只替换分号本身,保持前后结构 new_line = stripped_line.replace(';', ';PipeBarrier<PIPE_ALL>();') modified_lines.append(new_line + '\n') else: # 不包含关键词也不含分号,原样保留 modified_lines.append(line) # 写入修改后的内容到新文件 with open(output_file, 'w', encoding='utf-8') as f: f.writelines(modified_lines) print(f"处理完成!已将修改后的内容写入 {output_file}")

我们将增加了PIPE_ALL的新代码重新进行kernel编译去运行用例(如果读者使用该脚本后进行kernel编译失败的话需要根据报错日志自己微调下),用例精度直接PASS了。连着运行几次都是成功,这说明我们的问题来自同步。后面笔者就用二分法逐步还原代码函数片段,最终定位到是下面这个函数还原后(即不增加PIPE_ALL)精度问题又出现了。再对这个函数内部进行二分,进一步缩小到346行到352行之间任意位置插入PipeBarrier<PIPE_ALL>()时没有精度问题。笔者再直接分析这一段代码的计算逻辑:①CumSum计算结果;②先直接搬运最后一个值(最大值,也就是算子最少会保留一个值);③352行代码之后再根据loopProb-1遍历跟1-p阈值比较去搬运剩余的值。

从计算过程来看,①中Cumsum计算的值会在后续③中用来做判断依据,①和③是有依赖关系存在,但是笔者之前进行同步分析时在353行之后插入PIPE_ALL仍旧存在同步问题,这说明①cumsum计算过程是和②搬运最后一个值产生了同步问题,但这里二者本身不存在依赖关系,就很耐人寻味。
于是笔者想到唯一可能方向:复用空间。
①CumSum计算函数用到以下tensor:cumSumRes,cumSumTmp,softMaxRes,sharedTmpBuffer,
②搬运最后一个值用到以下tensor:scatterTensormGmOut_
其中①CumSum计算用到的临时空间sharedTmpBuffer和②中的scatterTensor是复用的,而他们之间只有347行有个PipeBarrier<PIPE_V>();和351行PipeBarrier<PIPE_MTE3>();操作,分别表示vec操作到vec操作之间的同步和mte3到mte3流水搬运之间的同步。这里就会出现一个情况,vec到mte3之间缺少同步,他们是异步执行的,在CumSum还在计算过程中时,scatterTensor取最后值并进行搬出的操作就已经开始了,这其中会产生错误数值导致最终精度异常。
# 3. 精度误差根源

CumSum和搬出最后一值过程中分别使用到的sharedTmpBufferscatterTensor共用一块空间,但是中间过程缺少相应同步,导致cumsum计算过程和最后一个值搬出过程冲突产生错误数值,最终使精度出现异常。

4. 解决方式

增加正确的同步操作:①508行cumsum计算→②509行vec到scalar同步确保cumsum计算完再使用scatterTensor取值:VToSSync();→③scatterTensor取最后值→④512行确保scalar取值完成后再进行搬出操作:SToMTE3Sync();→⑤最后一个值搬出。

5. 启发

在高性能计算中,合理复用内存空间能有效降低显存占用。但当多个异步操作共享同一块缓冲区时,若缺乏恰当的同步控制,极易引发数据竞争和精度异常。莫让“省空间”变成“出问题”,同步要“恰到好处”,要考虑空间复用之间的相互影响。

http://www.jsqmd.com/news/461023/

相关文章:

  • Pytorch2 PyTorch 张量(Tensors)完全指南
  • PyTorch4 Transforms 保姆级教程|ToTensor Lambda 实战
  • PyTorch5 构建神经网络保姆级教程|从层到模型全拆解
  • 2026年质量好的混纺PTFE滤袋厂家推荐:混纺PTFE滤袋厂家选择指南 - 品牌宣传支持者
  • C++ Lambda表达式:高效编程利器
  • C++进阶:从C到C++的完美过渡
  • 2026年口碑好的PTFE滤袋公司推荐:针刺毡PTFE滤袋实力厂家推荐 - 品牌宣传支持者
  • 宝鸡钛棒源头厂家/宝鸡钛棒现货工厂怎么挑?2026宝鸡钛合金棒厂家推荐:宝鸡鹰翔钛业,源头厂家实力供应 - 栗子测评
  • 精选2026宝鸡纯钛棒厂家推荐/TC4钛棒生产厂家推荐:宝鸡鹰翔钛业生产厂家直供 - 栗子测评
  • 精选2026甲基丙基酰氧基硅烷供应商/烷基硅烷生产厂家:杭州杰西卡,源头直供与定制化方案 - 栗子测评
  • “现代战争”天梯赛习题
  • 2026纳米二氧化钛厂家|二氧化钛分散液源头厂家-优选宁波极微纳 - 栗子测评
  • Flutter 三方库 commander_ui 的鸿蒙化适配指南 - 构建大屏控制台风格 UI、支持指令式交互与极客风格面板
  • 宿舍管理系统厂家怎么选?2026学生宿舍管理系统推荐:掌门物联科技-创新校园住宿管理智能化新体验 - 栗子测评
  • 学生公寓门锁哪家好?2026掌门物联科技:用智慧公寓系统打造住宿管理新生态 - 栗子测评
  • 高校智能锁哪家好?2026精选优质校园安全出入管理系统厂家:掌门物联科技铸造校园安全出入防线 - 栗子测评
  • 环氧树脂地坪批发怎么选?2026年优质供应商实力解析 - 2026年企业推荐榜
  • 琴房预约系统哪家好?2026掌门物联科-专业琴房管理系统厂家,打造校园琴房智能管理新方式 - 栗子测评
  • STM32——FreeRTOS - 基础
  • 2026KH-550/KH-560/KH-570偶联剂生产厂家:杭州杰西卡-用品质铸造口碑 - 栗子测评
  • 2026校园门锁哪家好?校园智能门锁厂家?掌门物联科技-打造专业校园无线智能锁品牌,铸造安全防线 - 栗子测评
  • 2026年热门的电厂PPS滤袋厂家推荐:电厂PPS滤袋销售厂家推荐 - 品牌宣传支持者
  • 2026年3月湖北环氧地坪厂家实力盘点与选购指南 - 2026年企业推荐榜
  • L3-010 是否完全二叉搜索树 - 题解与完整代码
  • OpenClaw变现实录:从“养龙虾“到可持续盈利的实践指南
  • L3-040 人生就像一场旅行 - 题解与完整代码
  • 2026年湖北力矩限制器实力厂家全景扫描与深度解析 - 2026年企业推荐榜
  • 桌面通用(全架构)【IE浏览器内核插件与 Chrome 内核浏览器插件的区别及兼容性分析】技术文章
  • 2026年武汉平移门选购指南:五大服务商深度解析 - 2026年企业推荐榜
  • 服务器通用(全架构)【服务器存储系统原理与运维实践解析】技术文章