CANN/runtime遇错即停错误定位

发布时间:2026/7/11 11:25:19
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); kernel18, nullptr, stream(args1); kernel28, 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失败 // 失败原因是什么 }可能原因任务序列较长Stream上下发了多个异步任务错误发生后无法直观判断是哪个任务失败。错误信息不够详细仅通过返回码无法获知具体失败原因需要结合plog日志和错误查询接口。遇错即停特性限制遇错即停模式会在首个错误发生时停止Context中所有Stream的任务执行可能影响错误现场的保护。处理步骤方法1分段同步定位错误任务将长任务序列分解为多个小段每段后进行同步检查aclrtStream stream; aclrtCreateStream(stream); aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); // 任务1Host - 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; } // 任务2kernel1执行 kernel18, 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; } // 任务3kernel2执行 kernel28, 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; } // 任务4Device - 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); // 标记拷贝任务完成 kernel18, nullptr, stream(args1); aclrtRecordEvent(event2, stream); // 标记kernel1完成 kernel28, 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_id0, stream_id2, task_id1 # - 定位到具体的设备、流、任务ID # fault kernel_nameAdd_ee98c6628030785f610b924ab1557b31 # - 定位到具体失败的内核 # retCode0x31, [vector core exception] # - 错误原因向量核异常 # module_type5, module_nameEZ9999 # - 错误来源模块方法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); kernel18, nullptr, stream(args1); aclrtLaunchHostFunc(stream, taskCallback, taskId2); kernel28, 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);相关 issueIssue #487: ACL Graph捕获阶段错误处理咨询Issue #544: 错误码格式及日志宏使用规范【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考