CANN Runtime 中 AUTO_USE_UC_MEMORY 环境变量详解:算子数据搬移绕过 L2 Cache 的试验特性
2026/9/18 4:16:17 网站建设 项目流程

CANN Runtime 中 AUTO_USE_UC_MEMORY 环境变量详解:算子数据搬移绕过 L2 Cache 的试验特性

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

本文以 CANN Runtime 的环境变量文档 AUTO_USE_UC_MEMORY 为主体,完整讲解该变量的取值语义、默认行为与使用约束,并结合仓库源码(acl.cpp)还原它在aclInit初始化流程中的真实生效路径:从环境变量解析、内核启动填充函数(kernel launch fill function)注册,到向算子写入 L2 Cache 偏移。读完本文,你可以准确判断该变量是否适用于你的芯片型号,理解"默认开启、置 0 关闭"的行为,并知道如何在日志与单元测试层面验证配置是否生效。

功能描述:控制系统是否允许算子搬移数据不经过 L2 Cache

AUTO_USE_UC_MEMORY控制系统是否允许算子搬移数据不经过 L2 Cache。这是该变量的核心语义:开启后,部分算子的数据搬移路径可以绕过 L2 Cache,从而降低访存延迟、提升部分算子的执行性能。

官方文档给出了明确的取值定义:

取值含义
0或其他值否。所有算子搬移数据都必须经过 L2 Cache
1是。允许算子搬移数据可以不经过 L2 Cache,具体是否经过 L2 Cache,由算子 Kernel 代码中的逻辑决定。默认值为 1

这里有两点需要注意:

  • 默认即开启:该变量未设置时行为等同于1。如果想强制"所有数据搬移必须走 L2 Cache",需要显式设置AUTO_USE_UC_MEMORY=0
  • 绕过 L2 Cache 是"允许"而非"强制":配置为1后,是否真正绕过 L2 Cache 由算子自身的 Kernel 逻辑决定,因此它是算子与运行时之间的一个协商开关,而不是对数据路径的硬性改写。

同时,官方文档明确提示了收益与风险:

配置为 1 后,部分算子性能可得到提升,但可能存在AI Core Error 风险

须知:本环境变量为试验特性,后续版本可能会存在变更,不支持应用于生产环境中。

这意味着在正式生产部署前,应在目标硬件上用自身模型充分验证正确性与稳定性,不要仅凭性能提升就把它当作生产配置。

配置示例

在启动业务进程前设置环境变量即可关闭该特性:

export AUTO_USE_UC_MEMORY=0

由于默认值即为1,因此该命令的典型用途是"显式关闭"。若环境未设置该变量,行为与AUTO_USE_UC_MEMORY=1一致。

使用约束:仅在 aclInit 初始化时读取

文档给出的使用约束是:在调用aclInit接口初始化时,会触发读取该环境变量。换言之:

  • 必须在进程完成 ACL 初始化之前设置好该变量,运行中修改环境变量不会改变已初始化 Runtime 的行为;
  • 变量只影响初始化阶段的内部配置注册,后续 Kernel 的执行路径变化由算子侧决定。

支持的型号

文档按 NPU 型号声明了适用范围:

NPU 型号支持的产品系列
310pAtlas 推理系列产品
910bAtlas A2 训练系列产品 / Atlas A2 推理系列产品
A3Atlas A3 训练系列产品 / Atlas A3 推理系列产品

如果你的硬件不在此范围内,即使设置了该变量也可能不产生预期效果——这一点与源码中的"特性不支持"分支相互印证(见下文)。

源码级实现解析:从环境变量到 L2 Cache 偏移写入

以下实现细节均来自仓库源码,可作为文档描述的落地证据。

环境变量的枚举注册

变量名与内部枚举 ID 的映射定义在两处:

  • 枚举MM_ENV_AUTO_USE_UC_MEMORY = 10000,位于 mmpa_env_define.h,归入 ACL 分组;
  • 枚举 ID 与环境变量字符串"AUTO_USE_UC_MEMORY"的对照表位于 mmpa_linux_env.c。

读取时使用的MM_SYS_GET_ENV宏定义在 mmpa_linux.h:它优先调用可注入的mmSysGetEnv,否则直接根据枚举名去掉MM_ENV_前缀后调用getenv。这也解释了为什么aclInit时设置环境变量即可被读到,以及为什么在可测试场景下可以通过注入回调来模拟不同的环境变量值。

解析逻辑:未设置、空串、首字符为 '1' 均视为开启

解析函数acl::IsEnableAutoUCMemeory()位于 acl.cpp:

bool IsEnableAutoUCMemeory() { const char_t* autoUcMemory = nullptr; MM_SYS_GET_ENV(MM_ENV_AUTO_USE_UC_MEMORY, autoUcMemory); // enable: env does not exist or set to 1 const bool enable = ((autoUcMemory == nullptr) || (strlen(autoUcMemory) == 0UL) || (autoUcMemory[0] == '1')); ACL_LOG_INFO("auto-uc-memory is %s.", enable ? "enabled" : "disabled"); return enable; }

可以归纳出三点行为:

  1. 环境变量不存在autoUcMemory == nullptr)→ 开启,与"默认值为 1"的文档描述一致;
  2. 变量为空串→ 同样视为开启;
  3. 首字符为'1'→ 开启;其他任何取值(包括02等)→ 关闭,与文档"0或其他值"的语义完全吻合。

