Closed
[Bug-Report|缺陷反馈]: aclnnDistributeBarrier 的 group 空串/超长分支在 aclnnStatus 函数内 return false 被当作 SUCCESS,最终返回 161001 与空指针无法区分 #6566
liuhanwen8Add on  23 days agoClosed at  18 days ago
liuhanwen8
liuhanwen8
23 days ago Create

问题描述

mc2/distribute_barrier/op_api/distribute_barrier_base.cpp 的 BarrierCheckParams 声明为 aclnnStatus,但 group 取值非法(空串 / 超长)分支里写的是 return false;:

aclnnStatus BarrierCheckParams(const aclTensor* xRef, const char* group)
{
    CHECK_RET(BarrierCheckNullStatus(xRef, group), ACLNN_ERR_PARAM_NULLPTR);
    auto groupStrnLen = strnlen(group, HCCL_GROUP_NAME_MAX);
    if ((groupStrnLen >= HCCL_GROUP_NAME_MAX) || (groupStrnLen == 0)) {
        OP_LOGE_FOR_INVALID_VALUE_WITH_REASON("aclnnDistributeBarrier", "group", ...);
        return false;                 // ← 0 == ACLNN_SUCCESS,"取值非法"被吞成成功
    }
    return ACLNN_SUCCESS;
}

false 转 aclnnStatus 即 0 = ACLNN_SUCCESS,于是调用点的 CHECK_RET(retParam == ACLNN_SUCCESS, retParam) 直接放行,这段取值校验完全没有生效:接口继续带着空 groupBuf 进入 aclnnInnerDistributeBarrierGetWorkspaceSize。

用户可见后果:group 为空串 / 超长时返回 161001(资料定义为「必选参数 Tensor 是空指针」),与 group=nullptr 的返回码完全一样,无法区分「指针为空」与「取值非法」;日志里打印的是 value must be in the range (0, HCCL_GROUP_NAME_MAX),返回码却是空指针语义,定位会走偏。资料 docs/aclnnDistributeBarrier.md 的错误码表只列了 161001 = 输入的必选参数 Tensor 是空指针,没有覆盖「group 取值非法」这一实际路径。

实测(A2 910B2):

用例 期望 实测
group = nullptr 161001 161001
group = ""(空串) 取值非法错误码(区分于空指针) 161001(与 nullptr 相同)
group = "aaa…"(127 字符,超 HCCL_GROUP_NAME_MAX) 取值非法错误码 161001(与 nullptr 相同)

三种情况 workspaceSize 均为 0,进程不崩溃。

环境信息

  • 硬件:Atlas A2 训练系列 910B2(npu-smi 26.1.1)
  • CANN:9.2.0,Linux aarch64,g++ 11.4.0
  • 仓:cann/ops-transformer master ce0faee2(2026-10-23 09:52)

复现脚本

// 编译: g++ -std=c++17 -O2 dbarrier.cpp -o dbarrier \
//         -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 \
//         -lascendcl -lopapi -lnnopbase
// 运行: ./dbarrier
#include <acl/acl.h>
#include <aclnnop/aclnn_distribute_barrier.h>
#include <cstdio>
#include <cstring>
#include <vector>

static aclTensor *mkT(std::vector<int64_t> s, aclDataType dt, void *d)
{
    std::vector<int64_t> st(s.size());
    int64_t k = 1;
    for (int i = (int)s.size() - 1; i >= 0; --i) { st[i] = k; k *= s[i]; }
    return aclCreateTensor(s.data(), s.size(), dt, st.data(), 0, ACL_FORMAT_ND, s.data(), s.size(), d);
}

static void trial(const char *tag, const char *group)
{
    void *dx = nullptr;
    aclrtMalloc(&dx, 64, ACL_MEM_MALLOC_HUGE_FIRST);
    std::vector<float> h(2, 1.0f);
    aclrtMemcpy(dx, 8, h.data(), 8, ACL_MEMCPY_HOST_TO_DEVICE);
    aclTensor *x = mkT({2}, ACL_FLOAT, dx);

    uint64_t ws = 0;
    aclOpExecutor *ex = nullptr;
    printf("-- %-34s group=%s\n", tag, group ? (group[0] ? group : "<empty>") : "nullptr");
    aclnnStatus r = aclnnDistributeBarrierGetWorkspaceSize(x, group, 1, &ws, &ex);
    printf("   ret=%d  ws=%llu\n", (int)r, (unsigned long long)ws);
}

