您好,感谢反馈!
问题分析
核对 cann/ops-math 固定版本 8c1f633e3679,可以确认返回码与接口资料存在不一致:两个接口均约定 other 为空时返回 ACLNN_ERR_PARAM_NULLPTR(161001)。
在 aclnn_fmod_scalar.cpp 的 GetWorkspaceSizeCommon 中,原始 aclScalar* other 在 ConvertToTensor 前被显式判空,但该分支返回的是 ACLNN_ERR_INNER_NULLPTR(561103)。后续 CheckParams 检查 self、转换后的标量 Tensor 和 out 时,空指针才按 161001 处理。这解释了您报告的 other 与 self/out 返回码差异;该路径在 host 侧参数检查阶段即返回,尚未进入 Mod 计算。
aclnnFmodScalarGetWorkspaceSize 和 aclnnInplaceFmodScalarGetWorkspaceSize 都直接返回这个公共函数的结果,因此两个接口同时受影响。当前完成的是源码核查,报告中的设备运行结果尚未由我们独立复测。
处理方向
一个可行的最小调整是在公共函数中,将原始 other 判空分支的返回码改为 ACLNN_ERR_PARAM_NULLPTR,继续在解引用和转换前拦截空指针。紧随其后的 otherTensor == nullptr 表示非空 scalar 的内部转换结果异常,仍应保留内部错误码,避免混淆调用方参数错误与内部失败。
该调整可同时覆盖普通和原地接口;验证重点是两接口 other=nullptr 的返回码,以及已有 self/out/selfRef 空指针和合法调用的行为。我们会继续跟踪这一返回码差异。


