您好,感谢提供 sorted 两种取值的对照。资料“仅支持 True”与您观察到 false 被接受之间,确实需要明确支持口径;但这组结果还不能证明 false 被全局忽略或始终等价于 true。
语义与源码核查
“无需保证排序”不等于“输出必须无序”,也不等于“按原始出现顺序输出”。对迁移自 PyTorch 的场景,官方 topk 说明只在 sorted=True 时保证结果有序,并明确等值元素的索引不保证稳定。因此不能依赖 sorted=False 保持原始顺序;下游应使用返回的 values/indices 配对关系,而非自行假设顺序。
按您给出的 584b2ea6cbaeba684a51a74296d82d4d50ab3b0f 核查,L0 Topk确实将 sorted 作为属性传给 TopKV2,并未统一改成 true。本例 A2、FLOAT、小尾轴选择常规 AiCore 路径;其他类型和大形状还有 RadixTopK 分流,其中超 INT32 索引范围的选择条件明确依赖 !sorted。所以不能把一组小形状的有序输出推广成所有后端都按 true 处理。
当前固定版本仓内未定位到报告提及的公开 aclnn_topk.cpp 包装,商用库入口与具体 kernel 对 false 的行为仍需核对;以上不代表已独立设备复验。
对齐方向
建议先确认各支持平台、类型和算法的 sorted 契约。若采用“不要求输出有序”的语义,应在资料中明确结果仍可能有序,且不承诺输入顺序或等值索引稳定性;不宜写成 false 永远等价于 true。若某些配置确实只支持 true,应限定对应范围,再评估入口拒绝及兼容影响,而不是直接全局拒绝 false。
回归应检查不同尾轴长度、k、largest、dtype 和算法分支的完整 values/indices 对应关系;当前脚本仅展示首行 values,尚不能验证索引及所有形状的顺序行为。我们会继续确认支持范围与顺序说明的对齐方式。


现象
aclnnTopkV2的sorted=false被接受(两段返回 0),且输出仍是有序的;而资料明确写「当前该参数仅支持取 True」。sorted=true9 8 7sorted=false9 8 7资料
math/topk/docs/aclnnTopkV2.mdL128(sorted使用说明)原文:True表示输出结果排序,False表示输出结果不排序。注意:当前该参数仅支持取True。期望
两种收法任选其一,但不能保持现状(声明"仅支持 True"却接受 False 且静默按 True 处理):① 第一段对
sorted=false返回 161002,与"仅支持取 True"的声明一致;② 或在资料里写明「sorted=false当前等价于true」,把这层退化关系说清楚。环境
npu-smi26.1.1,aarch64cann/ops-math584b2ea6复现步骤
repro.cppsource $ASCEND_HOME_PATH/set_env.shg++ -std=c++17 -O2 repro.cpp -o repro -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 -Wl,-rpath,$ASCEND_HOME_PATH/lib64 -Wl,--allow-shlib-undefined -lascendcl -lopapi -lnnopbaseREPRO_DEVICE=1 ./repro(0 号 die 非健康时换健康 die 编号)sorted=false与sorted=true的返回码与 values 完全相同复现脚本
// aclnnTopkV2: doc says "sorted 当前仅支持取 True", but sorted=false is accepted // (both stages return 0) and the result is still sorted. // Control group: sorted=true -> 0/0. #include <cstdio> #include <cstdlib> #include <vector> #include "acl/acl.h" #include "aclnnop/aclnn_topk.h" static aclTensor* Mk(std::vector<int64_t> sh, aclDataType dt, void* dev) { std::vector<int64_t> st(sh.size(), 1); for (int i = (int)sh.size() - 2; i >= 0; --i) st[i] = sh[i + 1] * st[i + 1]; return aclCreateTensor(sh.data(), sh.size(), dt, st.data(), 0, ACL_FORMAT_ND, sh.data(), sh.size(), dev); } static int Run(bool sorted, void* self, void* val, void* idx) { aclTensor* ts = Mk({4, 8}, ACL_FLOAT, self); aclTensor* tv = Mk({4, 3}, ACL_FLOAT, val); aclTensor* ti = Mk({4, 3}, ACL_INT64, idx); uint64_t ws = 0; aclOpExecutor* ex = nullptr; int r = (int)aclnnTopkV2GetWorkspaceSize(ts, 3, 1, true, sorted, 0, tv, ti, &ws, &ex); printf(" sorted=%-5s -> phase1=%d", sorted ? "true" : "false", r); if (r == 0) { void* p = nullptr; if (ws > 0) aclrtMalloc(&p, ws, ACL_MEM_MALLOC_HUGE_FIRST); int r2 = (int)aclnnTopkV2(p, ws, ex, nullptr); aclError sr = aclrtSynchronizeStream(nullptr); float out[3] = {0, 0, 0}; aclrtMemcpy(out, 12, val, 12, ACL_MEMCPY_DEVICE_TO_HOST); printf(" phase2=%d sync=%d row0 values=%.0f %.0f %.0f\n", r2, (int)sr, out[0], out[1], out[2]); if (p) aclrtFree(p); } else { printf("\n"); } aclDestroyTensor(ts); aclDestroyTensor(tv); aclDestroyTensor(ti); return r; } int main() { int dev = getenv("REPRO_DEVICE") ? atoi(getenv("REPRO_DEVICE")) : 0; aclInit(nullptr); aclrtSetDevice(dev); void *self = nullptr, *val = nullptr, *idx = nullptr; aclrtMalloc(&self, 128, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(&val, 48, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(&idx, 96, ACL_MEM_MALLOC_HUGE_FIRST); float host[32]; for (int r = 0; r < 4; ++r) { float row[8] = {9, 3, 7, 3, 1, 8, 2, 5}; for (int c = 0; c < 8; ++c) host[r * 8 + c] = row[c]; } aclrtMemcpy(self, 128, host, 128, ACL_MEMCPY_HOST_TO_DEVICE); printf("[1] control: sorted=true\n"); Run(true, self, val, idx); printf("[2] defect : sorted=false (doc: only true is supported)\n"); Run(false, self, val, idx); aclrtFree(self); aclrtFree(val); aclrtFree(idx); aclrtResetDevice(dev); aclFinalize(); return 0; }实测输出:
影响
从
torch.topk(..., sorted=False)迁过来的代码会按"不排序"的语义使用结果(只取集合、依赖原始出现顺序做后续 gather),实际拿到有序结果;返回码是 0,偏差不会在调用点暴露,只能靠下游数值异常反推。建议
优先按①在第一段拒绝(
math/topk/op_api/aclnn_topk.cpp的CheckParamValid里对sorted == false返回 161002),与同文件已有dim/k越界检查放在一起;若产品上确需支持sorted=false,按②改资料并写明退化语义。