CANN Runtime 可靠性能力实战:Stream 级浮点溢出检测与错误恢复、容错执行专题
2026/9/18 15:14:16 网站建设 项目流程

CANN Runtime 可靠性能力实战:Stream 级浮点溢出检测与错误恢复、容错执行专题

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

本文围绕 CANN Runtime 的可靠性能力展开,以仓库 example/4_reliability 目录为核心线索,深入讲解 Runtime 在溢出检测、错误恢复与容错执行三个维度的能力设计与实践用法。读者将学会如何使用 AscendCL 的 Device 饱和模式管理与 Stream 级溢出检测 API 实现"开关配置—状态查询—状态复位"的完整闭环,并理解如何在异常发生后通过日志诊断、错误码分类与资源重建实现可靠恢复。

Runtime 可靠性能力全景

Runtime 的可靠性能力覆盖程序运行期可能遇到的各类异常场景,仓库将其划分为三个专题(见 example/4_reliability/README_en.md):

专题目录核心能力
溢出检测overflow_detectionStream 级溢出检测开关、状态查询与复位(含可运行示例)
错误恢复error_recovery运行期错误后的恢复、重试与重新初始化
容错执行fault_tolerant容错执行、故障隔离与多设备/多进程场景下的容错设计

其中,溢出检测是唯一提供完整可编译示例的专题,位于 example/4_reliability/overflow_detection/0_overflow_detection,下文以它为主体展开;错误恢复与容错执行作为相关专题在第 6、7 节给出方向性指南。

溢出检测机制:为什么要管理浮点溢出模式

浮点运算出现上溢、下溢或非法结果(如除以零产生 Inf/NaN)时,不同的处理策略直接影响计算结果的可信度与后续执行的稳定性。AscendCL 通过aclrtFloatOverflowMode枚举(定义于 include/external/acl/acl_rt.h)暴露两种显式模式:

