Closed
aclnnCalculateMatmulWeightSizeV2 对不支持的 dtype(FLOAT/INT32/BOOL)未拦截,返回按 4 字节推算的 512 而非 161002 #3939
liuhanwen8Add on  16 days agoClosed at  8 days ago
liuhanwen8
liuhanwen8
16 days ago Create

aclnnCalculateMatmulWeightSizeV2 对不支持的数据类型未拦截,返回按 4 字节推算的占位大小

1. 环境

  • 硬件:Ascend 910B2(A2),单卡
  • CANN:9.2.0(商用发布包,ops 包 9.2.0)
  • 驱动/固件:npu-smi 26.1.1
  • 调用方式:aclnn 单算子直调(C++ 两段式无关,本接口是单段式 host 接口)

2. 现象

资料 aclnnCalculateMatmulWeightSizeV2 参数表写明 dataType 只支持 FLOAT16、BFLOAT16、INT8,
错误码表 161002 覆盖「输入的数据类型不满足要求」。

实测传入 ACL_FLOAT / ACL_INT32 / ACL_BOOL 时接口返回 0(成功),并给出 weightTensorSize=512,
而不是返回 161002。512 恰好等于「按 4 字节 itemsize 取 C0=32」推算出的元素个数,说明非法 dtype
被当成 4 字节类型静默参与计算。

同一组输入下,aclnnCalculateMatmulWeightSize(V1,无 dtype 形参)恒返回 256,
与 V2 的 512 不一致,调用方无法判断该信哪个。

3. 复现步骤

  1. source CANN 的 set_env.sh;
  2. 编译并运行下面的 repro_calc;
  3. 观察 6 行输出。

4. 复现代码

#include <cstdio>
#include <cstdint>
#include "acl/acl.h"
#include "aclnnop/aclnn_trans_matmul_weight.h"

static void run(aclDataType dt, const char *name)
{
    int64_t shape[2] = {16, 16};
    aclIntArray *arr = aclCreateIntArray(shape, 2);
    uint64_t size = 0;
    aclnnStatus rc = aclnnCalculateMatmulWeightSizeV2(arr, dt, &size);
    printf("%-8s rc=%d size=%llu\n", name, (int)rc, (unsigned long long)size);
    aclDestroyIntArray(arr);
}

int main()
{
    aclInit(nullptr);
    aclrtSetDevice(0);
    run(ACL_FLOAT16, "fp16");   // 资料声明支持
    run(ACL_BF16, "bf16");      // 资料声明支持
    run(ACL_INT8, "int8");      // 资料声明支持
    run(ACL_FLOAT, "fp32");     // 资料未声明 → 期望 161002
    run(ACL_INT32, "int32");    // 资料未声明 → 期望 161002
    run(ACL_BOOL, "bool");      // 资料未声明 → 期望 161002
    aclrtResetDevice(0);
    aclFinalize();
    return 0;
}

编译:g++ -O0 -o repro_calc repro_calc.cpp -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 -lopapi -lnnopbase -lascendcl

5. 期望结果

fp16     rc=0 size=256
bf16     rc=0 size=256
int8     rc=0 size=512
fp32     rc=161002 size=0
int32    rc=161002 size=0
bool     rc=161002 size=0

6. 实际结果

fp16     rc=0 size=256
bf16     rc=0 size=256
int8     rc=0 size=512
fp32     rc=0 size=512
int32    rc=0 size=512
bool     rc=0 size=512

三台 910B2 机器(CANN 9.2.0)结果一致,可稳定复现。

7. 影响与建议

该接口的返回值被调用方直接用来申请 weight 张量空间(常见写法是
aclnnCalculateMatmulWeightSizeV2(...) → aclrtMalloc(size * itemsize))。
非法 dtype 被静默受理后,调用方拿到一个「看起来合理」的元素个数,
把 fp32 权重按 2 字节类的块布局去申请和填充,后续 aclnnTransMatmulWeight
或 matmul 侧就会按错误的存储布局读写,属于静默错误配置而非立即报错,排查成本高。

建议:

  1. 在 aclnnCalculateMatmulWeightSizeV2 入口按资料声明的白名单校验 dataType,
    不在 {FLOAT16, BFLOAT16, INT8} 内时返回 ACLNN_ERR_PARAM_INVALID(161002);
  2. 若产品上确实打算支持更多 dtype,请同步更新资料的支持面与错误码描述(二者取其一,
    但不要「文档说不支持、实现按兜底值算」)。
likedislike
liuhanwen8liuhanwen8
16 days ago Added label: bug-report
陈思
陈思Collaborators
15 days ago Comments:

您好,感谢反馈!

问题分析

在本次读取的 cann/ops-math@a11d8785 中,aclnnCalculateMatmulWeightSizeV2 确实没有检查 dataType:完成 SoC、指针和 shape 检查后直接计算并返回成功。资料限定 FLOAT16、BFLOAT16、INT8,并把类型不满足要求列为 161002,两者存在校验缺口。V2 实现、资料约束。这是源码核查结论,尚未核对您商用 9.2.0 包的具体源码对应关系。

其中 512 的来源需要澄清:计算函数将 FLOAT16/BFLOAT16 以外的类型全部放进 INT8 对齐分支,对 [16,16] 计算 Align(16,16)×Align(16,32)=512;这里返回的是元素个数,没有按 dtype 的字节宽度计算。V1 固定传入 FLOAT16,因而得到 256,合法 INT8 在 V2 中得到 512 本身是预期差异。计算与 V1 调用、容量单位与公式。

此外,aclnnTransMatmulWeight 有独立的类型校验,该版本的支持列表不含 FLOAT、INT32、BOOL。因此,容量接口误返回成功可以确认,但不能据此断言后续转换一定发生错误读写。下游类型列表、下游校验。

处理方向

一个可行方向是在 V2 写入容量之前,按该接口正式支持的数据类型和产品范围增加明确校验,不支持时返回 161002,同时保留合法类型的对齐规则和元素单位。若扩大类型支持,则需匹配容量规则、后续转换能力和资料,不能仅凭当前兜底分支视为已支持。

调用方应在返回成功后使用容量;错误时输出是否统一归零也需单独明确约定。我们会继续确认入口校验与支持契约的对齐方式。

likedislike
陈思陈思Collaborators
15 days ago Assign chen_0715 as responsible person
陈思陈思Collaborators
15 days ago Added label: pending-confirmation
陈思陈思Collaborators
15 days ago Removed label: pending-confirmation
CchenyifengCollaborators
14 days ago Assign Anthony0331 as responsible person
CchenyifengCollaborators
14 days ago Removed responsible person chen_0715
yyt_hwyyt_hwCollaborators
14 days ago Associated pull request
MetastarxMetastarx
9 days ago Associated pull request
yyt_hwyyt_hwCollaborators
8 days ago changed custom state from 进行中 to 已完成
yyt_hwyyt_hwCollaborators
8 days ago Close issue