int main()
{
    aclInit(nullptr);
    aclrtSetDevice(0);
    trial("CTRL nullptr group", nullptr);
    trial("BUG  empty group", "");
    char longg[128];
    memset(longg, 'a', sizeof(longg) - 1);
    longg[127] = 0;
    trial("BUG  overlong group", longg);
    aclrtResetDevice(0);
    aclFinalize();
    return 0;
}

实测输出:

-- CTRL nullptr group                      group=nullptr
   ret=161001  ws=0
-- BUG  empty group                        group=<empty>
   ret=161001  ws=0
-- BUG  overlong group                     group=aaaaaaaa...(127 字符)
   ret=161001  ws=0

期望行为

BarrierCheckParams 的取值非法分支返回 ACLNN_ERR_PARAM_INVALID(161002),使「group 为空指针」与「group 取值非法」两条路径可区分;同时资料错误码表补一行「group 为空串或长度 ≥ HCCL_GROUP_NAME_MAX」的说明。

影响

aclnnDistributeBarrier / aclnnDistributeBarrierV2(共用 distribute_barrier_base.cpp)在 group 参数写错时,给用户的返回码与「传了空指针」完全一致,日志文案又指向「取值范围」,排障时容易被引到错误方向;且 aclnn 层这道校验实际是死代码,后续 Inner 若变更对空 group 的处理,将直接落到 kernel 侧。

likedislike
liuhanwen8liuhanwen8
23 days ago Added label: bug-report
周云飞
周云飞Collaborators
23 days ago Comments:

感谢提供完整的复现用例和环境信息。您指出的返回值问题有明确依据:在所贴的 BarrierCheckParams 片段中,函数返回类型是 aclnnStatus,非法长度分支却返回 false。按片段中的成功码判断方式,false 转为数值 0 后会被当作成功,因此该分支虽然打印了错误日志,却没有阻止后续调用。

问题分析

这里需要区分两件事:一是参数校验错误地返回成功,二是后续流程最终返回了什么错误码。前者可由您提供的代码片段直接判断;空串和超长字符串最终返回 161001,则是您在 A2 910B2、CANN 9.2.0 环境下报告的实测结果,具体由后续哪一层产生仍需进一步确认。

V1 入口和 V2 入口确实都调用 aclnnDistributeBarrierGetWorkspaceSizeBase,因此处理范围需要同时考虑两个接口的工作空间查询阶段。不过,目前提供的实测结果仅覆盖 V1,不能直接视为 V2 已完成验证。

处理方向

一个可行的修正方向是:在 BarrierCheckParams 中,将空串或长度大于等于 HCCL_GROUP_NAME_MAX 的分支改为返回 ACLNN_ERR_PARAM_INVALID,保留 group == nullptr 的空指针错误返回。这样可以在参数检查阶段直接区分“指针为空”和“字符串取值非法”,而不是依赖后续流程报错。

文档也应与最终确认的返回行为保持一致,明确空串及超长字符串对应的错误码,并避免将 group 空指针仅描述为“必选 Tensor 是空指针”。验证时需要同时覆盖两个接口的空指针、空串、长度边界和有效通信域输入,确认错误码区分正确且正常调用不受影响。

likedislike
游震Collaborators
23 days ago Comments:

/assign @luobaiqing

likedislike
CANN-robotCANN-robotCollaborators
23 days ago Assign luobaiqing as responsible person
luobqluobqCollaborators
22 days ago Assign SuperYuan as responsible person
luobqluobqCollaborators
22 days ago Removed responsible person luobaiqing
Simple_Bright&ManSimple_Bright&Man
20 days ago Associated pull request
CANN-robotCANN-robotCollaborators
18 days ago Close issue
CANN-robotCANN-robotCollaborators
18 days ago Added label: resolved
周云飞
周云飞Collaborators
4 days ago Comments:

已修正 aclnnDistributeBarrier 的 group 名称校验:空字符串或长度大于等于 128 时,返回参数错误 161002,不再因返回 false 被误判为成功;group 为空指针仍返回 161001。

同时更新了 Barrier 及 V2 接口的错误码文档,并补充了名称长度边界测试。长度为 1~127 仅表示通过名称长度检查,不代表通信域已初始化。

关联 PR:PR #14593

likedislike