CANN opbase 错误码 EZ0028 深度解析:Tensor Stride 校验失败的定位与修复指南
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
导读
EZ0028(Invalid Argument Tensor Stride)是 CANN opbase 算子库中用于标识"输入/输出 Tensor 的 stride 参数不合法"的预定义算子错误码。当算子实现或 aclnn 接口在参数校验阶段发现某个 Tensor 的实际 stride 与预期值不一致时,框架会通过OP_LOGE_FOR_INVALID_STRIDE宏记录 ERROR 级别日志并上报 EZ0028 错误码。本文从错误信息格式、stride 底层语义、源码级上报链路到实际排查方法,完整讲解该错误码的来龙去脉,帮助算子开发者在开发、调测与用户报障场景中快速定位 stride 参数问题。
一、EZ0028 错误码概览
EZ0028 属于 CANN opbase 算子库预定义错误体系中的 Operator Errors(算子错误)大类,完整错误码清单见 Operator-Errors.md。从源码中的错误码注册表可以确认该错误的完整定义(见 log.cpp):
| 字段 | 值 |
|---|---|
| errClass | Operator Errors |
| errTitle | Invalid_Argument_Tensor_Stride |
| ErrCode | EZ0028 |
| ErrMessage | Parameter %s of %s has incorrect stride %s, it should be %s. |
| Arglist | param_name, op_name, incorrect_stride, correct_stride |
| Solution | Check whether the stride of input/output tensor is correct. |
错误码语义高度聚焦:仅用于 stride 参数与预期不符的场景。与之配套的是同一错误体系下的其他 Tensor 校验错误码,便于开发者按维度区分问题类型:
- EZ0008~EZ0016:Tensor Shape 相关错误;
- EZ0017~EZ0018:Tensor Format 相关错误;
- EZ0019~EZ0021:Tensor Dtype 相关错误;
- EZ0028:Tensor Stride 相关错误。
二、错误信息格式解读
EZ0028 的报错文本由 4 个占位符组成,依次填充输入参数名、算子名或接口名、stride 错误值、stride 正确值:
Parameter %s of %s has incorrect stride %s, it should be %s.官方文档给出的报错示例如下(见 EZ0028-Invalid_Argument_Tensor_Stride.md):
Parameter x of Conv2dv2 has incorrect stride [1, 2, 3, 4], it should be [1, 1, 1, 1].逐字段拆解这条报错:
| 报错片段 | 含义 |
|---|---|
Parameter x | 参数名为x,即报错的输入/输出 Tensor 形参名 |
of Conv2dv2 | 该参数所属的算子名为Conv2dv2(也可能是 aclnn 接口名) |
incorrect stride [1, 2, 3, 4] | 实际传入的 stride 为[1, 2, 3, 4] |
it should be [1, 1, 1, 1] | 预期(正确)的 stride 为[1, 1, 1, 1] |
注意 stride 以列表形式打印,形如[1,1,1,1],方括号内各元素为每个维度的 stride 值,元素个数应与 Tensor 维度数一致。上述示例中,Conv2dv2的输入x期望按紧凑连续内存排布(stride 为全 1),而调用方传入了非连续的[1,2,3,4],从而触发该校验。
三、stride 的底层语义与"正确值"从何而来
要真正理解 EZ0028,需要先厘清 stride 的定义。在 CANN opbase 中,stride(步长)描述 Tensor 逻辑索引到物理内存偏移的映射关系:某一维的 stride 表示沿该维度移动一个单位时,内存地址需要跨越的元素个数。它是张量视图(view)机制的核心元数据,决定了一个 Tensor 是否按连续内存(contiguous)排布,以及能否以非连续方式共享底层存储。
3.1 连续内存 stride 的计算规则
对于形状为[d0, d1, ..., dn-1]的紧凑连续 Tensor,其各维 stride 满足递推关系:
- 最后一维 stride 为 1;
- 第 i 维 stride = 第 i+1 维的 shape × 第 i+1 维的 stride。
opbase 在 shape_utils.cpp 中给出了标准实现ToContiguousStrides:
void ToContiguousStrides(const op::Shape& shape, op::Strides& strides) { strides.assign(shape.GetDimNum(), 1); for (int64_t i = static_cast<int64_t>(shape.GetDimNum() - 2); i >= 0; i--) { strides[i] = shape.GetDim(i + 1) * strides[i + 1]; } }例如形状[2, 3, 4]的连续 stride 为[3*4, 4, 1] = [12, 4, 1]。当实际 stride 与按此规则计算出的结果不一致时,即构成 EZ0028 所描述的"incorrect stride",报错文本中的"correct value"正是预期的连续(或算子约定)stride 值。
3.2 stride 在 aclTensor 中的管理与打印
在框架层,aclTensor 内部通过viewStrides_成员保存视图 stride,并提供GetViewStrides()/SetViewStrides()读写接口(见 common_types.cpp)。当外部显式传入 stride 时,会直接赋值;否则调用ToContiguousStrides生成连续 stride(见 common_types.cpp)。
日志与报错中 stride 列表的打印格式由op::ToString(const op::Strides&)统一生成(见 shape_utils.cpp),它会将 stride 数组格式化为[v0, v1, ..., vn]的字符串,这也是 EZ0028 报错信息中 stride 呈现形式的来源。
四、EZ0028 的源码级上报机制
EZ0028 由算子/接口实现中的参数校验代码显式触发,其上报入口是预定义日志宏OP_LOGE_FOR_INVALID_STRIDE。
4.1 宏原型与参数说明
宏定义位于 log.h,接口说明文档见 OP_LOGE_FOR_INVALID_STRIDE.md:
OP_LOGE_FOR_INVALID_STRIDE(entityName, paramName, incorrectStride, correctStride)| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| entityName | 输入 | 算子名称或 aclnn 接口名称,支持const char*或std::string类型 |
| paramName | 输入 | 参数名称,支持const char*或std::string类型 |
| incorrectStride | 输入 | 实际(错误)stride,格式如"[1,1,1,1]",支持const char*或std::string类型 |
| correctStride | 输入 | 预期(正确)stride,格式如"[1,1,1,1]",支持const char*或std::string类型 |
返回值为空;宏内部通过do { ... } while (0)包裹,可在if分支等场景安全使用。
4.2 宏的内部执行链路
从宏实现可以看到 EZ0028 上报的完整动作(见 log.h):
- 将 4 个入参转换为
std::string安全副本(避免传入临时对象或空指针带来的风险); - 调用
OP_LOGE_LIBOPAPI_REPORT输出ERROR 级别日志,文本为Parameter %s of %s has incorrect stride %s, it should be %s.; - 组装结构化消息键值对
msgKey = {"param_name", "op_name", "incorrect_stride", "correct_stride"},调用REPORT_PREDEFINED_ERR_MSG("EZ0028", msgKey, msgvalue)上报预定义错误码 EZ0028。
其中 EZ0028 的预定义错误信息(含 errClass、errTitle、ErrMessage、Arglist、suggestion)在 log.cpp 的错误码注册表中统一定义,保证日志文本、上报错误码与文档描述三者始终一致。
五、触发场景与常见根因
EZ0028 表明调用方传入的 Tensor stride 与算子约定不符。从源码结构与错误语义推断,常见触发场景包括:
- 显式传入非连续 stride:用户通过 aclnn 接口显式指定 stride 构造张量视图,但该 stride 与算子要求的连续内存排布(或算子约定的 stride 约束)不一致;
- 算子对 stride 有强约束:部分算子(如卷积类算子)要求输入按紧凑连续排布或满足特定对齐要求,非连续输入直接触发校验失败;
- 切片/视图操作后的错误传播:对原始 Tensor 做切片、转置、扩维等操作后生成的视图 stride 不连续,若未经
contiguous()处理直接传入要求连续输入的算子,同样会命中该校验; - strides 与 shape 不匹配:stride 数组长度与维度数不一致,或 stride 数值与 shape 无法对应(例如某维 stride 未满足"该维 stride = 相邻低维 shape 乘积"的连续性条件)。
六、排查与修复方法
根据 EZ0028-Invalid_Argument_Tensor_Stride.md 中的官方解决方法,并结合上述原理,可按以下步骤排查:
- 核对报错中的参数名与算子名:确认是哪个输入/输出 Tensor(如示例中的
x)在校验中失败,缩小排查范围; - 对比实际 stride 与预期 stride:报错中已同时给出
incorrect stride与it should be两组值。若预期值为连续 stride(如[1,1,1,1]),则说明算子要求连续输入; - 检查构造张量的方式:确认 stride 是显式传入还是由切片/视图操作隐式生成;若是视图导致的不连续,需在调用前将张量转换为连续内存排布;
- 确认 stride 与 shape 的一致性:按
ToContiguousStrides的规则(末维为 1、向前累乘)验算实际 stride,定位是哪一维的取值异常; - 修正后重跑:确保实际 stride 与预期完全一致后重新执行,确认报错消失。
6.1 典型的校验代码模式
在实际算子/接口实现中,EZ0028 的触发代码通常遵循"校验失败 → 上报 → 返回失败"的模式。参考 OP_LOGE_FOR_INVALID_STRIDE.md 中的调用示例:
if (!CheckStrideValid(inputStride, expectedStride)) { OP_LOGE_FOR_INVALID_STRIDE("MyOp", "x", StrideToStr(inputStride).c_str(), "[1,1,1,1]"); return ge::GRAPH_FAILED; }这段代码说明了两点使用规范:
- 先校验后上报:只有确认 stride 不合法时才调用宏,避免误报;
- 上报即返回:上报 ERROR 日志与错误码后立即返回失败状态,终止后续执行,防止错误参数继续参与计算。
实际项目中,expectedStride通常由op::ToContiguousStrides根据输入 shape 计算得出,而incorrectStride来自 Tensor 的GetViewStrides(),两相对比即可完成校验,这也与 shape_utils.cpp 中提供的连续 stride 生成接口形成闭环。
七、与其他错误码的区分
EZ0028 与同体系错误码容易混淆,排查时可通过报错关键字快速区分(错误码总览见 Operator-Errors.md):
| 错误码 | 报错关键字 | 问题维度 |
|---|---|---|
| EZ0008~EZ0016 | shape / shape size / shape dim | 张量形状 |
| EZ0017~EZ0018 | format | 张量排布格式 |
| EZ0019~EZ0021 | dtype | 张量数据类型 |
| EZ0024 | incorrect value | 单个参数取值错误 |
| EZ0026 / EZ0027 | incorrect value + reason | 单/多参数取值错误(带原因) |
| EZ0028 | incorrect stride | 张量步长(stride) |
当报错信息中出现 "stride" 关键字且格式为Parameter %s of %s has incorrect stride %s, it should be %s.时,即可确定为 EZ0028,应聚焦 stride 相关的校验逻辑与张量构造方式。
八、小结
EZ0028 是 CANN opbase 算子库中专门标识 Tensor stride 校验失败的预定义错误码,其报错信息同时携带实际值、期望值与归属参数/算子,信息完整、定位路径清晰。理解该错误码的关键在于掌握三件事:stride 的连续内存递推规则(ToContiguousStrides)、上报宏OP_LOGE_FOR_INVALID_STRIDE的使用方式(参数含义与内部日志+错误码双重上报机制),以及"校验失败即上报并返回"的算子实现惯例。开发者收到此类报错时,只需对照报错中的 incorrect/correct 两组 stride 值,检查张量构造与算子约束即可快速收敛问题。
相关文档与源码索引
- 错误码定义文档:EZ0028-Invalid_Argument_Tensor_Stride.md
- 错误码总览:Operator-Errors.md
- 上报宏接口文档:OP_LOGE_FOR_INVALID_STRIDE.md
- 上报宏实现:log.h
- 错误码注册表(EZ0028 定义):log.cpp
- 连续 stride 计算实现:shape_utils.cpp
- stride 在 aclTensor 中的管理与序列化:common_types.cpp
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考