初始化时日志会输出auto-uc-memory is enabled/disabled,可作为配置是否被读取的快速验证手段。

aclInit 阶段:注册内核启动填充函数

aclInit的实现中(acl.cpp),只有IsEnableAutoUCMemeory()返回 true 时,才会通过rtRegKernelLaunchFillFunc注册一个名为"g_opSystemRunCfg"的回调:

// register kernel launch fill function if (acl::IsEnableAutoUCMemeory()) { ACL_LOG_INFO("register kernel launch fill function in aclInit"); const auto rtRegErr = rtRegKernelLaunchFillFunc("g_opSystemRunCfg", acl::UpdateOpSystemRunCfg); if (rtRegErr != RT_ERROR_NONE) { if (rtRegErr == ACL_ERROR_RT_FEATURE_NOT_SUPPORT) { ACL_LOG_WARN("Cannot register kernel launch fill function, feature is not supported."); } else { ... return ACL_GET_ERRCODE_RTS(rtRegErr); } } }

这里有一个值得注意的容错设计:若底层返回ACL_ERROR_RT_FEATURE_NOT_SUPPORT(特性不支持),仅打印WARN日志而aclInit失败;其他错误则向上返回初始化失败。从源码结构看,这正对应了"支持的型号"清单之外的硬件——变量可以被设置,但不受支持的芯片上该特性会被静默跳过,不会导致进程启动失败。

回调本体:把 L2 Cache 偏移写进算子运行配置

回调函数acl::UpdateOpSystemRunCfg(acl.cpp)是"允许绕过 L2 Cache"这一能力真正落地的地方。它在 Kernel 启动时被调用,核心流程是:

  1. 校验入参:cfgAddr非空、cfgLen >= sizeof(size_t),否则返回ACL_ERROR_RT_PARAM_INVALID
  2. 通过rtGetDevice获取当前 device id;
  3. 调用rtGetL2CacheOffset(devId, &offset)查询该设备的L2 Cache 偏移地址;该调用若返回特性不支持,则降级为 WARN;
  4. 将查询到的偏移值写入算子的系统运行配置缓冲(*addr = offset)。
uint64_t* addr = static_cast<uint64_t*>(cfgAddr); *addr = offset; ACL_LOG_INFO("execute UpdateOpSystemRunCfg successfully, l2 cache offset is %lu, device id = %d", offset, devId);

也就是说,Runtime 向算子交付的是"该设备上 L2 Cache 的地址偏移"这类系统信息,算子 Kernel 侧据此判断数据搬移是否可以直接绕过 L2 Cache 进行——这与文档中"具体是否经过 L2 Cache,由算子 Kernel 代码中的逻辑决定"的描述一致。

aclFinalize 阶段:对称地注销回调

aclFinalize中(acl.cpp),若该特性处于开启状态,会调用rtUnRegKernelLaunchFillFunc("g_opSystemRunCfg")注销回调,处理ACL_ERROR_RT_FEATURE_NOT_SUPPORT的方式与初始化时相同(WARN 而非失败)。注册与注销严格对称,避免跨aclInit/aclFinalize生命周期泄漏回调状态。

单元测试中的验证线索

Runtime 侧的单元测试 rt_utest_profileapi.cc(以及 910B 平台版本)直接使用了相同的回调名g_opSystemRunCfg验证注册、查找与注销的完整生命周期,包括注册后callbackMap_中存在该 key、注销后不再存在等断言。这说明该回调机制是 Runtime 的公开能力之一,而非一次性临时逻辑,也表明g_opSystemRunCfg这个键名在不同平台(含 910B)的测试中被一致使用。

小结与使用建议

  • 默认行为:不设置AUTO_USE_UC_MEMORY时等同于1(开启);显式export AUTO_USE_UC_MEMORY=0可强制所有算子数据搬移经过 L2 Cache。
  • 生效时机:仅在aclInit时读取一次,须在初始化前设置;可通过日志auto-uc-memory is enabled/disabled确认实际生效值。
  • 适用边界:文档声明其为试验特性,可能随版本变更,不建议用于生产环境;支持 Atlas 推理系列(310p)、Atlas A2(910b)、Atlas A3(A3)系列产品,从源码结构看不受支持的芯片上注册回调会降级为 WARN 且不阻断初始化。
  • 权衡:开启后部分算子性能可能提升,但存在 AI Core Error 风险,启用前建议先在目标硬件上完成正确性与稳定性验证。

如需进一步理解该变量在整个 Runtime 环境变量体系中的位置,可参考环境变量总览 env_vars/README。

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

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

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

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

立即咨询