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

CANN/runtime遇错即停错误定位

遇错即停模式下错误定位方法

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

问题现象描述

现象1:遇错即停模式下无法准确定位失败任务

在Stream上配置了遇错即停模式(ACL_STOP_ON_FAILURE),任务执行失败时整个Context下的任务被停止,但无法准确定位是哪个任务失败,失败原因是什么。

典型场景:

aclrtStream stream; aclrtCreateStream(&stream); aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); // 下发多个任务 aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); kernel1<<<8, nullptr, stream>>>(args1); kernel2<<<8, nullptr, stream>>>(args2); aclrtMemcpyAsync(hostPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); // 同步时发现错误,但不知道是哪个任务失败 aclError error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { // 如何定位是kernel1还是kernel2失败? // 失败原因是什么? }

可能原因

  1. 任务序列较长:Stream上下发了多个异步任务,错误发生后无法直观判断是哪个任务失败。

  2. 错误信息不够详细:仅通过返回码无法获知具体失败原因,需要结合plog日志和错误查询接口。

  3. 遇错即停特性限制:遇错即停模式会在首个错误发生时停止Context中所有Stream的任务执行,可能影响错误现场的保护。

处理步骤

方法1:分段同步定位错误任务

将长任务序列分解为多个小段,每段后进行同步检查:

aclrtStream stream; aclrtCreateStream(&stream); aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); // 任务1:Host -> Device拷贝 aclError error = aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); if (error != ACL_RT_SUCCESS) { printf("Task 1 launch failed: %d\n", error); return error; } error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { printf("Task 1 execution failed: %d\n", error); char *errMsg = aclGetRecentErrMsg(); printf("Error: %s\n", errMsg); return error; } // 任务2:kernel1执行 kernel1<<<8, nullptr, stream>>>(args1); error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { printf("Task 2 (kernel1) execution failed: %d\n", error); char *errMsg = aclGetRecentErrMsg(); printf("Error: %s\n", errMsg); return error; } // 任务3:kernel2执行 kernel2<<<8, nullptr, stream>>>(args2); error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { printf("Task 3 (kernel2) execution failed: %d\n", error); char *errMsg = aclGetRecentErrMsg(); printf("Error: %s\n", errMsg); return error; } // 任务4:Device -> Host拷贝 aclrtMemcpyAsync(hostPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { printf("Task 4 execution failed: %d\n", error); return error; } aclrtDestroyStream(stream);

方法2:使用Event标记任务边界

在关键任务之间插入Event,通过Event状态判断任务执行进度:

aclrtStream stream; aclrtCreateStream(&stream); aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); // 创建多个Event用于标记任务边界 aclrtEvent event1, event2, event3; aclrtCreateEvent(&event1); aclrtCreateEvent(&event2); aclrtCreateEvent(&event3); // 下发任务并插入Event标记 aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); aclrtRecordEvent(event1, stream); // 标记拷贝任务完成 kernel1<<<8, nullptr, stream>>>(args1); aclrtRecordEvent(event2, stream); // 标记kernel1完成 kernel2<<<8, nullptr, stream>>>(args2); aclrtRecordEvent(event3, stream); // 标记kernel2完成 aclrtMemcpyAsync(hostPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); // 同步并检查错误 aclError error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { // 查询Event状态,定位失败任务 aclrtEventStatus status1, status2, status3; aclrtEventQuery(event1, &status1); aclrtEventQuery(event2, &status2); aclrtEventQuery(event3, &status3); printf("Event status: event1=%d, event2=%d, event3=%d\n", status1, status2, status3); // ACL_RT_EVENT_COMPLETE = 1, ACL_RT_EVENT_NOT_READY = 0 // 最后一个完成的Event之后的任务为失败任务 if (status1 == ACL_RT_EVENT_COMPLETE && status2 == ACL_RT_EVENT_NOT_READY) { printf("Task failed between event1 and event2 (kernel1 failed)\n"); } else if (status2 == ACL_RT_EVENT_COMPLETE && status3 == ACL_RT_EVENT_NOT_READY) { printf("Task failed between event2 and event3 (kernel2 failed)\n"); } char *errMsg = aclGetRecentErrMsg(); printf("Error detail: %s\n", errMsg); } // 清理资源 aclrtDestroyEvent(event1); aclrtDestroyEvent(event2); aclrtDestroyEvent(event3); aclrtDestroyStream(stream);

方法3:结合错误查询接口和plog日志

通过错误查询接口获取错误码,结合plog日志定位具体失败原因:

aclrtStream stream; aclrtCreateStream(&stream); aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); // 下发任务 // ...(省略任务下发代码) // 同步并检查错误 aclError error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { // 1. 获取错误码 printf("Stream synchronize failed with error code: %d (0x%x)\n", error, error); // 2. 查看最近错误 aclError lastError = aclrtPeekAtLastError(ACL_RT_THREAD_LEVEL); printf("Last error: %d (0x%x)\n", lastError, lastError); // 3. 获取详细错误信息 char *errMsg = aclGetRecentErrMsg(); if (errMsg != nullptr) { printf("Error message: %s\n", errMsg); } // 4. 提示查看plog日志 printf("Please check plog for detailed error information:\n"); printf(" - Look for 'fault kernel_name' to identify failed kernel\n"); printf(" - Look for 'retCode' to get error code\n"); printf(" - Look for 'error module_type' and 'module_name' for error source\n"); } aclrtDestroyStream(stream);

plog日志关键信息提取

