Closed
[Bug-Report|缺陷反馈]: aclnnReflectionPad1d/2d/3d 负 padding 第一段放行、第二段返回内部错误 561103 #3932
liuhanwen8Add on  16 days agoClosed at  11 days ago
liuhanwen8
liuhanwen8
16 days ago Create

现象

aclnnReflectionPad1d / 2d / 3d 在 padding 含负值(裁剪)时,第一段 GetWorkspaceSize 返回 0 放行,
第二段执行返回 561103(ACLNN_ERR_INNER_NULLPTR)—— 两段口径不一致,且把内部错误码外泄给调用方。

FLOAT32、值 1..7,同机逐项对照:

  • 1d 对照组 self=[2,5] pad=1,2:ret(gws)=0 ret(exec)=0,输出 [2,8] 正常
  • 1d 缺陷组 self=[2,5] pad=-1,2:ret(gws)=0 ret(exec)=561103(输出 [2,6])
  • 2d 对照组 self=[1,4,4] pad=1,1,1,1:ret(gws)=0 ret(exec)=0,输出 [1,6,6] 正常
  • 2d 缺陷组 self=[1,4,4] pad=-1,1,1,1:ret(gws)=0 ret(exec)=561103(输出 [1,6,4])

3d 同样命中(self=[1,1,4,5,6] pad=-1,1,0,2,1,0] → ret(exec)=561103),说明是 mirror_pad 一族共用的 host 路径问题,不是单个接口的偶发。

期望

资料 conversion/mirror_pad/docs/aclnnReflectionPad{1,2,3}d.md 没有声明负 padding 的语义
(既没写「支持裁剪」,也没写「负值报错」),因此本 issue 不主张「应当支持裁剪」。

主张的是两段一致:若不支持,应在第一段返回 161002(ACLNN_ERR_PARAM_INVALID);padding 是 aclIntArray 属性,host 侧判负是零成本校验。

影响

失败发生在第二段/执行期而非参数校验期:调用方拿到 561103(内部错误)而不是 161002(参数错误),会倾向重试或按环境故障上报,掩盖真实的入参问题;异步/图模式下更难定位到「padding 为负」。无数据正确性问题(直接失败,不产脏数据)。

建议

两种修法都可以,但两段必须一致:

  1. 不支持 → host 侧(op_api 的 check 或 tiling 前置)判负并返回 161002;
  2. 支持 → 在资料补上负 padding 的裁剪语义,并让 kernel 走裁剪分支(PyTorch F.pad(mode='reflect') 支持负值)。

环境

  • 仓:cann/ops-math @ 584b2ea6(master,2026-10-24 fetch)
  • 硬件/系统:Ascend 910B2(A2)单卡,Linux aarch64;CANN 9.2.0;实测 2026-10-25

复现步骤

  1. 把下方「复现脚本」存为 repro_refpad_negpad.cpp;LF 换行
  2. 编译:g++ -std=c++17 -O2 repro_refpad_negpad.cpp -o repro -I"$ASCEND_HOME_PATH/include" -L"$ASCEND_HOME_PATH/lib64" -lascendcl -lopapi -lnnopbase
  3. 运行:ASCEND_LAUNCH_BLOCKING=1 ./repro
  4. 两组 CTRL-* 应 ret(gws)=0 ret(exec)=0;两组 CASE-*-negative 应 ret(gws)=0 ret(exec)=561103

复现脚本

#include <cstdio>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_reflection_pad1d.h"
#include "aclnnop/aclnn_reflection_pad2d.h"

static aclTensor* Make(std::vector<float>& h, std::vector<int64_t>& sh, void** dev) {
    int64_t n = 1; for (auto d : sh) n *= d;
    size_t b = size_t(n > 0 ? n : 1) * sizeof(float);
    aclrtMalloc(dev, b, ACL_MEM_MALLOC_HUGE_FIRST);
    if (n > 0) aclrtMemcpy(*dev, b, h.data(), b, ACL_MEMCPY_HOST_TO_DEVICE);
    std::vector<int64_t> st(sh.size(), 1);
    for (int64_t i = int64_t(sh.size()) - 2; i >= 0; --i) st[i] = sh[i + 1] * st[i + 1];
    return aclCreateTensor(sh.data(), sh.size(), ACL_FLOAT, st.data(), 0,
                           ACL_FORMAT_ND, sh.data(), sh.size(), *dev);
}

static std::vector<int64_t> Padded(const std::vector<int64_t>& s, const std::vector<int64_t>& p) {
    std::vector<int64_t> o = s; int r = int(o.size());
    for (int k = r - 1; k >= 0; --k) {
        int i = 2 * (r - 1 - k);
        if (i + 1 < int(p.size())) o[k] += p[i] + p[i + 1];
    }
    return o;
}

