算子开发的守护神深度解析msSanitizer异常检测工具【免费下载链接】cann-learning-hubCANN 学习中心仓支持在线互动运行、边学边练提供教程、示例与优化方案一站式助力昇腾开发者快速上手。项目地址: https://gitcode.com/cann/cann-learning-hub大家好欢迎来到Ascend C算子开发工具深度探索系列。在算子开发过程中你是否遇到过这样的问题代码看起来逻辑正确但一运行就出现神秘的精度错误、内存访问异常、或者莫名其妙的同步失败在昇腾AI芯片的开发生态中msSanitizerMindStudio Sanitizer就是我们的异常检测守护神。它是一款专门为单算子开发场景设计的工具能够在早期阶段发现并修复各类异常问题确保算子的质量和稳定性。本文将从msSanitizer的核心功能出发通过一个实际的Add算子案例深入讲解如何使用这个工具来检测和定位各类异常问题。无论你是刚接触Ascend C的新手还是希望提升开发效率的资深开发者相信这篇文章都能给你带来新的启发。一、为什么需要msSanitizer在Ascend C算子开发中我们面临着几类常见的异常问题异常类型问题表现定位难度内存类问题非法读写、内存泄漏、非对齐访问⭐⭐⭐⭐⭐数据竞争问题流水间/核间竞争导致精度异常⭐⭐⭐⭐未初始化问题脏数据读取导致结果错误⭐⭐⭐同步问题同步指令未配对导致后续算子失败⭐⭐⭐⭐这些问题往往具有隐蔽性——代码编译通过甚至在某些情况下运行正常但在特定条件下就会出现问题。msSanitizer的出现就是为了帮助我们在早期发现这些问题。msSanitizer的四大核心能力msSanitizer提供四类核心异常检测功能内存检测- 定位非法读写、多核踩踏、非对齐访问、内存泄漏、非法释放等问题竞争检测- 发现流水间竞争、流水内竞争、核间竞争等数据竞争问题未初始化检测- 检测内存未初始化导致的脏数据读取同步检测- 定位前序算子中未配对的同步指令问题使用前提在使用msSanitizer之前建议先通过msOpST工具在真实硬件环境中完成算子功能测试确保基本功能正确后再使用msSanitizer进行深度异常检测。二、msSanitizer使用指南2.1 基本使用流程环境准备参考算子开发工具文档中的环境准备章节编译算子使用标准的Ascend C编译流程生成测试数据运行gen_data.py生成输入数据使用msSanitizer运行根据需要选择不同的检测模式分析报错信息根据msSanitizer的输出来定位问题2.2 常用命令汇总# 基本检测非法读写 / 非对齐访问 mssanitizer ./demo # 开启内存泄漏检查 mssanitizer ./demo --leak-checkyes # 开启分配内存未使用检查 mssanitizer ./demo --check-unused-memoryyes # 竞争检测 mssanitizer ./demo --toolracecheck # 未初始化检测 mssanitizer ./demo --toolinitcheck2.3 如何读懂msSanitizer报错信息msSanitizer的报错信息格式是统一的学会解读这格式就能快速定位问题 ERROR: 错误类型 of size 大小 at 地址 on 内存类型 in 算子名 in block 块信息 on device 设备号关键信息解读错误类型illegal write/misaligned access/LeakCheck等告诉你是什么问题大小异常访问的字节数地址异常发生的具体内存地址内存类型UBUnified Buffer统一缓冲区/ GMGlobal Memory全局内存算子名哪个算子出的问题块信息在哪个AI Core/AIV块设备号在哪个设备上2.4 支持的产品Atlas A3 训练系列产品/Atlas A3 推理系列产品Atlas A2 训练系列产品/Atlas A2 推理系列产品2.5 使用限制msSanitizer存在两类不支持的检测场景❌ 不支持对多线程算子进行检测❌ 不支持对使用了掩码的向量类计算指令进行检测三、最佳实践如何高效使用msSanitizer3.1 检测顺序建议建议按照以下顺序进行检测这样能帮你系统性地排查问题先测基本功能用msOpST确保算子功能正确再测内存检测发现非法读写、对齐问题等基础问题然后测泄漏检测确保没有内存泄漏最后测竞争和初始化发现更隐蔽的并行问题3.2 常见问题排查清单问题现象可能原因建议检测工具运行崩溃非法读写、非对齐访问基础mssanitizer结果错误数据竞争、未初始化--toolracecheck/initcheck内存持续增长内存泄漏--leak-checkyes时好时坏数据竞争--toolracecheck四、msSanitizer内存检测深度解析现在我们通过一个实际的Add算子案例来看看msSanitizer如何帮助我们检测各类内存异常。4.1 案例背景Add算子实现我们要实现的是一个固定shape为72×4096的Add算子计算公式很简单z x y其中x输入形状为[72, 4096]数据类型为floaty输入形状为[72, 4096]数据类型为floatz输出形状为[72, 4096]数据类型为floatAdd算子的经典三段式实现流程CopyIn将Global Memory上的xGm和yGm搬运到Local MemoryCompute对xLocal和yLocal执行加法操作CopyOut将结果从zLocal搬运至Global Memory4.2 异常场景一非法读写问题描述访问了未分配的内存区域复现方法在DataCopy中使用错误的搬运大小// 1. correct datacopy AscendC::DataCopy(xLocal, xGm[i * TILE_LENGTH], TILE_LENGTH); // 2. illegal read of xGm (TILE_LENGTH*2) // AscendC::DataCopy(xLocal, xGm[i * TILE_LENGTH], TILE_LENGTH * 2);问题分析LocalTensor xLocal分配的大小为TILE_LENGTH但搬运时错误地填为TILE_LENGTH * 2大于xLocal分配的大小因此触发非法读写。msSanitizer报错 ERROR: illegal write of size 16384 at 0x0 on UB in add_custom in block aiv(0-7) on device 0按照我们前面讲的解读方式illegal write of size 16384检测到16384字节的非法写入at 0x0 on UB异常发生在Unified Buffer的0x0地址in add_custom在add_custom算子中in block aiv(0-7)在AIV块0-7中4.3 异常场景二非对齐访问问题描述内存访问未满足字节对齐要求复现方法使用未对齐的UB侧地址// 1. correct datacopy AscendC::DataCopy(xLocal, xGm[i * TILE_LENGTH], TILE_LENGTH); // 3. misaligned access of xLocal (should be 32Byte aligned) // AscendC::DataCopy(xLocal[5], xGm[i * TILE_LENGTH], TILE_LENGTH);问题分析DataCopy GM-UB的搬运中UB侧地址需要满足32B对齐要求但xLocal[5]的地址是5 * sizeof(float) 20字节不满足32B对齐因此触发非对齐访问异常。msSanitizer报错 ERROR: misaligned access of size 32 at 0x14 on UB in add_custom in block aiv(0-7) on device 0硬件背景知识 在昇腾AI芯片中Unified Buffer的访问通常需要满足32字节对齐。非对齐访问会导致性能下降甚至硬件异常。msSanitizer能够精准检测这类问题。4.4 异常场景三内存泄漏问题描述申请内存使用后未释放导致程序运行过程中内存占用持续增加复现方法注释掉内存释放代码// 1. correct free for memory. If deleted, it will trigger memory leak check. aclrtFree(tilingDevice);问题分析注释掉aclrtFree后tilingDevice在使用后未释放因此触发内存泄漏检测。注意调用mssanitizer时需要传入--leak-checkyes来开启分配内存泄露检查。msSanitizer报错 ERROR: LeakCheck: detected memory leaks Direct leak of 64 byte(s) at 0x12c0c0013000 on GM allocated in :0 (serialNo:0)4.5 异常场景四分配内存未使用问题描述对内存分配后未使用导致资源浪费复现方法分配超过实际需要的内存// 1. correct malloc for memory aclrtMalloc((void **)(inputDevice[i]), inputsInfo[i].length, ACL_MEM_MALLOC_HUGE_FIRST); // 2. needed inputsInfo[i].length, but malloc length * 5, therefore trigger unused memory // aclrtMalloc((void **)(inputDevice[i]), inputsInfo[i].length * 5, ACL_MEM_MALLOC_HUGE_FIRST);问题分析inputDevice[i]实际需要分配的大小为inputsInfo[i].length但分配了inputsInfo[i].length * 5其中有inputsInfo[i].length * 4未使用因此触发分配内存未使用检测。注意调用mssanitizer时需要传入--check-unused-memoryyes来开启分配内存未使用检查。msSanitizer报错 WARNING: Unused memory of 4718624 byte(s) at 0x12c041200000 on GM code in :0 (serialNo:260)五、竞争检测发现并行计算中的隐蔽问题在多核或流水并行的场景中数据竞争是一个常见但难以定位的问题。msSanitizer的竞争检测功能能够帮助我们发现这类问题。5.1 什么是数据竞争数据竞争发生在多个执行单元不同流水线、不同核同时访问同一块内存至少有一个访问是写操作没有正确的同步机制来保证访问顺序在Add算子的流水并行实现中我们使用SetFlag和WaitFlag来保证MTE2 GM-UB的搬运和Vector计算Add的时序。5.2 异常场景流水间竞争问题描述删除同步指令导致先计算后搬运数据复现方法注释掉SetFlag和WaitFlag// dependency of PIPE_MTE2 PIPE_V caused by xLocal/yLocal in one single loop // If SetFlag and WaitFlag are deleted, will trigger RAW AscendC::SetFlagAscendC::HardEvent::MTE2_V(EVENT_ID0); AscendC::WaitFlagAscendC::HardEvent::MTE2_V(EVENT_ID0);问题分析SetFlag和WaitFlag用来保证MTE2搬运和Vector计算的时序。删除后可能会导致先计算Add再搬运数据导致读取到旧数据RAW hazard因此触发竞争检测。注意调用mssanitizer时需要传入--toolracecheck来开启竞争检测。msSanitizer报错 ERROR: Potential RAW hazard detected at UB in add_custom on device 0: PIPE_MTE2 Write at RAW()0x4000 in block 0 (aiv) on device 0 at pc current 0xd08 (serialNo:25) xxxxx PIPE_V Read at RAW()0x4000 in block 0 (aiv) on device 0 at pc current 0x1578 (serialNo:28) xxxxx如何理解RAW hazardRAW Read After Write写后读PIPE_MTE2在地址0x4000处写入PIPE_V在同一地址处读取但没有正确的同步保证写完成后再读六、未初始化检测防止脏数据引发的神秘错误内存申请后未初始化就直接读取是导致算子精度异常的常见原因之一。这类问题特别隐蔽因为未初始化内存的值是不确定的——有时候恰好是0结果看起来正常有时候是随机值结果就错误了。6.1 异常场景未初始化读取问题描述内存申请后为未初始化状态未对内存进行写入直接读取未初始化的值复现方法注释掉GlobalBuffer的初始化// correct initialize of zGm. // If deleted, it will trigger uninitialized read zGm.SetGlobalBuffer((__gm__ float *)z AscendC::GetBlockIdx() * singleCoreLength, singleCoreLength);问题分析对于device侧的zGm在使用前未初始化因此触发未初始化检测。注意调用mssanitizer时需要传入--toolinitcheck来开启未初始化检测。msSanitizer报错 ERROR: uninitialized read of size 1179648 at 0x12c041600000 on GM七、总结与回顾今天我们深入探讨了msSanitizer异常检测工具这是Ascend C算子开发中的守护神。让我们总结一下核心要点核心知识点回顾四大检测能力内存检测、竞争检测、未初始化检测、同步检测如何读报错掌握统一报错格式快速定位问题位置内存检测非法读写、非对齐访问、内存泄漏、未使用内存竞争检测发现流水间、流水内、核间的数据竞争未初始化检测防止脏数据读取导致的神秘错误命令选项根据需要选择不同的检测模式msSanitizer的价值早期发现问题在开发阶段就发现问题避免线上故障精准定位提供详细的报错信息帮助快速定位全面覆盖覆盖内存、竞争、初始化等各类异常易于使用简单的命令行接口上手快速msSanitizer虽然只是一个工具但正是这样的工具让我们的算子开发过程更加稳健和高效。希望这篇深度解析能帮助你更好地使用msSanitizer写出更高质量的Ascend C算子参考资料CANN社区版 9.0.0-beta.2 开发文档 - 异常检测msSanitizer本文代码案例参考https://gitcode.com/cann/asc-devkit/blob/master/examples/01_simd_cpp_api/01_utilities/05_sanitizer/msSanitizer本文基于CANN asc-devkit样例整理支持Atlas A3/A2训练和推理系列产品【免费下载链接】cann-learning-hubCANN 学习中心仓支持在线互动运行、边学边练提供教程、示例与优化方案一站式助力昇腾开发者快速上手。项目地址: https://gitcode.com/cann/cann-learning-hub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考