算子执行输出全0的常见原因排查
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
问题现象描述
现象1:执行算子后输出数据全为0
执行算子时,算子输入数据正确,但输出数据异常,全为0。
报错日志示例如下:
[ERROR] RUNTIME(2082291,python3):2024-07-04-14:14:25.036.721 [stars_engine.cc:1321]2082291 ProcLogicCqReport:[INIT][DEFAULT]Task run failed, device_id=0, stream_id=2, task_id=1, sqe_type=0(ffts), errType=0x1(task exception), sqSwStatus=0 [ERROR] RUNTIME(2082291,python3):2024-07-04-14:14:25.050.365 [davinic_kernel_task.cc:1219]2082291 PreCheckTaskErr:[INIT][DEFAULT]Kernel task happen error, retCode=0x31, [vector core exception]. [ERROR] RUNTIME(2082291,python3):2024-07-04-14:14:25.050.517 [stream.cc:1082]2082291 GetError:[INIT][DEFAULT]AIV Kernel happen error, retCode=0x31. [ERROR] RUNTIME(2082291,python3):2024-07-04-14:14:25.051.013 [davinic_kernel_task.cc:1082]2082291 GetArgsInfo:[INIT][DEFAULT][AIC_INFO] args(0 to 9) after execute:0, 0, 0, 0, 0, 0, 0, 0, 0可能原因
内存未初始化:输出内存未正确初始化或清零,导致读取到未初始化的数据(通常为0)。
数据类型不匹配:算子输入输出数据类型配置错误,例如float32与float16混用,导致数据解析错误。
内存拷贝失败:Host与Device之间的内存拷贝操作失败或未执行,导致Device侧内存为初始值(0)。
内核编译或执行异常:
- 低版本内核(5.10以下)使用asan工具导致执行异常。
- 算子编译选项不正确。
- 内核启动参数配置错误。
地址访问越界:算子访问了非法内存地址,触发Device侧异常。
处理步骤
排查步骤1:检查内存初始化
确保输出内存已正确分配和初始化:
// 检查内存分配是否成功 void *devPtr = nullptr; size_t devSize = 1024 * 1024; // 1MB aclError error = aclrtMalloc(&devPtr, devSize, ACL_MEM_MALLOC_HUGE_FIRST); if (error != ACL_RT_SUCCESS || devPtr == nullptr) { printf("Memory allocation failed\n"); return error; } // 初始化内存为特定值(非0)用于验证 error = aclrtMemset(devPtr, devSize, 0xFF, devSize); if (error != ACL_RT_SUCCESS) { printf("Memory initialization failed\n"); aclrtFree(devPtr); return error; } // 执行算子... // 执行后检查输出,如果仍为0xFF说明算子未写入 // 如果为0说明算子写入但数据异常排查步骤2:验证数据类型匹配
确保算子输入输出数据类型一致:
// 检查tensor描述符的数据类型 aclDataType inputType, outputType; aclGetTensorDescType(inputDesc, &inputType); aclGetTensorDescType(outputDesc, &outputType); if (inputType != outputType) { printf("Warning: Input type %d != Output type %d\n", inputType, outputType); } // 确认数据格式(ND、NCHW等)匹配 aclFormat inputFormat, outputFormat; aclGetTensorDescFormat(inputDesc, &inputFormat); aclGetTensorDescFormat(outputDesc, &outputFormat); printf("Input format: %d, Output format: %d\n", inputFormat, outputFormat);排查步骤3:检查内存拷贝操作
验证Host与Device之间的数据传输是否成功:
// Host -> Device拷贝 aclError error = aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); if (error != ACL_RT_SUCCESS) { printf("Host to Device copy failed: %d\n", error); return error; } // 确保拷贝完成 error = aclrtSynchronizeStream(stream); if (error != ACL_RT_SUCCESS) { printf("Synchronize failed after H2D copy: %d\n", error); return error; } // 可选:拷贝回Host验证数据是否正确传输 error = aclrtMemcpyAsync(hostVerifyPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); error = aclrtSynchronizeStream(stream); // 比较hostPtr和hostVerifyPtr的数据是否一致排查步骤4:分析plog日志定位异常
通过plog日志中的错误码和异常信息定位问题:
# 查找关键错误信息 grep -i "error\|exception\|failed" plog.log # 定位错误内核 grep "fault kernel_name" plog.log # 示例输出:fault kernel_name=Add_ee98c6628030785f610b924ab1557b31相关 issue
- Issue #480: aicore异常报错导致算子执行失败
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考