Closed
[Bug-Report|缺陷反馈]: aclnnSparseFlashAttention value 传空指针返回 0,未按资料返回 161001 #6637
liuhanwen8Add on  20 days agoClosed at  14 days ago
liuhanwen8
liuhanwen8
20 days ago Create

Describe the current behavior / 问题描述 (Mandatory / 必填)

必选输入 value 传空指针时,两段式接口都返回 0;同签名的 query 传空指针正确返回 161001。资料错误码表写明「必选输入/输出/属性为空指针 → 161001」,value 是必选输入。

用例 phase1 / phase2 资料要求
基线(全部非空) 0 / 0 0
value = nullptr 0 / 0 161001
query = nullptr(对照) 161001 / 未进入 161001

Environment Information / 环境信息 (Mandatory / 必填)

  • 昇腾硬件:Atlas A2 系列(910B2,单 die)
  • CANN:9.2.0
  • 系统 / 编译器:Linux aarch64,g++($ASCEND_HOME_PATH 指向 CANN)
  • 调用方式:aclnn 两段式 C 接口直调(不经框架适配层)

Steps to reproduce the issue / 重现步骤 (Mandatory / 必填)

  1. 保存 repro.cpp 并按顶部命令编译运行。
  2. 程序依次跑基线、value=nullptr、query=nullptr 三次调用,其余参数完全相同。
  3. 观察输出:只有 value=nullptr 被放行。

Describe the expected behavior / 预期结果 (Mandatory / 必填)

value == nullptr 时 aclnnSparseFlashAttentionGetWorkspaceSize 应返回 161001,与 query/key/sparseIndices 等必选输入一致,不应进入执行段。

baseline      : phase1=0 phase2=0
value=nullptr : phase1=0 phase2=0  (期望 161001)
query=nullptr : phase1=161001 phase2=-1  (对照)

Special notes for this issue/备注 (Optional / 选填)

复现脚本(单文件自包含,50 行,含对照组与缺陷组)

g++ -O2 -I$ASCEND_HOME_PATH/include -I$ASCEND_HOME_PATH/include/aclnnop repro.cpp \
  -L$ASCEND_HOME_PATH/lib64 -lopapi_transformer -lopapi -lnnopbase -lascendcl \
  -Wl,-rpath,$ASCEND_HOME_PATH/lib64 -o repro && ./repro
// aclnnSparseFlashAttention: value=nullptr 两段均返回 0(资料要求 161001)
// g++ -O2 -I$ASCEND_HOME_PATH/include -I$ASCEND_HOME_PATH/include/aclnnop repro.cpp \
//   -L$ASCEND_HOME_PATH/lib64 -lopapi_transformer -lopapi -lnnopbase -lascendcl -o repro
#include <acl/acl.h>
#include <aclnnop/aclnn_sparse_flash_attention.h>
#include <cstdio>
#include <cstdint>
#include <cmath>
#include <vector>
typedef std::vector<int64_t> S;
static void *M(size_t n){void*p=nullptr;aclrtMalloc(&p,n,ACL_MEM_MALLOC_HUGE_FIRST);return p;}
static aclTensor*T(S s,aclDataType d,void*p){static std::vector<S> k;k.push_back(s);
  auto&v=k.back();return aclCreateTensor(v.data(),v.size(),d,0,0,ACL_FORMAT_ND,v.data(),v.size(),p);}
static void F16(void*p,size_t n){std::vector<uint16_t>h(n,0x3C00);
  aclrtMemcpy(p,n*2,h.data(),n*2,ACL_MEMCPY_HOST_TO_DEVICE);}
static void I32(void*p,std::vector<int32_t>v){
  aclrtMemcpy(p,v.size()*4,v.data(),v.size()*4,ACL_MEMCPY_HOST_TO_DEVICE);}