typedef enum aclrtFloatOverflowMode { ACL_RT_OVERFLOW_MODE_SATURATION = 0, // 饱和模式:运算结果钳制到最大/最小可表示值 ACL_RT_OVERFLOW_MODE_INFNAN, // Inf/NaN 模式:溢出结果以 Inf/NaN 形式传播 ACL_RT_OVERFLOW_MODE_UNDEF, // 未定义模式(通常作为查询的初始值) } aclrtFloatOverflowMode;
  • 饱和模式(SATURATION):溢出时结果被钳制到该数据类型的最大(或最小)可表示值,避免无效值在后续运算中扩散,适合对结果范围敏感、希望"数值不出界"的场景;
  • Inf/NaN 模式(INFNAN):溢出时保留 Inf/NaN 语义继续传播,适合需要精确追踪异常来源、配合溢出检测做问题定位的场景。

溢出检测开关依赖饱和模式工作,因此示例的执行流程是:先查询当前 Device 的饱和模式,切换到ACL_RT_OVERFLOW_MODE_SATURATION,再使能 Stream 级溢出检测,最后查询并复位溢出状态。

溢出检测核心 API 参考

以下接口均声明于 include/external/acl/acl_rt.h,是溢出检测功能的主干:

API参数说明
aclrtGetDeviceSatModeaclrtFloatOverflowMode* mode(OUT)查询当前 Device 的饱和模式
aclrtSetDeviceSatModeaclrtFloatOverflowMode mode(IN)设置 Device 饱和模式
aclrtSetStreamOverflowSwitchaclrtStream stream(IN)、uint32_t flag(IN,0 关闭 / 1 开启)使能或关闭指定 Stream 上的溢出检测开关
aclrtGetStreamOverflowSwitchaclrtStream stream(IN)、uint32_t* flag(OUT,0 关闭,非 0 开启)查询指定 Stream 的溢出检测开关状态
aclrtGetOverflowStatusvoid* outputAddr(IN/OUT,设备侧状态缓冲区)、size_t outputSize(IN)、aclrtStream stream(IN)异步获取 Stream 的溢出状态
aclrtResetOverflowStatusaclrtStream stream(IN)异步复位 Stream 的溢出状态

关于aclrtGetOverflowStatusaclrtResetOverflowStatus,头文件注释明确要求:二者均为异步接口,调用后必须调用aclrtSynchronizeStream确保 Stream 中的任务执行完成,再读取或继续后续操作。这一点在示例源码中被严格遵守(见 main.cpp)。

此外,aclrtFloatOverflowMode与 Stream 属性也存在关联:ACL_STREAM_ATTR_FLOAT_OVERFLOW_CHECK(枚举值 2,定义于 include/external/acl/acl_rt.h)即流属性体系中与浮点溢出检查对应的属性类型,可通过aclrtSetStreamAttr/aclrtGetStreamAttr体系访问。

示例源码逐步解析

示例入口为 example/4_reliability/overflow_detection/0_overflow_detection/main.cpp,完整流程如下。

第 1 步:环境初始化

依次调用aclInit(nullptr)完成 ACL 初始化、aclrtSetDevice(0)设置 Device、aclrtCreateContext(&context, 0)创建 Context。示例采用 Lambda 表达式封装主体逻辑,并用多个布尔标志(aclInitializeddeviceSetcontextCreated等)跟踪每一步的资源状态,保证任何一步失败后都能精确执行对应的清理动作。

第 2 步:查询并切换饱和模式

aclrtGetDeviceSatMode(&originalMode); // 记录原始模式,供结束时恢复 aclrtSetDeviceSatMode(ACL_RT_OVERFLOW_MODE_SATURATION); aclrtGetDeviceSatMode(&currentMode); // 回读确认 INFO_LOG("Device saturation mode switched from %s to %s.", OverflowModeToString(originalMode), OverflowModeToString(currentMode));

OverflowModeToString将枚举值映射为可读字符串(ACL_RT_OVERFLOW_MODE_SATURATION/ACL_RT_OVERFLOW_MODE_INFNAN/ACL_RT_OVERFLOW_MODE_UNDEF/ACL_RT_OVERFLOW_MODE_UNKNOWN),对应示例输出中的第一行日志。

第 3 步:创建 Stream 并使能溢出检测

aclrtCreateStream(&stream); aclrtSetStreamOverflowSwitch(stream, 1); // 使能溢出检测 aclrtGetStreamOverflowSwitch(stream, &queriedSwitch); INFO_LOG("Overflow switch=%u", queriedSwitch); // 期望输出 1

第 4 步:查询溢出状态并同步到 Host

constexpr size_t kOverflowStatusBufferSize = 64; // 固定 64 字节设备侧状态缓冲 aclrtMalloc(&statusDevice, kOverflowStatusBufferSize, ACL_MEM_MALLOC_HUGE_FIRST); aclrtGetOverflowStatus(statusDevice, kOverflowStatusBufferSize, stream); // 异步查询 aclrtSynchronizeStream(stream); // 等待完成 aclrtMemcpy(statusHost, sizeof(statusHost), statusDevice, kOverflowStatusBufferSize, ACL_MEMCPY_DEVICE_TO_HOST); // 同步回 Host overflowFlag = ReadOverflowFlag(statusHost); // 读取前 4 字节 INFO_LOG("Overflow status before reset=%u", overflowFlag);

ReadOverflowFlag通过std::copy_n将缓冲区前 4 个字节按小端序还原为uint32_t溢出标志。在未发生溢出的正常运行场景下该值为 0。

第 5 步:复位并二次查询

aclrtResetOverflowStatus(stream); aclrtSynchronizeStream(stream); std::fill_n(statusHost, kOverflowStatusBufferSize, 0); // 清空 Host 侧缓冲 aclrtGetOverflowStatus(statusDevice, kOverflowStatusBufferSize, stream); aclrtSynchronizeStream(stream); aclrtMemcpy(statusHost, sizeof(statusHost), statusDevice, kOverflowStatusBufferSize, ACL_MEMCPY_DEVICE_TO_HOST); overflowFlag = ReadOverflowFlag(statusHost); INFO_LOG("Overflow status after reset=%u", overflowFlag);

第 6 步:资源清理与模式恢复

无论主体逻辑成功还是失败,示例都会逆序执行清理:aclrtFree(statusDevice)释放状态缓冲 →aclrtSetDeviceSatMode(originalMode)恢复原始饱和模式 →aclrtDestroyStreamaclrtDestroyContextaclrtResetDeviceForce(deviceId)aclrtFinalize()。每个清理调用都单独检查返回值,任一失败都会将最终结果置为 -1。这种"标志位驱动的分级回滚"是 Runtime 示例中通用的资源管理范式,与 example/utils.h 中CHECK_ERROR/CHECK_ERROR_WITHOUT_RETURN宏配合使用。

构建与运行

环境准备

按 example/README_en.md 完成 CANN 安装后,按以下步骤执行(默认安装目录为/usr/local/Ascend):

# 将 ${install_root} 替换为 CANN 安装根目录 source ${install_root}/cann/set_env.sh export ASCEND_INSTALL_PATH=${install_root}/cann # 构建并运行 bash run.sh

构建细节

run.sh 内部通过source $_ASCEND_INSTALL_PATH/bin/setenv.bash加载编译环境,然后执行 CMake 配置与make,最终直接运行./build/main

CMakeLists.txt 的关键点:

  • include_directories同时加入${ASCEND_CANN_PACKAGE_PATH}/include与示例公共目录(../../..,即 example 根目录,用于引入 example/utils.h);
  • 编译选项-O2 -std=c++17 -D_GLIBCXX_USE_CXX11_ABI=0 -Wall -Werror,其中-D_GLIBCXX_USE_CXX11_ABI=0是 CANN 常见的要求,用于与安装包的 ABI 保持一致;
  • 链接${ASCEND_CANN_PACKAGE_PATH}/lib64/libascendcl.so

预期输出

[INFO] Device saturation mode switched from ACL_RT_OVERFLOW_MODE_INFNAN to ACL_RT_OVERFLOW_MODE_SATURATION. [INFO] Overflow switch=1 [INFO] Overflow status before reset=0 [INFO] Overflow status after reset=0 [INFO] Overflow detection sample finished successfully.

当未发生浮点溢出时,复位前后的溢出状态均为 0。若要观察非 0 的溢出状态,可在使能溢出检测后在 Stream 上启动会产生浮点溢出的算子,再执行查询。

产品支持与已知问题

产品支持情况
Ascend 950PR / Ascend 950DT支持
Atlas A3 训练系列产品 / Atlas A3 推理系列产品支持
Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持

已知问题:aclrtSetStreamOverflowSwitchACL_RT_OVERFLOW_MODE_SATURATIONACL_RT_OVERFLOW_MODE_INFNAN两种模式下均可使用;若当前产品不支持该能力,相关接口可能返回ACL_ERROR_RT_FEATURE_NOT_SUPPORT(错误码 207000,参见 include/external/acl/error_codes/rt_error_codes.h)。示例中的HandleOptionalOverflowRet正是为此设计的:对可选能力接口(饱和模式查询/设置、溢出开关)进行"探测式调用",收到ACL_ERROR_RT_FEATURE_NOT_SUPPORT时打印警告并以 0 退出,收到其他错误码则按致命错误处理,同时保证资源已清理完毕。这种"可选能力降级"写法值得在跨版本、跨产品的应用中复用。

相关专题一:错误恢复与重试

example/4_reliability/error_recovery/README_en.md 给出了错误恢复专题的建议研究路线:

  • 故障后的资源重建与恢复流程:明确哪些资源(Context、Stream、Device 内存)在异常后需要销毁重建,哪些可以保留复用;
  • 错误分类、降级与重试策略:将错误码按可重试(如瞬时性失败)与不可重试(如参数非法、资源耗尽)分类,决定是降级运行还是重试;
  • 结合日志与诊断信息的排障方法:借助 Runtime 错误码与 plog 日志定位设备侧异常根因。

基础错误处理范式的可运行示例见 example/0_quickstart/1_error_handling,其中演示了通过aclGetRecentErrMsg获取最近一次错误的详细描述并结合错误码分支处理的写法,可视为错误恢复专题的入门素材。

相关专题二:容错执行与故障隔离

example/4_reliability/fault_tolerant/README_en.md 聚焦以下方向:

  • 任务失败后的隔离与恢复:单个算子/模型任务失败时,如何将故障限制在局部而不影响同进程内的其他任务;
  • 多设备或多进程场景下的容错设计:跨设备、跨进程协作时,某一方失败后的状态一致性与同步策略;
  • 诊断、重试与降级的协同设计:将检测到的问题按严重程度分层处理,形成完整的可靠性闭环。

该专题与错误恢复专题相互衔接(错误恢复解决"失败后怎么办",容错解决"如何设计得不那么容易失败、失败后如何隔离")。

参考资料

  • example/4_reliability/README_en.md:可靠性能力示例总览
  • example/4_reliability/overflow_detection/0_overflow_detection/README_en.md:溢出检测示例说明
  • example/4_reliability/overflow_detection/0_overflow_detection/main.cpp:溢出检测示例源码
  • include/external/acl/acl_rt.h:溢出检测相关 API 与枚举定义
  • include/external/acl/error_codes/rt_error_codes.h:Runtime 错误码定义
  • example/utils.h:示例公共错误处理宏

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

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询