# 查找失败的任务 grep "Task run failed" plog.log # 查找失败的内核名称 grep "fault kernel_name" plog.log # 查找错误码和类型 grep "retCode\|errType" plog.log # 查找错误模块 grep "module_type\|module_name" plog.log # 示例输出解析: # [ERROR] Task run failed, device_id=0, stream_id=2, task_id=1 # -> 定位到具体的设备、流、任务ID # fault kernel_name=Add_ee98c6628030785f610b924ab1557b31 # -> 定位到具体失败的内核 # retCode=0x31, [vector core exception] # -> 错误原因:向量核异常 # module_type=5, module_name=EZ9999 # -> 错误来源模块

方法4:对比遇错继续模式

如果遇错即停模式难以定位,可临时切换到遇错继续模式,让后续任务继续执行以收集更多信息:

aclrtStream stream; aclrtCreateStream(&stream); // 测试时使用遇错继续模式 aclrtSetStreamFailureMode(stream, ACL_CONTINUE_ON_FAILURE); // 下发多个任务 // ... // 同步并检查错误 aclError error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { printf("Error occurred: %d\n", error); // 遇错继续模式下,可以获取更多信息 // 但注意:aclrtPeekAtLastError可能返回的是最后发生的错误,而非首次错误 aclError lastError = aclrtPeekAtLastError(ACL_RT_THREAD_LEVEL); printf("Last error: %d\n", lastError); char *errMsg = aclGetRecentErrMsg(); printf("Error message: %s\n", errMsg); // 查看哪些任务执行成功,哪些失败 // (需要通过中间结果验证) } // 问题定位后,改回遇错即停模式用于生产环境 aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); aclrtDestroyStream(stream);

方法5:使用Host回调任务进行调试

在关键任务之间插入Host回调函数,记录任务执行进度:

void taskCallback(void *userData) { int *taskId = (int*)userData; printf("Task %d completed successfully\n", *taskId); } // ... aclrtStream stream; aclrtCreateStream(&stream); aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); int taskId1 = 1, taskId2 = 2, taskId3 = 3, taskId4 = 4; // 下发任务并插入回调 aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); aclrtLaunchHostFunc(stream, taskCallback, &taskId1); kernel1<<<8, nullptr, stream>>>(args1); aclrtLaunchHostFunc(stream, taskCallback, &taskId2); kernel2<<<8, nullptr, stream>>>(args2); aclrtLaunchHostFunc(stream, taskCallback, &taskId3); aclrtMemcpyAsync(hostPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); aclrtLaunchHostFunc(stream, taskCallback, &taskId4); // 同步 aclError error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { // 通过回调输出可以知道最后一个成功完成的任务 // 失败的任务就是最后一个成功任务之后的任务 printf("Error occurred after last successful task\n"); } aclrtDestroyStream(stream);

相关 issue

  • Issue #487: ACL Graph捕获阶段错误处理咨询
  • Issue #544: 错误码格式及日志宏使用规范

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

相关文章:

  • 2026 重庆实地探店测评|标杆易奢福新开门店,专业仪器无损鉴宝 - ys韩
  • HDRP Custom Pass实现电影级物体描边:从原理到实战优化
  • FigmaCN中文汉化插件:设计师的终极语言解决方案
  • TAS5414C-Q1与PIC18F87J50芯片对比分析
  • 3步告别键盘连击:KeyboardChatterBlocker 如何成为你的输入守护神
  • 30 岁转行,考 HCIE 还是 RHCE,哪个更容易拿到稳定高薪 offer?
  • 基于NLP的聊天机器人系统
  • Java中的锁
  • 3分钟永久激活:KMS_VL_ALL_AIO全平台激活解决方案实战指南
  • 西安本地文旅出行服务首选西安中旅碑林分公司
  • GIA钻戒估价标准公开!2026年7月北京持证钻石回收机构全城点位汇总 - 分享测评官
  • 焦圈儿Skill正式上线:让AI写出“人味儿“,一句话就够了
  • 在线培训学习平台哪个好?2026年选购指南
  • Hacker News Digest高级技巧:5种方法优化ChatGPT摘要质量
  • Token调用量两年暴涨千倍:AI产业链基础设施重构深度分析
  • Conv-TasNet源码解析:从数据预处理到模型推理的全流程
  • QMK Toolbox:让机械键盘自定义变得前所未有的简单
  • Midjourney海报实战速成:从零到商用级作品的5个不可跳过的提示词工程技巧
  • 选购干货|瑞德医生皮皮乐有无副作用?温和低敏无刺激 - 思溯深度专栏
  • Zotero PDF Translate插件进阶指南:20+翻译引擎深度集成与学术翻译效能优化
  • Privoxy 4.2.0 广告过滤规则实战:5分钟配置提升 80% 网页加载速度
  • CTF Misc 进阶:Python 自定义加密逆向分析实战——py_hide_flag
  • 终极黑苹果SMBIOS生成指南:3步打造完美硬件信息
  • Commander 与其他 Ruby CLI 库对比:Thor、GLI 和 OptionParser 的优缺点分析
  • 2026年红茶品牌综合排行:国内四大红茶品牌代表,从产区、工艺风味客观实测
  • BetterNCM Installer:用Rust重写网易云音乐插件安装体验
  • 小米运动自动刷步数完整指南:5分钟实现微信运动排名第一
  • 思源宋体CN:7种字重的免费商用字体终极指南
  • 2026英语教学APP怎么选?一线教师亲测这3个坑一定要避开
  • 终极指南:如何使用GoldHEN Cheats Manager轻松管理PS4游戏修改