// 对照组 CTRL(正 padding)/ 缺陷组 DEFECT(负 padding)
static void Run(const char* tag, int dim, std::vector<int64_t> in, std::vector<int64_t> pads,
                aclrtStream stream) {
    std::vector<int64_t> out = Padded(in, pads);
    int64_t nIn = 1, nOut = 1;
    for (auto d : in) nIn *= d;
    for (auto d : out) nOut *= d;
    std::vector<float> sh(size_t(nIn > 0 ? nIn : 1));
    for (int64_t i = 0; i < nIn; ++i) sh[size_t(i)] = float(i % 7 + 1);
    std::vector<float> oh(size_t(nOut > 0 ? nOut : 1), -7.0f);
    void* sd = nullptr; void* od = nullptr;
    aclTensor* self = Make(sh, in, &sd);
    aclTensor* ot = Make(oh, out, &od);
    aclIntArray* pa = aclCreateIntArray(pads.data(), int64_t(pads.size()));
    uint64_t ws = 0; aclOpExecutor* ex = nullptr;
    aclnnStatus r1 = (dim == 1)
        ? aclnnReflectionPad1dGetWorkspaceSize(self, pa, ot, &ws, &ex)
        : aclnnReflectionPad2dGetWorkspaceSize(self, pa, ot, &ws, &ex);
    void* w = nullptr;
    if (r1 == 0 && ws > 0) aclrtMalloc(&w, ws, ACL_MEM_MALLOC_HUGE_FIRST);
    aclnnStatus r2 = (aclnnStatus)-1;
    if (r1 == 0) r2 = (dim == 1) ? aclnnReflectionPad1d(w, ws, ex, stream)
                                 : aclnnReflectionPad2d(w, ws, ex, stream);
    aclnnStatus r3 = (r1 == 0 && r2 == 0) ? aclrtSynchronizeStream(stream) : -1;
    printf("[%-18s] pad=[", tag);
    for (size_t i = 0; i < pads.size(); ++i) printf("%s%ld", i ? "," : "", long(pads[i]));
    printf("] ret(gws)=%d ret(exec)=%d sync=%d\n", int(r1), int(r2), int(r3));
    aclDestroyTensor(self); aclDestroyTensor(ot); aclDestroyIntArray(pa);
    if (w) aclrtFree(w); aclrtFree(sd); aclrtFree(od);
}

int main() {
    aclInit(nullptr); aclrtSetDevice(0);
    aclrtStream s = nullptr; aclrtCreateStream(&s);
    // 对照组 CTRL
    Run("CTRL-1d", 1, {2, 5}, {1, 2}, s);
    // 缺陷组 DEFECT
    Run("CASE-1d-negative", 1, {2, 5}, {-1, 2}, s);
    Run("CTRL-2d", 2, {1, 4, 4}, {1, 1, 1, 1}, s);
    Run("CASE-2d-negative", 2, {1, 4, 4}, {-1, 1, 1, 1}, s);
    aclrtDestroyStream(s); aclrtResetDevice(0); aclFinalize();
    return 0;
}

实测输出:[CTRL-1d] ret(gws)=0 ret(exec)=0、[CASE-1d-negative] ret(gws)=0 ret(exec)=561103、
[CTRL-2d] ret(gws)=0 ret(exec)=0、[CASE-2d-negative] ret(gws)=0 ret(exec)=561103。

likedislike
liuhanwen8liuhanwen8
16 days ago Added label: bug-report
陈思
陈思Collaborators
15 days ago Comments:

您好,感谢反馈!

问题分析

按您提供的 cann/ops-math@584b2ea6 核查,三接口的 Host 检查要求各侧 padding 小于对应原维度,并通过 SafePadSum 检查溢出、裁剪范围和输出尺寸;它没有统一拒绝负值。因此长度 5、[-1,2]、输出长度 6 这样的输入可以通过第一段检查。SafePadSum 只验证尺寸,并未实现负值裁剪。形状检查、SafePadSum。

对报告中的 FLOAT32,实际走的是 ProcessMirrorPad,负值保留符号后传给 MirrorPad;A2 的 FLOAT32 分派到 AI Core。复数类型另走 PadV3,不能据此认为所有类型具有相同负 padding 能力。接口分支、padding 传递、后端选择。当前公开构建列出的 MirrorPad 实现平台为 arch35,尚不能仅凭这部分代码确认您所用 A2 包内第二段返回 561103 的具体触发位置。构建配置。

处理方向

现有资料确实只给出了 padding 上界及输出尺寸加和,没有明确负值的语义。资料约束。一个可行方向是结合平台和数据类型明确能力边界:若对应路径不支持负 padding,可在现有 Host 参数检查中提前返回 161002;若支持,则需同时明确裁剪与反射的索引语义,并匹配可执行实现。正负混合时反射参考范围也需明确,不能只按输出尺寸合法就认定可执行,或直接假定先裁剪再反射对所有边界等价。

这些调整需保留正 padding 上界、裁剪范围、溢出与输出形状检查,并评估其他类型和平台已可用行为的兼容性。我们会继续确认该路径的能力与错误码处理。

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
庄昭雄庄昭雄
12 days ago Associated pull request
庄昭雄
庄昭雄
12 days ago Comments:

已提交修复:反射填充(ReflectionPad1d/2d/3d)在 CheckShape 中增加 padding 非负校验,负值第一段返回 161002。

真机(910B / CANN 8.5.1):修复前 padding=-1,1,1,1 为 rc1=0 / rc2=561103;修复后 rc1=161002;正 padding 对照仍为 0。

likedislike
庄昭雄
庄昭雄
12 days ago Comments:

MR:!6828

likedislike
WangJinChengWangJinChengCollaborators
11 days ago Associated pull request
WangJinChengWangJinChengCollaborators
11 days ago changed custom state from 进行中 to 已完成
WangJinChengWangJinChengCollaborators
11 days ago Close issue