一、问题描述 (必填)
aclnnFmodScalarGetWorkspaceSize/aclnnInplaceFmodScalarGetWorkspaceSize在other(aclScalar)传空指针时返回 561103(ACLNN_ERR_INNER_NULLPTR,内部错误),而本接口资料错误码表明确声明该场景应返回 161001(ACLNN_ERR_PARAM_NULLPTR,参数错误)。同一错误码表条目下的
self/out空指针确实返回 161001,三个形参处理口径不一致。资料原文(
math/mod/docs/aclnnFmodScalar&aclnnInplaceFmodScalar.md)aclnnFmodScalar段(L174-178):aclnnInplaceFmodScalar段(L330-333)同型:实测结果
self空指针out空指针other空指针(aclnnFmodScalar)other空指针(aclnnInplaceFmodScalar)other空指针重跑 5 次复现率 5/5;阴性对照(合法基线返回 0、
self/out空指针返回 161001)均成立,可排除构造问题。错误码常量对照(CANN 9.2.0
include/aclnn/opdev/op_errno.h现抄)#define ACLNN_ERR_PARAM_NULLPTR 161001 #define ACLNN_ERR_PARAM_INVALID 161002 #define ACLNN_ERR_INNER_NULLPTR 561103代码定位
math/mod/op_api/aclnn_fmod_scalar.cpp:199-202// 将other scalar转换为tensor CHECK_RET(other != nullptr, ACLNN_ERR_INNER_NULLPTR); // ← other 判空用内部错误码 auto otherTensor = uniqueExecutor.get()->ConvertToTensor(other, other->GetDataType()); CHECK_RET(otherTensor != nullptr, ACLNN_ERR_INNER_NULLPTR);而
self/out的判空走CheckNotNull()→CheckParams()→ACLNN_ERR_PARAM_NULLPTR(同文件:49-56、:175-190)。根因:
other(aclScalar)的判空被放在GetWorkspaceSizeCommon里、早于CheckParams,且返回内部错误码;self/out的判空在CheckParams内、返回参数错误码。两处口径分裂。aclnnInplaceFmodScalarGetWorkspaceSize与 out-of-place 版共用GetWorkspaceSizeCommon(:265-270→:192),因此两个接口同时受影响。影响
if (ret == ACLNN_ERR_PARAM_NULLPTR)处理空指针入参时会漏判;CheckParams执行,导致「self非法 +other为空」的组合也被这个内部错误码抢先拦截,进一步放大影响面。二、环境信息 (可选)
npu-smi26.1.1 显示910B3,8 die)/usr/local/Ascend/cann-9.2.0)libopapi_math.so提供aclnnFmodScalar符号;该 SoC 走 CANN 内置ops_legacy的 Mod 实现,本问题属 aclnn 接口层(host 侧)行为,与 kernel 版本无关cann/ops-mathmasterd8fc7a6三、重现步骤 (可选)
自包含 C++ 复现(两段式接口直调,一场景一进程),完整代码如下:
// build: // g++ -O2 -std=c++17 repro.cpp -o fmod_repro \ // -I/usr/local/Ascend/cann-9.2.0/include \ // -L/usr/local/Ascend/cann-9.2.0/aarch64-linux/lib64 \ // -lascendcl -lnnopbase -lopapi_math -lopapi // run: // source /usr/local/Ascend/ascend-toolkit/set_env.sh // export LD_LIBRARY_PATH=/usr/local/Ascend/cann-9.2.0/aarch64-linux/lib64:$LD_LIBRARY_PATH // ./fmod_repro other_null # -> 561103(异常) // ./fmod_repro self_null # -> 161001(对照) // ./fmod_repro out_null # -> 161001(对照) // ./fmod_repro ok # -> 0 (阴性对照) #include <cstdio> #include <cstdlib> #include <cstring> #include <cstdint> #include <vector> #include <unistd.h> #include "acl/acl.h" #include "aclnnop/aclnn_fmod_scalar.h" int main(int argc, char** argv) { setvbuf(stdout, nullptr, _IONBF, 0); const char* sc = (argc > 1) ? argv[1] : "ok"; int32_t dev = 0; const char* e = getenv("FMOD_DEV"); if (e != nullptr) dev = atoi(e); bool inplace = (getenv("FMOD_OP") != nullptr && strcmp(getenv("FMOD_OP"), "inplace") == 0); aclInit(nullptr); if (aclrtSetDevice(dev) != ACL_SUCCESS) { printf("SetDevice(%d) failed\n", dev); return 11; } aclrtStream stream = nullptr; aclrtCreateStream(&stream); std::vector<int64_t> sh = {4, 2}; std::vector<int64_t> sd = {2, 1}; int64_t n = 8; std::vector<float> host((size_t)n, 0.0f); for (int64_t i = 0; i < n; i++) host[(size_t)i] = (float)(i * 7 + 3); void* dS = nullptr; void* dO = nullptr; aclrtMalloc(&dS, (size_t)(n * 4), ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(&dO, (size_t)(n * 4), ACL_MEM_MALLOC_HUGE_FIRST); aclrtMemcpy(dS, (size_t)(n * 4), host.data(), (size_t)(n * 4), ACL_MEMCPY_HOST_TO_DEVICE); aclTensor* self = aclCreateTensor(sh.data(), 2, ACL_FLOAT, sd.data(), 0, ACL_FORMAT_ND, sh.data(), 2, dS); aclTensor* out = aclCreateTensor(sh.data(), 2, ACL_FLOAT, sd.data(), 0, ACL_FORMAT_ND, sh.data(), 2, dO); float otherVal = 3.0f; aclScalar* other = aclCreateScalar(&otherVal, ACL_FLOAT); if (strcmp(sc, "self_null") == 0) self = nullptr; if (strcmp(sc, "other_null") == 0) other = nullptr; if (strcmp(sc, "out_null") == 0) out = nullptr; uint64_t ws = 0; aclOpExecutor* exec = nullptr; aclnnStatus r1 = inplace ? aclnnInplaceFmodScalarGetWorkspaceSize(self, other, &ws, &exec) : aclnnFmodScalarGetWorkspaceSize(self, other, out, &ws, &exec); printf("scenario=%s op=%s GetWorkspaceSize = %d\n", sc, inplace ? "inplace" : "outofplace", (int)r1); int r2 = -999; if (r1 == 0) { void* w = nullptr; if (ws > 0) aclrtMalloc(&w, ws, ACL_MEM_MALLOC_HUGE_FIRST); r2 = (int)(inplace ? aclnnInplaceFmodScalar(w, ws, exec, stream) : aclnnFmodScalar(w, ws, exec, stream)); aclrtSynchronizeStream(stream); printf("scenario=%s Execute = %d\n", sc, r2); if (w) aclrtFree(w); } fflush(stdout); _exit(0); }实测输出(Ascend 910B3 / CANN 9.2.0):
重复 5 次,
other_null恒为 561103。四、预期结果 (可选)
other传空指针时返回 161001(ACLNN_ERR_PARAM_NULLPTR),与资料错误码表及self/out的现有行为保持一致。建议修复(
math/mod/op_api/aclnn_fmod_scalar.cpp:200):- CHECK_RET(other != nullptr, ACLNN_ERR_INNER_NULLPTR); + CHECK_RET(other != nullptr, ACLNN_ERR_PARAM_NULLPTR);或将 scalar 判空并入
CheckNotNull并统一使用ACLNN_ERR_PARAM_NULLPTR。因两个接口共用GetWorkspaceSizeCommon,一处修改即可同时修复aclnnFmodScalar与aclnnInplaceFmodScalar。💡 备注(选填)
同类先例(本仓已受理的同类「空指针/非法入参返回 561103 而非 161001/161002」问题),可见这不是孤例,而是同一类错误码口径分裂:
aclnnBitwiseNotself 传空指针返回 561103,资料声明 161001aclnnDiagFlat空指针返回 561103,资料声明 161001aclnnLinspace出参空指针返回 561103,资料声明 161001aclnnLtScalar/aclnnInplaceLtScalar空指针入参返回 561103,资料声明 161001aclnnBitwiseOrScalarout dtype 不支持返回 561103,资料声明 161002查重说明:已翻查
cann/ops-math全部 1200 条 issue,aclnnFmodScalar相关仅有 #4149(头文件公式用 floor 与资料 trunc 不符),属不同问题(那条是文档公式口径,本单是接口层返回码),不重复。本次挖掘已核对一致的项(同批排查,非本单内容,供参考排除范围):8 种 dtype(DOUBLE/BFLOAT16/FLOAT16/FLOAT32/INT32/INT64/INT8/UINT8)全部可用且数值正确;rank 0-8 边界(rank9 正确返回 161002);
outshape 与 self 不一致(返回 161002);self为 int16/bool/complex64 等不在支持面(返回 161002);空 tensor(返回 0);NaN/±inf/除零特殊值行为符合 IEEE-754;多线程 4 线程 × 100 次并发调用 0 失败。