// nullWhich: 0=基线, 1=value, 2=query
static int one(int nullWhich,int*p2){
  const int64_t B=1,S1=2,N1=1,S2=64,D=512,Dr=64;
  void*q=M(B*S1*N1*D*2),*k=M(B*S2*D*2),*v=M(B*S2*D*2);
  void*si=M(B*S1*4*4),*aq=M(4),*ak=M(4);
  void*qr=M(B*S1*N1*Dr*2),*kr=M(B*S2*Dr*2);
  void*oa=M(B*S1*N1*D*2),*om=M(B*S1*N1*4),*os=M(B*S1*N1*4);
  F16(q,B*S1*N1*D);F16(k,B*S2*D);F16(v,B*S2*D);F16(qr,B*S1*N1*Dr);F16(kr,B*S2*Dr);
  I32(si,{0,1,2,3});I32(aq,{S1});I32(ak,{S2});
  uint64_t ws=0;aclOpExecutor*ex=nullptr;
  int rc=(int)aclnnSparseFlashAttentionGetWorkspaceSize(
    nullWhich==2?nullptr:T({B,S1,N1,D},ACL_FLOAT16,q),
    T({B,S2,1,D},ACL_FLOAT16,k),nullWhich==1?nullptr:T({B,S2,1,D},ACL_FLOAT16,v),
    T({B,S1,1,4},ACL_INT32,si),nullptr,T({1},ACL_INT32,aq),T({1},ACL_INT32,ak),
    T({B,S1,N1,Dr},ACL_FLOAT16,qr),T({B,S2,1,Dr},ACL_FLOAT16,kr),
    1.0/std::sqrt((double)(D+Dr)),16,(char*)"BSND",(char*)"BSND",
    0,INT64_MAX,INT64_MAX,2,false,
    T({B,S1,N1,D},ACL_FLOAT16,oa),T({B,1,S1,N1},ACL_FLOAT,om),
    T({B,1,S1,N1},ACL_FLOAT,os),&ws,&ex);
  *p2=-1;
  if(rc==0)*p2=(int)aclnnSparseFlashAttention(ws?M(ws):nullptr,ws,ex,nullptr);
  return rc;
}
int main(){
  aclInit(nullptr);aclrtSetDevice(0);
  int a2=0,b2=0,c2=0;
  int a=one(0,&a2),b=one(1,&b2),c=one(2,&c2);
  printf("baseline      : phase1=%d phase2=%d\n",a,a2);
  printf("value=nullptr : phase1=%d phase2=%d  (期望 161001)\n",b,b2);
  printf("query=nullptr : phase1=%d phase2=%d  (对照)\n",c,c2);
  aclrtResetDevice(0);aclFinalize();return 0;
}

影响:放行后 kernel 会带着空指针进入计算(读到非法地址或静默读到零页),属于稳定性风险,且上层无法在调用前发现参数错误。

建议:在参数校验入口补 value 判空,并补一条「仅 value 为空」的 UT(现有用例多为单参数置空,容易漏)。

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

感谢提供详细的复现参数和逐项置空对照。

从您提供的 CANN 9.2.0、Atlas A2(910B2)测试结果看,仅将 value 置为 nullptr 时,aclnnSparseFlashAttentionGetWorkspaceSize 仍返回 0,这与您引用的必选参数空指针应返回 ACLNN_ERR_PARAM_NULLPTR(161001) 的说明不一致。这里需要区分空指针与空 tensor:本次报告的是 value 指针本身为空,应重点检查必选输入的空指针校验及其错误码返回路径。

目前的代码片段尚未覆盖完整的参数检查和内部调用实现,因此还不能确定是遗漏了 value 判空,还是检查失败后未正确向外返回错误码。另外,执行段返回 0 本身不足以证明 kernel 已实际访问空指针,但也不能据此认为该输入可以安全使用。

一个可行的处理方向是:在 GetWorkspaceSize 阶段、任何访问或向下传递 value 的操作之前,确保空指针被拦截,并向调用方返回 161001。您建议的“仅 value 为空、其余参数保持有效”的单测很有针对性,可以用于验证这一行为,同时保留正常输入的成功路径。使用侧可暂时在调用前检查 value,为空时直接拒绝调用,不再进入执行段。我们会继续确认具体校验路径与返回码传递情况。

likedislike
liuhanwen8liuhanwen8
20 days ago Modify description of issue
周云飞
周云飞Collaborators
18 days ago Comments:

/assign @gcw_oeok7yxb

likedislike
CANN-robotCANN-robotCollaborators
18 days ago Assign gcw_oeok7yxb as responsible person
TiMoTiMoCollaborators
16 days ago Associated pull request
CANN-robotCANN-robotCollaborators
14 days ago Close issue
CANN-robotCANN-robotCollaborators
14 days ago Added label: resolved
周云飞
周云飞Collaborators
2 days ago Comments:

已修正文档:value 支持传入空指针,此时使用 key 作为 value,不因该空指针返回 161001;value 仍不支持空 tensor。

本次为文档修正,无需修改算子代码。

关联 PR:PR #14796

likedislike