已合并
[Feature][ops] add fused_infer_attention_score op_api files_s for migrate FIA to mindiesd #411
[Feature][ops] add fused_infer_attention_score op_api files_s for migrate FIA to mindiesd #411
已合并
wenjiali_sh创建于 7月3日
6 个文件变更+915-0
@@ -0,0 +1,204 @@
1+/**
2+ * Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
3+ * MindIE is licensed under Mulan PSL v2.
4+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
5+ * You may obtain a copy of Mulan PSL v2 at:
6+ * http://license.coscl.org.cn/MulanPSL2
7+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10+ * See the Mulan PSL v2 for more details.
11+ */
12+ 
13+#include "aclnn_fused_infer_attention_score_v4.h"
14+#include "opdev/common_types.h"
15+#include "opdev/make_op_executor.h"
16+#include "opdev/platform.h"
17+#include "opdev/op_def.h"
18+#include "opdev/op_log.h"
19+#include "fused_infer_attention_score_inner.h"
20+#include "aclnnInner_eagle_fused_infer_attention_score.h" // 该文件为自动生成,在build/autogen/inner路径下
21+ 
22+using namespace op;
23+ 
24+#ifdef __cplusplus
25+extern "C" {
26+#endif
27+ 
28+namespace {
29+/**
30+ * @brief for acl graph calculates the max workspace size based on the specific calculation process.
31+ * declaration here for testcase to use by extern the interface
32+ * @domain aclnn_ops_infer
33+ */
34+__attribute__((visibility("default"))) aclnnStatus aclnnFusedInferAttentionScoreV4GetMaxWorkspaceSize(
35+ const aclTensor *query, const aclTensorList *tensorListKey, const aclTensorList *tensorListValue,
36+ const aclTensor *pseShiftOptional, const aclTensor *attenMaskOptional, const aclIntArray *actualSeqLengthsOptional,
37+ const aclIntArray *actualSeqLengthsKvOptional, const aclTensor *deqScale1Optional,
38+ const aclTensor *quantScale1Optional, const aclTensor *deqScale2Optional, const aclTensor *quantScale2Optional,
39+ const aclTensor *quantOffset2Optional, const aclTensor *antiquantScaleOptional,
40+ const aclTensor *antiquantOffsetOptional, const aclTensor *blockTableOptional,
41+ const aclTensor *queryPaddingSizeOptional, const aclTensor *kvPaddingSizeOptional,
42+ const aclTensor *keyAntiquantScaleOptional, const aclTensor *keyAntiquantOffsetOptional,
43+ const aclTensor *valueAntiquantScaleOptional, const aclTensor *valueAntiquantOffsetOptional,
44+ const aclTensor *tensorKeySharedPrefixOptional, const aclTensor *tensorValueSharedPrefixOptional,
45+ const aclIntArray *actualSharedPrefixLenOptional, const aclTensor *queryRopeOptional,
46+ const aclTensor *keyRopeOptional, const aclTensor *keyRopeAntiquantScaleOptional,
47+ const aclTensor *dequantScaleQueryOptional, const aclTensor *learnableSinkOptional, int64_t numHeads,
48+ double scaleValue, int64_t preTokens, int64_t nextTokens, char *inputLayout, int64_t numKeyValueHeads,
49+ int64_t sparseMode, int64_t innerPrecise, int64_t blockSize, int64_t antiquantMode, bool softmaxLseFlag,
50+ int64_t keyAntiquantMode, int64_t valueAntiquantMode, int64_t queryQuantMode, const aclTensor *attentionOut,
51+ const aclTensor *softmaxLse, uint64_t *workspaceSize, aclOpExecutor **executor);
52+ 
53+extern "C" aclnnStatus __attribute__((weak)) NnopbaseDisableOptionalInput(void *executor, const size_t irIndex);
54+ 
55+aclnnStatus aclnnFusedInferAttentionScoreV4GetMaxWorkspaceSize(const aclTensor *query,
56+ const aclTensorList *tensorListKey, const aclTensorList *tensorListValue, const aclTensor *pseShiftOptional,
57+ const aclTensor *attenMaskOptional, const aclIntArray *actualSeqLengthsOptional,
58+ const aclIntArray *actualSeqLengthsKvOptional, const aclTensor *deqScale1Optional,
59+ const aclTensor *quantScale1Optional, const aclTensor *deqScale2Optional, const aclTensor *quantScale2Optional,
60+ const aclTensor *quantOffset2Optional, const aclTensor *antiquantScaleOptional,
61+ const aclTensor *antiquantOffsetOptional, const aclTensor *blockTableOptional,
62+ const aclTensor *queryPaddingSizeOptional, const aclTensor *kvPaddingSizeOptional,
63+ const aclTensor *keyAntiquantScaleOptional, const aclTensor *keyAntiquantOffsetOptional,
64+ const aclTensor *valueAntiquantScaleOptional, const aclTensor *valueAntiquantOffsetOptional,
65+ const aclTensor *tensorKeySharedPrefixOptional, const aclTensor *tensorValueSharedPrefixOptional,
66+ const aclIntArray *actualSharedPrefixLenOptional, const aclTensor *queryRopeOptional,
67+ const aclTensor *keyRopeOptional, const aclTensor *keyRopeAntiquantScaleOptional,
68+ const aclTensor *dequantScaleQueryOptional, const aclTensor *learnableSinkOptional, int64_t numHeads,
69+ double scaleValue, int64_t preTokens, int64_t nextTokens, char *inputLayout, int64_t numKeyValueHeads,
70+ int64_t sparseMode, int64_t innerPrecise, int64_t blockSize, int64_t antiquantMode, bool softmaxLseFlag,
71+ int64_t keyAntiquantMode, int64_t valueAntiquantMode, int64_t queryQuantMode, const aclTensor *attentionOut,
72+ const aclTensor *softmaxLse, uint64_t *workspaceSize, aclOpExecutor **executor) {
73+ if (op::GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_3510) {
74+ OP_LOGE(ACLNN_ERR_RUNTIME_ERROR,
75+ "Interface aclnnFusedInferAttentionScore versions V1 to V4 are no longer supported on Ascend950.");
76+ return ACLNN_ERR_RUNTIME_ERROR;
77+ }
78+ OP_LOGD("start aclnnFusedInferAttentionScoreV4GetMaxWorkspaceSize");
79+ TensorPreProcess(tensorListKey, tensorListValue);
80+ PrefixTensorPreProcess(tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional);
81+ 
82+ aclTensor *fakeActualSeqLengthsOptional{nullptr};
83+ aclTensor *fakeActualSeqLengthsKvOptional{nullptr};
84+ aclTensor *fakeActualSharedPrefixLenOptional{nullptr};
85+ 
86+ // nullptr不处理, nullptr是空指针,这样不会影响原来就不传入actual seq length为空的逻辑
87+ aclnnStatus ret = FakeArray(actualSeqLengthsOptional, fakeActualSeqLengthsOptional);
88+ CHECK_RET_CODE(ret, "Try alloc fake actualSeqLengthsOptional failed");
89+ 
90+ ret = FakeArray(actualSeqLengthsKvOptional, fakeActualSeqLengthsKvOptional);
91+ if (ret != ACLNN_SUCCESS) {
92+ OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "Try alloc fake actualSeqLengthsKvOptional failed");
93+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 没有返回值无需校验
94+ return ret;
95+ }
96+ 
97+ ret = FakeArray(actualSharedPrefixLenOptional, fakeActualSharedPrefixLenOptional);
98+ if (ret != ACLNN_SUCCESS) {
99+ OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "Try alloc fake actualSharedPrefixLenOptional failed");
100+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 没有返回值无需校验
101+ aclDestroyTensor(fakeActualSeqLengthsKvOptional);
102+ return ret;
103+ }
104+ 
105+ const aclTensor *placeHolder = nullptr;
106+ const aclTensor *tempTensor = nullptr;
107+ FusedInferAttentionScoreProcessSoftmaxLse(softmaxLseFlag, softmaxLse, tempTensor, placeHolder);
108+ 
109+ ret = aclnnInnerEagleFusedInferAttentionScoreTensorGetWorkspaceSize(query, tensorListKey, tensorListValue,
110+ pseShiftOptional, attenMaskOptional, fakeActualSeqLengthsOptional, fakeActualSeqLengthsKvOptional,
111+ deqScale1Optional, quantScale1Optional, deqScale2Optional, quantScale2Optional, quantOffset2Optional,
112+ antiquantScaleOptional, antiquantOffsetOptional, blockTableOptional, queryPaddingSizeOptional,
113+ kvPaddingSizeOptional, keyAntiquantScaleOptional, keyAntiquantOffsetOptional, valueAntiquantScaleOptional,
114+ valueAntiquantOffsetOptional, tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional,
115+ fakeActualSharedPrefixLenOptional, queryRopeOptional, keyRopeOptional, keyRopeAntiquantScaleOptional,
116+ dequantScaleQueryOptional, learnableSinkOptional, nullptr, nullptr, numHeads, scaleValue, preTokens, nextTokens,
117+ inputLayout, numKeyValueHeads, sparseMode, innerPrecise, blockSize, antiquantMode, softmaxLseFlag,
118+ keyAntiquantMode, valueAntiquantMode, queryQuantMode, 0, 0, attentionOut, placeHolder, workspaceSize, executor);
119+ if (softmaxLseFlag == false) {
120+ aclDestroyTensor(tempTensor);
121+ }
122+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 只会成功,无需校验
123+ aclDestroyTensor(fakeActualSeqLengthsKvOptional);
124+ aclDestroyTensor(fakeActualSharedPrefixLenOptional);
125+ return ret;
126+}
127+ 
128+aclnnStatus aclnnFusedInferAttentionScoreV4GetWorkspaceSize(const aclTensor *query, const aclTensorList *key,
129+ const aclTensorList *value, const aclTensor *pseShiftOptional, const aclTensor *attenMaskOptional,
130+ const aclIntArray *actualSeqLengthsOptional, const aclIntArray *actualSeqLengthsKvOptional,
131+ const aclTensor *deqScale1Optional, const aclTensor *quantScale1Optional, const aclTensor *deqScale2Optional,
132+ const aclTensor *quantScale2Optional, const aclTensor *quantOffset2Optional,
133+ const aclTensor *antiquantScaleOptional, const aclTensor *antiquantOffsetOptional,
134+ const aclTensor *blockTableOptional, const aclTensor *queryPaddingSizeOptional,
135+ const aclTensor *kvPaddingSizeOptional, const aclTensor *keyAntiquantScaleOptional,
136+ const aclTensor *keyAntiquantOffsetOptional, const aclTensor *valueAntiquantScaleOptional,
137+ const aclTensor *valueAntiquantOffsetOptional, const aclTensor *keySharedPrefixOptional,
138+ const aclTensor *valueSharedPrefixOptional, const aclIntArray *actualSharedPrefixLenOptional,
139+ const aclTensor *queryRopeOptional, const aclTensor *keyRopeOptional,
140+ const aclTensor *keyRopeAntiquantScaleOptional, const aclTensor *dequantScaleQueryOptional,
141+ const aclTensor *learnableSinkOptional, int64_t numHeads, double scaleValue, int64_t preTokens, int64_t nextTokens,
142+ char *inputLayout, int64_t numKeyValueHeads, int64_t sparseMode, int64_t innerPrecise, int64_t blockSize,
143+ int64_t antiquantMode, bool softmaxLseFlag, int64_t keyAntiquantMode, int64_t valueAntiquantMode,
144+ int64_t queryQuantMode, const aclTensor *attentionOut, const aclTensor *softmaxLse, uint64_t *workspaceSize,
145+ aclOpExecutor **executor) {
146+ if (op::GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_3510) {
147+ OP_LOGE(ACLNN_ERR_RUNTIME_ERROR,
148+ "Interface aclnnFusedInferAttentionScore versions V1 to V4 are no longer supported on Ascend950.");
149+ return ACLNN_ERR_RUNTIME_ERROR;
150+ }
151+ const aclTensorList *tensorListKey = key;
152+ const aclTensorList *tensorListValue = value;
153+ TensorPreProcess(tensorListKey, tensorListValue);
154+ 
155+ const aclTensor *tensorKeySharedPrefixOptional = keySharedPrefixOptional;
156+ const aclTensor *tensorValueSharedPrefixOptional = valueSharedPrefixOptional;
157+ PrefixTensorPreProcess(tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional);
158+ 
159+ aclnnStatus ret = CheckKVContiguous(key, value);
160+ if (ret != ACLNN_SUCCESS && NnopbaseSupportTensorV2 == nullptr) {
161+ return ret;
162+ }
163+ 
164+ const aclTensor *placeHolder = nullptr;
165+ const aclTensor *tempTensor = nullptr;
166+ FusedInferAttentionScoreProcessSoftmaxLse(softmaxLseFlag, softmaxLse, tempTensor, placeHolder);
167+ 
168+ ret = aclnnInnerEagleFusedInferAttentionScoreGetWorkspaceSize(query, tensorListKey, tensorListValue,
169+ pseShiftOptional, attenMaskOptional, actualSeqLengthsOptional, actualSeqLengthsKvOptional, deqScale1Optional,
170+ quantScale1Optional, deqScale2Optional, quantScale2Optional, quantOffset2Optional, antiquantScaleOptional,
171+ antiquantOffsetOptional, blockTableOptional, queryPaddingSizeOptional, kvPaddingSizeOptional,
172+ keyAntiquantScaleOptional, keyAntiquantOffsetOptional, valueAntiquantScaleOptional,
173+ valueAntiquantOffsetOptional, tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional,
174+ actualSharedPrefixLenOptional, queryRopeOptional, keyRopeOptional, keyRopeAntiquantScaleOptional,
175+ dequantScaleQueryOptional, learnableSinkOptional, nullptr, nullptr, numHeads, scaleValue, preTokens, nextTokens,
176+ inputLayout, numKeyValueHeads, sparseMode, innerPrecise, blockSize, antiquantMode, softmaxLseFlag,
177+ keyAntiquantMode, valueAntiquantMode, queryQuantMode, 0, 0, attentionOut, placeHolder, workspaceSize, executor);
178+ if (softmaxLseFlag == false) {
179+ aclDestroyTensor(tempTensor);
180+ }
181+ if (ret == 0) {
182+ if (NnopbaseDisableOptionalInput != nullptr) {
183+ NnopbaseDisableOptionalInput(*executor, 29U); // 29 is input irIndex,占位符
184+ NnopbaseDisableOptionalInput(*executor, 30U); // 30 is input irIndex,占位符
185+ }
186+ }
187+ return ret;
188+}
189+ 
190+aclnnStatus aclnnFusedInferAttentionScoreV4(
191+ void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, const aclrtStream stream) {
192+ if (op::GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_3510) {
193+ OP_LOGE(ACLNN_ERR_RUNTIME_ERROR,
194+ "Interface aclnnFusedInferAttentionScore versions V1 to V4 are no longer supported on Ascend950.");
195+ return ACLNN_ERR_RUNTIME_ERROR;
196+ }
197+ return aclnnInnerEagleFusedInferAttentionScore(workspace, workspaceSize, executor, stream);
198+}
199+ 
200+} // namespace
atomgit-bot
atomgit-botatomgit-bot7月3日

🔴 Critical

在 v4.cpp 中,匿名命名空间 namespace {(第28行)包裹了整个文件,包括两个在头文件 v4.h 中声明为外部 API 的函数:

  • aclnnFusedInferAttentionScoreV4GetWorkspaceSize(第145行定义,v4.h 第25行声明)
  • aclnnFusedInferAttentionScoreV4(第224行定义,v4.h 第47行声明)

匿名命名空间使这些函数获得 内部链接(internal linkage),与头文件中的外部链接声明不匹配。任何包含 v4.h 并调用这两个函数的翻译单元在链接阶段都会因找不到外部符号而产生 undefined reference 链接错误,导致构建失败。

对比 v5.cpp:v5.cpp 无匿名命名空间,其同名模式的函数处于 extern "C" 块内,具有正确的外部链接。

修复:删除 v4.cpp 第28行的 namespace { 和第234行的 } // namespace,使函数定义与头文件声明保持一致的 C 外部链接。

建议:删除匿名命名空间(第28行的 namespace { 和第234行的 } // namespace),使 aclnnFusedInferAttentionScoreV4GetWorkspaceSizeaclnnFusedInferAttentionScoreV4 具有与头文件声明一致的外部链接(C linkage)。

likedislike
201+ 
202+#ifdef __cplusplus
203+}
204+#endif
@@ -0,0 +1,54 @@
1+/**
2+ * Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
3+ * MindIE is licensed under Mulan PSL v2.
4+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
5+ * You may obtain a copy of Mulan PSL v2 at:
6+ * http://license.coscl.org.cn/MulanPSL2
7+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10+ * See the Mulan PSL v2 for more details.
11+ */
12+ 
13+#ifndef ACLNN_FUSED_INFER_ATTENTION_SCORE_V4_H_
14+#define ACLNN_FUSED_INFER_ATTENTION_SCORE_V4_H_
15+#include "aclnn/acl_meta.h"
16+ 
17+#ifdef __cplusplus
18+extern "C" {
19+#endif
20+ 
21+/**
22+ * @brief The first interface of aclnnFusedInferAttentionScoreV4 calculates the workspace size based on the specific calculation process.
23+ * @domain aclnn_ops_infer
24+ */
25+__attribute__((visibility("default"))) aclnnStatus aclnnFusedInferAttentionScoreV4GetWorkspaceSize(
26+ const aclTensor *query, const aclTensorList *key, const aclTensorList *value, const aclTensor *pseShiftOptional,
27+ const aclTensor *attenMaskOptional, const aclIntArray *actualSeqLengthsOptional,
28+ const aclIntArray *actualSeqLengthsKvOptional, const aclTensor *deqScale1Optional,
29+ const aclTensor *quantScale1Optional, const aclTensor *deqScale2Optional, const aclTensor *quantScale2Optional,
30+ const aclTensor *quantOffset2Optional, const aclTensor *antiquantScaleOptional,
31+ const aclTensor *antiquantOffsetOptional, const aclTensor *blockTableOptional,
32+ const aclTensor *queryPaddingSizeOptional, const aclTensor *kvPaddingSizeOptional,
33+ const aclTensor *keyAntiquantScaleOptional, const aclTensor *keyAntiquantOffsetOptional,
34+ const aclTensor *valueAntiquantScaleOptional, const aclTensor *valueAntiquantOffsetOptional,
35+ const aclTensor *keySharedPrefixOptional, const aclTensor *valueSharedPrefixOptional,
36+ const aclIntArray *actualSharedPrefixLenOptional, const aclTensor *queryRopeOptional,
37+ const aclTensor *keyRopeOptional, const aclTensor *keyRopeAntiquantScaleOptional,
38+ const aclTensor *dequantScaleQueryOptional, const aclTensor *learnableSinkOptional, int64_t numHeads,
39+ double scaleValue, int64_t preTokens, int64_t nextTokens, char *inputLayout, int64_t numKeyValueHeads,
40+ int64_t sparseMode, int64_t innerPrecise, int64_t blockSize, int64_t antiquantMode, bool softmaxLseFlag,
41+ int64_t keyAntiquantMode, int64_t valueAntiquantMode, int64_t queryQuantMode, const aclTensor *attentionOut,
42+ const aclTensor *softmaxLse, uint64_t *workspaceSize, aclOpExecutor **executor);
43+ 
44+/**
45+ * @brief The second interface of aclnnFusedInferAttentionScoreV4 is used to perform calculations.
46+ */
47+__attribute__((visibility("default"))) aclnnStatus aclnnFusedInferAttentionScoreV4(
48+ void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, const aclrtStream stream);
49+ 
50+#ifdef __cplusplus
51+}
52+#endif
53+ 
54+#endif
@@ -0,0 +1,250 @@
1+/**
2+ * Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
3+ * MindIE is licensed under Mulan PSL v2.
4+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
5+ * You may obtain a copy of Mulan PSL v2 at:
6+ * http://license.coscl.org.cn/MulanPSL2
7+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10+ * See the Mulan PSL v2 for more details.
11+ */
12+ 
13+#include "aclnn_fused_infer_attention_score_v5.h"
atomgit-bot
atomgit-botatomgit-bot7月3日

🔴 Critical

aclnn_fused_infer_attention_score_v5.cpp 第 13 行和 fallback_fused_infer_attention_score.cpp 第 22 行均 #include "aclnn_fused_infer_attention_score_v5.h",但该头文件在整个仓库中不存在(glob 搜索无结果)。PR 描述中也明确注明 v5 "未引入头文件",然而 .cpp 文件又引用了它,这是一个矛盾。没有该头文件,编译必定失败——v5.cpp 中定义的对外 API 函数(如 aclnnEagleFusedInferAttentionScoreV5、aclnnEagleFusedInferAttentionScoreV5GetWorkspaceSize 等)的外部调用者(包括 fallback.cpp 中的 EXEC_OPAPI_CMD 宏需要通过函数指针调用 GetWorkspaceSize 和执行函数)无法找到声明。类比 v4 版本,v4.h 提供了对应的公开声明,v5 需要同等的头文件。

建议:参照 aclnn_fused_infer_attention_score_v4.h 的模式,创建 aclnn_fused_infer_attention_score_v5.h,在其中声明 aclnnEagleFusedInferAttentionScoreV5、aclnnEagleFusedInferAttentionScoreV5GetWorkspaceSize、CheckTensorContiguous、NnopbaseSupportTensorV2 等公开符号。同时确保该头文件被 v5.cpp 和 fallback_fused_infer_attention_score.cpp 正确包含。

likedislike
14+ 
15+#include "opdev/common_types.h"
16+#include "opdev/make_op_executor.h"
17+#include "opdev/op_def.h"
18+#include "opdev/op_log.h"
19+#include "fused_infer_attention_score_inner.h"
20+#include "aclnnInner_eagle_fused_infer_attention_score.h" // 该文件为自动生成,在build/autogen/inner路径下
21+#include "opdev/tensor_view_utils.h"
22+ 
23+using namespace op;
24+ 
25+#ifdef __cplusplus
26+extern "C" {
27+#endif
28+ 
29+/**
30+ * @brief for acl graph calculates the max workspace size based on the specific calculation process.
31+ * declaration here for testcase to use by extern the interface
32+ * @domain aclnn_ops_infer
33+ */
34+__attribute__((visibility("default"))) aclnnStatus aclnnEagleFusedInferAttentionScoreV5GetMaxWorkspaceSize(
35+ const aclTensor *query, const aclTensorList *key, const aclTensorList *value, const aclTensor *pseShiftOptional,
36+ const aclTensor *attenMaskOptional, const aclIntArray *actualSeqLengthsOptional,
37+ const aclIntArray *actualSeqLengthsKvOptional, const aclTensor *deqScale1Optional,
38+ const aclTensor *quantScale1Optional, const aclTensor *deqScale2Optional, const aclTensor *quantScale2Optional,
39+ const aclTensor *quantOffset2Optional, const aclTensor *antiquantScaleOptional,
40+ const aclTensor *antiquantOffsetOptional, const aclTensor *blockTableOptional,
41+ const aclTensor *queryPaddingSizeOptional, const aclTensor *kvPaddingSizeOptional,
42+ const aclTensor *keyAntiquantScaleOptional, const aclTensor *keyAntiquantOffsetOptional,
43+ const aclTensor *valueAntiquantScaleOptional, const aclTensor *valueAntiquantOffsetOptional,
44+ const aclTensor *keySharedPrefixOptional, const aclTensor *valueSharedPrefixOptional,
45+ const aclIntArray *actualSharedPrefixLenOptional, const aclTensor *queryRopeOptional,
46+ const aclTensor *keyRopeOptional, const aclTensor *keyRopeAntiquantScaleOptional,
47+ const aclTensor *dequantScaleQueryOptional, const aclTensor *learnableSinkOptional,
48+ const aclIntArray *qStartIdxOptional, const aclIntArray *kvStartIdxOptional, int64_t numHeads, double scaleValue,
49+ int64_t preTokens, int64_t nextTokens, char *inputLayout, int64_t numKeyValueHeads, int64_t sparseMode,
50+ int64_t innerPrecise, int64_t blockSize, int64_t antiquantMode, bool softmaxLseFlag, int64_t keyAntiquantMode,
51+ int64_t valueAntiquantMode, int64_t queryQuantMode, int64_t pseType, const aclTensor *attentionOut,
52+ const aclTensor *softmaxLse, uint64_t *workspaceSize, aclOpExecutor **executor);
53+ 
54+__attribute__((visibility("default"))) aclnnStatus CheckTensorContiguous(const aclTensorList *key,
55+ const aclTensorList *value, const aclTensor *keyAntiquantScaleOptional,
56+ const aclTensor *valueAntiquantScaleOptional, const aclTensor *keyRopeOptional);
57+ 
58+// 新版本opbase存在TensorV2的新接口,用弱符号判断当前opbase是新版本还是旧版本,旧版本不支持传入非连续tensor
59+bool NnopbaseSupportTensorV2() __attribute__((weak));
60+ 
61+aclnnStatus aclnnEagleFusedInferAttentionScoreV5GetMaxWorkspaceSize(const aclTensor *query, const aclTensorList *key,
62+ const aclTensorList *value, const aclTensor *pseShiftOptional, const aclTensor *attenMaskOptional,
63+ const aclIntArray *actualSeqLengthsOptional, const aclIntArray *actualSeqLengthsKvOptional,
64+ const aclTensor *deqScale1Optional, const aclTensor *quantScale1Optional, const aclTensor *deqScale2Optional,
65+ const aclTensor *quantScale2Optional, const aclTensor *quantOffset2Optional,
66+ const aclTensor *antiquantScaleOptional, const aclTensor *antiquantOffsetOptional,
67+ const aclTensor *blockTableOptional, const aclTensor *queryPaddingSizeOptional,
68+ const aclTensor *kvPaddingSizeOptional, const aclTensor *keyAntiquantScaleOptional,
69+ const aclTensor *keyAntiquantOffsetOptional, const aclTensor *valueAntiquantScaleOptional,
70+ const aclTensor *valueAntiquantOffsetOptional, const aclTensor *keySharedPrefixOptional,
71+ const aclTensor *valueSharedPrefixOptional, const aclIntArray *actualSharedPrefixLenOptional,
72+ const aclTensor *queryRopeOptional, const aclTensor *keyRopeOptional,
73+ const aclTensor *keyRopeAntiquantScaleOptional, const aclTensor *dequantScaleQueryOptional,
74+ const aclTensor *learnableSinkOptional, const aclIntArray *qStartIdxOptional, const aclIntArray *kvStartIdxOptional,
75+ int64_t numHeads, double scaleValue, int64_t preTokens, int64_t nextTokens, char *inputLayout,
76+ int64_t numKeyValueHeads, int64_t sparseMode, int64_t innerPrecise, int64_t blockSize, int64_t antiquantMode,
77+ bool softmaxLseFlag, int64_t keyAntiquantMode, int64_t valueAntiquantMode, int64_t queryQuantMode, int64_t pseType,
78+ const aclTensor *attentionOut, const aclTensor *softmaxLse, uint64_t *workspaceSize, aclOpExecutor **executor) {
79+ OP_LOGD("start aclnnEagleFusedInferAttentionScoreV5GetMaxWorkspaceSize");
80+ const aclTensorList *tensorListKey = key;
81+ const aclTensorList *tensorListValue = value;
82+ TensorPreProcess(tensorListKey, tensorListValue);
83+ 
84+ const aclTensor *tensorKeySharedPrefixOptional = keySharedPrefixOptional;
85+ const aclTensor *tensorValueSharedPrefixOptional = valueSharedPrefixOptional;
86+ PrefixTensorPreProcess(tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional);
87+ 
88+ aclTensor *fakeActualSeqLengthsOptional{nullptr};
89+ aclTensor *fakeActualSeqLengthsKvOptional{nullptr};
90+ aclTensor *fakeActualSharedPrefixLenOptional{nullptr};
91+ aclTensor *fakeQStartIdxOptional{nullptr};
92+ aclTensor *fakeKVStartIdxOptional{nullptr};
93+ 
94+ // nullptr不处理, nullptr是空指针,这样不会影响原来就不传入actual seq length为空的逻辑
95+ aclnnStatus ret = FakeArray(actualSeqLengthsOptional, fakeActualSeqLengthsOptional);
96+ CHECK_RET_CODE(ret, "Try alloc fake actualSeqLengthsOptional failed");
97+ 
98+ ret = FakeArray(actualSeqLengthsKvOptional, fakeActualSeqLengthsKvOptional);
99+ if (ret != ACLNN_SUCCESS) {
100+ OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "Try alloc fake actualSeqLengthsKvOptional failed");
101+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 没有返回值无需校验
102+ return ret;
103+ }
104+ 
105+ ret = FakeArray(actualSharedPrefixLenOptional, fakeActualSharedPrefixLenOptional);
106+ if (ret != ACLNN_SUCCESS) {
107+ OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "Try alloc fake actualSharedPrefixLenOptional failed");
108+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 没有返回值无需校验
109+ aclDestroyTensor(fakeActualSeqLengthsKvOptional);
110+ return ret;
111+ }
112+ 
113+ ret = FakeArray(qStartIdxOptional, fakeQStartIdxOptional);
114+ if (ret != ACLNN_SUCCESS) {
115+ OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "Try alloc fake qStartIdxOptional failed");
116+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 没有返回值无需校验
117+ aclDestroyTensor(fakeActualSeqLengthsKvOptional);
118+ aclDestroyTensor(fakeActualSharedPrefixLenOptional);
119+ return ret;
120+ }
121+ 
122+ ret = FakeArray(kvStartIdxOptional, fakeKVStartIdxOptional);
123+ if (ret != ACLNN_SUCCESS) {
124+ OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "Try alloc fake kvStartIdxOptional failed");
125+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 没有返回值无需校验
126+ aclDestroyTensor(fakeActualSeqLengthsKvOptional);
127+ aclDestroyTensor(fakeActualSharedPrefixLenOptional);
128+ aclDestroyTensor(fakeQStartIdxOptional);
129+ return ret;
130+ }
131+ 
132+ const aclTensor *placeHolder = nullptr;
133+ const aclTensor *tempTensor = nullptr;
134+ if (softmaxLseFlag == false) {
135+ std::vector<int64_t> shape = {0};
136+ int64_t addr = 0xff;
137+ tempTensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, shape.data(), 0, ACL_FORMAT_ND,
138+ shape.data(), shape.size(), static_cast<void *>(&addr));
139+ placeHolder = tempTensor;
140+ } else {
141+ placeHolder = softmaxLse;
142+ }
143+ 
144+ ret = aclnnInnerEagleFusedInferAttentionScoreTensorGetWorkspaceSize(query, tensorListKey, tensorListValue,
145+ pseShiftOptional, attenMaskOptional, fakeActualSeqLengthsOptional, fakeActualSeqLengthsKvOptional,
146+ deqScale1Optional, quantScale1Optional, deqScale2Optional, quantScale2Optional, quantOffset2Optional,
147+ antiquantScaleOptional, antiquantOffsetOptional, blockTableOptional, queryPaddingSizeOptional,
148+ kvPaddingSizeOptional, keyAntiquantScaleOptional, keyAntiquantOffsetOptional, valueAntiquantScaleOptional,
149+ valueAntiquantOffsetOptional, tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional,
150+ fakeActualSharedPrefixLenOptional, queryRopeOptional, keyRopeOptional, keyRopeAntiquantScaleOptional,
151+ dequantScaleQueryOptional, learnableSinkOptional, fakeQStartIdxOptional, fakeKVStartIdxOptional, numHeads,
152+ scaleValue, preTokens, nextTokens, inputLayout, numKeyValueHeads, sparseMode, innerPrecise, blockSize,
153+ antiquantMode, softmaxLseFlag, keyAntiquantMode, valueAntiquantMode, queryQuantMode, pseType, 0, attentionOut,
154+ placeHolder, workspaceSize, executor);
155+ if (softmaxLseFlag == false) {
156+ aclDestroyTensor(tempTensor);
157+ }
158+ aclDestroyTensor(fakeActualSeqLengthsOptional); // 只会成功,无需校验
159+ aclDestroyTensor(fakeActualSeqLengthsKvOptional);
160+ aclDestroyTensor(fakeActualSharedPrefixLenOptional);
161+ aclDestroyTensor(fakeQStartIdxOptional);
162+ aclDestroyTensor(fakeKVStartIdxOptional);
163+ return ret;
164+}
165+ 
166+aclnnStatus CheckTensorContiguous(const aclTensorList *key, const aclTensorList *value,
167+ const aclTensor *keyAntiquantScaleOptional, const aclTensor *valueAntiquantScaleOptional,
168+ const aclTensor *keyRopeOptional) {
169+ if (!IsContiguous((*key)[0]) || !IsContiguous((*value)[0])) {
atomgit-bot
atomgit-botatomgit-bot7月3日

🟡 Medium Priority

aclnn_fused_infer_attention_score_v5.cpp 第 193 行,CheckTensorContiguous 函数中直接执行 (*key)[0](*value)[0],未检查 key 或 value 是否为 nullptr 或 tensorList 是否为空。该函数在第 251 行被 aclnnEagleFusedInferAttentionScoreV5GetWorkspaceSize 调用,而 GetWorkspaceSize 是公开 API,外部调用者可能传入 nullptr。若 key 或 value 为 nullptr,解引用将导致段错误(UB)。v4 中的 CheckKVContiguous 存在同样模式,但本次新增的 v5 代码使该问题在新路径上可触发。

建议:在解引用 key/value 之前增加空指针检查,若 key 或 value 为 nullptr 则直接返回 ACLNN_ERR_INNER_NULLPTR 或等价错误码。

likedislike
170+ return ACLNN_ERR_INNER_TILING_ERROR;
171+ }
172+ if (keyRopeOptional != nullptr && !IsContiguous(keyRopeOptional)) {
173+ return ACLNN_ERR_INNER_TILING_ERROR;
174+ }
175+ if ((keyAntiquantScaleOptional != nullptr && !IsContiguous(keyAntiquantScaleOptional)) ||
176+ (valueAntiquantScaleOptional != nullptr && !IsContiguous(valueAntiquantScaleOptional))) {
177+ return ACLNN_ERR_INNER_TILING_ERROR;
178+ }
179+ return ACLNN_SUCCESS;
180+}
181+ 
182+aclnnStatus aclnnEagleFusedInferAttentionScoreV5GetWorkspaceSize(const aclTensor *query, const aclTensorList *key,
183+ const aclTensorList *value, const aclTensor *pseShiftOptional, const aclTensor *attenMaskOptional,
184+ const aclIntArray *actualSeqLengthsOptional, const aclIntArray *actualSeqLengthsKvOptional,
185+ const aclTensor *deqScale1Optional, const aclTensor *quantScale1Optional, const aclTensor *deqScale2Optional,
186+ const aclTensor *quantScale2Optional, const aclTensor *quantOffset2Optional,
187+ const aclTensor *antiquantScaleOptional, const aclTensor *antiquantOffsetOptional,
188+ const aclTensor *blockTableOptional, const aclTensor *queryPaddingSizeOptional,
189+ const aclTensor *kvPaddingSizeOptional, const aclTensor *keyAntiquantScaleOptional,
190+ const aclTensor *keyAntiquantOffsetOptional, const aclTensor *valueAntiquantScaleOptional,
191+ const aclTensor *valueAntiquantOffsetOptional, const aclTensor *keySharedPrefixOptional,
192+ const aclTensor *valueSharedPrefixOptional, const aclIntArray *actualSharedPrefixLenOptional,
193+ const aclTensor *queryRopeOptional, const aclTensor *keyRopeOptional,
194+ const aclTensor *keyRopeAntiquantScaleOptional, const aclTensor *dequantScaleQueryOptional,
195+ const aclTensor *learnableSinkOptional, const aclIntArray *qStartIdxOptional, const aclIntArray *kvStartIdxOptional,
196+ int64_t numHeads, double scaleValue, int64_t preTokens, int64_t nextTokens, char *inputLayout,
197+ int64_t numKeyValueHeads, int64_t sparseMode, int64_t innerPrecise, int64_t blockSize, int64_t antiquantMode,
198+ bool softmaxLseFlag, int64_t keyAntiquantMode, int64_t valueAntiquantMode, int64_t queryQuantMode, int64_t pseType,
199+ const aclTensor *attentionOut, const aclTensor *softmaxLse, uint64_t *workspaceSize, aclOpExecutor **executor) {
200+ const aclTensorList *tensorListKey = key;
201+ const aclTensorList *tensorListValue = value;
202+ TensorPreProcess(tensorListKey, tensorListValue);
203+ 
204+ const aclTensor *tensorKeySharedPrefixOptional = keySharedPrefixOptional;
205+ const aclTensor *tensorValueSharedPrefixOptional = valueSharedPrefixOptional;
206+ PrefixTensorPreProcess(tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional);
207+ 
208+ aclnnStatus ret =
209+ CheckTensorContiguous(key, value, keyAntiquantScaleOptional, valueAntiquantScaleOptional, keyRopeOptional);
210+ if (ret != ACLNN_SUCCESS && NnopbaseSupportTensorV2 == nullptr) {
211+ OP_LOGE(ACLNN_ERR_INNER_TILING_ERROR, "When tensor is not contiguous, opbase package version check failed");
212+ return ret;
213+ }
214+ 
215+ const aclTensor *placeHolder = nullptr;
216+ const aclTensor *tempTensor = nullptr;
217+ if (softmaxLseFlag == false) {
218+ std::vector<int64_t> shape = {0};
219+ int64_t addr = 0xff;
220+ tempTensor = aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, shape.data(), 0, ACL_FORMAT_ND,
221+ shape.data(), shape.size(), static_cast<void *>(&addr));
222+ placeHolder = tempTensor;
223+ } else {
224+ placeHolder = softmaxLse;
225+ }
226+ ret = aclnnInnerEagleFusedInferAttentionScoreGetWorkspaceSize(query, tensorListKey, tensorListValue,
227+ pseShiftOptional, attenMaskOptional, actualSeqLengthsOptional, actualSeqLengthsKvOptional, deqScale1Optional,
228+ quantScale1Optional, deqScale2Optional, quantScale2Optional, quantOffset2Optional, antiquantScaleOptional,
229+ antiquantOffsetOptional, blockTableOptional, queryPaddingSizeOptional, kvPaddingSizeOptional,
230+ keyAntiquantScaleOptional, keyAntiquantOffsetOptional, valueAntiquantScaleOptional,
231+ valueAntiquantOffsetOptional, tensorKeySharedPrefixOptional, tensorValueSharedPrefixOptional,
232+ actualSharedPrefixLenOptional, queryRopeOptional, keyRopeOptional, keyRopeAntiquantScaleOptional,
233+ dequantScaleQueryOptional, learnableSinkOptional, qStartIdxOptional, kvStartIdxOptional, numHeads, scaleValue,
234+ preTokens, nextTokens, inputLayout, numKeyValueHeads, sparseMode, innerPrecise, blockSize, antiquantMode,
235+ softmaxLseFlag, keyAntiquantMode, valueAntiquantMode, queryQuantMode, pseType, 0, attentionOut, placeHolder,
236+ workspaceSize, executor);
237+ if (softmaxLseFlag == false) {
238+ aclDestroyTensor(tempTensor);
239+ }
240+ return ret;
241+}
242+ 
243+aclnnStatus aclnnEagleFusedInferAttentionScoreV5(
244+ void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, const aclrtStream stream) {
245+ return aclnnInnerEagleFusedInferAttentionScore(workspace, workspaceSize, executor, stream);
246+}
247+ 
248+#ifdef __cplusplus
249+}
250+#endif
@@ -0,0 +1,39 @@
1+/**
2+ * Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
3+ * MindIE is licensed under Mulan PSL v2.
4+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
5+ * You may obtain a copy of Mulan PSL v2 at:
6+ * http://license.coscl.org.cn/MulanPSL2
7+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10+ * See the Mulan PSL v2 for more details.
11+ */
12+ 
13+#ifndef ACLNN_FUSED_INFER_ATTENTION_SCORE_INNER_H_
14+#define ACLNN_FUSED_INFER_ATTENTION_SCORE_INNER_H_
15+#define ACLNN_API __attribute__((visibility("default")))
16+ 
17+#include "aclnn/aclnn_base.h"
18+ 
19+#ifdef __cplusplus
20+extern "C" {
21+#endif
22+ 
23+void TensorPreProcess(const aclTensorList *&tensorListKey, const aclTensorList *&tensorListValue);
24+void PrefixTensorPreProcess(const aclTensor *&tensorKey, const aclTensor *&tensorValue);
25+aclnnStatus FakeArray(const aclIntArray *inArray, aclTensor *&outArray);
26+ 
27+void FusedInferAttentionScoreProcessSoftmaxLse(
28+ bool softmaxLseFlag, const aclTensor *softmaxLse, const aclTensor *&tempTensor, const aclTensor *&placeHolder);
29+ 
30+aclnnStatus CheckKVContiguous(const aclTensorList *key, const aclTensorList *value);
31+ 
32+// 新版本opbase存在TensorV2的新接口,用弱符号判断当前opbase是新版本还是旧版本,旧版本不支持传入非连续tensor
33+bool NnopbaseSupportTensorV2() __attribute__((weak));
34+ 
35+#ifdef __cplusplus
36+}
37+#endif
38+ 
39+#endif
@@ -0,0 +1,13 @@
1+# Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
2+# MindIE is licensed under Mulan PSL v2.
3+# You can use this software according to the terms and conditions of the Mulan PSL v2.
4+# You may obtain a copy of Mulan PSL v2 at:
5+# http://license.coscl.org.cn/MulanPSL2
6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
7+# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
8+# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
9+# See the Mulan PSL v2 for more details.
10+ 
11+if (BUILD_OPEN_PROJECT)
12+ add_graph_plugin_sources()
13+endif()
@@ -0,0 +1,355 @@
1+/**
2+ * Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
3+ * MindIE is licensed under Mulan PSL v2.
4+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
5+ * You may obtain a copy of Mulan PSL v2 at:
6+ * http://license.coscl.org.cn/MulanPSL2
7+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10+ * See the Mulan PSL v2 for more details.
11+ */
12+ 
13+/*!
14+ * \file fallback_fused_infer_attention_score.cpp
15+ * \brief
16+ */
17+ 
18+#include "log/log.h"
19+#include "log/error_code.h"
20+#include "fallback/fallback_comm.h"
21+#include "fallback/fallback.h"
22+#include "../op_api/aclnn_fused_infer_attention_score_v5.h"
23+ 
24+#ifdef __cplusplus
25+extern "C" {
26+#endif
27+namespace fallback {
28+ 
29+using namespace ge;
30+using namespace gert;
31+static const size_t QUERY_INDEX = 0;
32+static const size_t KEY_INDEX = 1;
33+static const size_t VALUE_INDEX = 2;
34+static const size_t PSE_SHIFT_INDEX = 3;
35+static const size_t ATTEN_MASK_INDEX = 4;
36+static const size_t ACTUAL_SEQ_Q_INDEX = 5;
37+static const size_t ACTUAL_SEQ_KV_INDEX = 6;
38+static const size_t DEQUANT_SCALE1_INDEX = 7;
39+static const size_t QUANT_SCALE1_INDEX = 8;
40+static const size_t DEQUANT_SCALE2_INDEX = 9;
41+static const size_t QUANT_SCALE2_INDEX = 10;
42+static const size_t QUANT_OFFSET2_INDEX = 11;
43+static const size_t ANTIQUANT_SCALE_INDEX = 12;
44+static const size_t ANTIQUANT_OFFSET_INDEX = 13;
45+static const size_t BLOCK_TABLE_INDEX = 14;
46+static const size_t QUERY_PADDING_INDEX = 15;
47+static const size_t KV_PADDING_INDEX = 16;
48+static const size_t KEY_ANTIQUANT_SCALE_INDEX = 17;
49+static const size_t KEY_ANTIQUANT_OFFSET_INDEX = 18;
50+static const size_t VALUE_ANTIQUANT_SCALE_INDEX = 19;
51+static const size_t VALUE_ANTIQUANT_OFFSET_INDEX = 20;
52+static const size_t KEY_SHARED_PREFIX_INDEX = 21;
53+static const size_t VALUE_SHARED_PREFIX_INDEX = 22;
54+static const size_t ACTUAL_SHARED_PREFIX_LEN_INDEX = 23;
55+static const size_t QUERY_ROPE_INDEX = 24;
56+static const size_t KEY_ROPE_INDEX = 25;
57+static const size_t KEY_ROPE_ANTIQUANT_SCALE_INDEX = 26;
58+static const size_t DEQUANT_SCALE_QUERY_INDEX = 27;
59+static const size_t LEARNABLE_SINK_INDEX = 28;
60+ 
61+static const size_t ATTR_N_INDEX = 0;
62+static const size_t ATTR_SCALE_INDEX = 1;
63+static const size_t ATTR_PRE_TOKEN_INDEX = 2;
64+static const size_t ATTR_NEXT_TOKEN_INDEX = 3;
65+static const size_t ATTR_INPUT_LAYOUT_INDEX = 4;
66+static const size_t ATTR_NUM_KV_HEADS_INDEX = 5;
67+static const size_t ATTR_SPARSE_MODE_INDEX = 6;
68+static const size_t ATTR_INNER_PRECISE_INDEX = 7;
69+static const size_t ATTR_BLOCK_SIZE_INDEX = 8;
70+static const size_t ATTR_ANTIQUANT_MODE_INDEX = 9;
71+static const size_t ATTR_SOFTMAX_LSE_FLAG_INDEX = 10;
72+static const size_t ATTR_KEY_ANTIQUANT_MODE_INDEX = 11;
73+static const size_t ATTR_VALUE_ANTIQUANT_MODE_INDEX = 12;
74+static const size_t ATTR_QUERY_QUANT_MODE_INDEX = 13;
75+static const size_t ATTR_PSE_TYPE_INDEX = 14;
76+ 
77+static const size_t ATTENTION_OUT_INDEX = 0;
78+static const size_t SOFTMAX_LSE_INDEX = 1;
79+ 
80+static constexpr int64_t SPARSE_MODE_INT_MAX = 2147483647;
81+ 
82+struct FusedInferHostTensorParams {
83+ const gert::Tensor *query = nullptr;
84+ const gert::Tensor *key = nullptr;
85+ const gert::Tensor *value = nullptr;
86+ const gert::Tensor *output = nullptr;
87+ const gert::Tensor *softmaxLse = nullptr;
88+ const gert::Tensor *pseShiftGe = nullptr;
89+ const gert::Tensor *attenMaskGe = nullptr;
90+ const gert::Tensor *actualSeqLengthsGe = nullptr;
91+ const gert::Tensor *actualSeqLengthsGeKv = nullptr;
92+ const gert::Tensor *deqScale1 = nullptr;
93+ const gert::Tensor *quantScale1 = nullptr;
94+ const gert::Tensor *deqScale2 = nullptr;
95+ const gert::Tensor *quantScale2 = nullptr;
96+ const gert::Tensor *quantOffset2 = nullptr;
97+ const gert::Tensor *antiquantScaleGe = nullptr;
98+ const gert::Tensor *antiquantOffsetGe = nullptr;
99+ const gert::Tensor *blocktableGe = nullptr;
100+ const gert::Tensor *queryPaddingGe = nullptr;
101+ const gert::Tensor *kvPaddingGe = nullptr;
102+ const gert::Tensor *keyAntiquantScaleGe = nullptr;
103+ const gert::Tensor *keyAntiquantOffsetGe = nullptr;
104+ const gert::Tensor *valueAntiquantScaleGe = nullptr;
105+ const gert::Tensor *valueAntiquantOffsetGe = nullptr;
106+ const gert::Tensor *keySharedPrefixGe = nullptr;
107+ const gert::Tensor *valueSharedPrefixGe = nullptr;
108+ const gert::Tensor *actualSharedPrefixLenGe = nullptr;
109+ const gert::Tensor *queryRopeGe = nullptr;
110+ const gert::Tensor *keyRopeGe = nullptr;
111+ const gert::Tensor *keyRopeAntiquantScaleGe = nullptr;
112+ const gert::Tensor *dequantScaleQueryGe = nullptr;
113+ const gert::Tensor *learnableSinkGe = nullptr;
114+ const gert::Tensor *qStartIdx = nullptr; // not supported in Pytorch interfaces, default nullptr
115+ const gert::Tensor *kvStartIdx = nullptr; // not supported in Pytorch interfaces, default nullptr
116+};
117+ 
118+static graphStatus FiaFillTensorParams(const OpExecuteContext *host_api_ctx, FusedInferHostTensorParams &fiaTensors) {
119+ fiaTensors.query = host_api_ctx->GetInputTensor(QUERY_INDEX);
120+ if (fiaTensors.query == nullptr) {
121+ OP_LOGE_WITH_INVALID_INPUT(host_api_ctx->GetNodeName(), "query");
122+ return GRAPH_FAILED;
123+ }
124+ 
125+ fiaTensors.key = host_api_ctx->GetDynamicInputTensor(KEY_INDEX, 0);
126+ if (fiaTensors.key == nullptr) {
127+ OP_LOGE_WITH_INVALID_INPUT(host_api_ctx->GetNodeName(), "key");
128+ return GRAPH_FAILED;
129+ }
130+ 
131+ fiaTensors.value = host_api_ctx->GetDynamicInputTensor(VALUE_INDEX, 0);
132+ if (fiaTensors.value == nullptr) {
133+ OP_LOGE_WITH_INVALID_INPUT(host_api_ctx->GetNodeName(), "value");
134+ return GRAPH_FAILED;
135+ }
136+ 
137+ fiaTensors.output = host_api_ctx->GetOutputTensor(ATTENTION_OUT_INDEX);
138+ if (fiaTensors.output == nullptr) {
139+ OP_LOGE_WITH_INVALID_INPUT(host_api_ctx->GetNodeName(), "output");
140+ return GRAPH_FAILED;
141+ }
142+ 
143+ fiaTensors.softmaxLse = host_api_ctx->GetOutputTensor(SOFTMAX_LSE_INDEX);
144+ if (fiaTensors.softmaxLse == nullptr) {
145+ OP_LOGE_WITH_INVALID_INPUT(host_api_ctx->GetNodeName(), "softmaxLse");
146+ return GRAPH_FAILED;
147+ }
148+ 
149+ fiaTensors.pseShiftGe = host_api_ctx->GetOptionalInputTensor(PSE_SHIFT_INDEX);
150+ fiaTensors.attenMaskGe = host_api_ctx->GetOptionalInputTensor(ATTEN_MASK_INDEX);
151+ fiaTensors.actualSeqLengthsGe = host_api_ctx->GetOptionalInputTensor(ACTUAL_SEQ_Q_INDEX);
152+ fiaTensors.actualSeqLengthsGeKv = host_api_ctx->GetOptionalInputTensor(ACTUAL_SEQ_KV_INDEX);
153+ fiaTensors.deqScale1 = host_api_ctx->GetOptionalInputTensor(DEQUANT_SCALE1_INDEX);
154+ fiaTensors.quantScale1 = host_api_ctx->GetOptionalInputTensor(QUANT_SCALE1_INDEX);
155+ fiaTensors.deqScale2 = host_api_ctx->GetOptionalInputTensor(DEQUANT_SCALE2_INDEX);
156+ fiaTensors.quantScale2 = host_api_ctx->GetOptionalInputTensor(QUANT_SCALE2_INDEX);
157+ fiaTensors.quantOffset2 = host_api_ctx->GetOptionalInputTensor(QUANT_OFFSET2_INDEX);
158+ fiaTensors.antiquantScaleGe = host_api_ctx->GetOptionalInputTensor(ANTIQUANT_SCALE_INDEX);
159+ fiaTensors.antiquantOffsetGe = host_api_ctx->GetOptionalInputTensor(ANTIQUANT_OFFSET_INDEX);
160+ fiaTensors.blocktableGe = host_api_ctx->GetOptionalInputTensor(BLOCK_TABLE_INDEX);
161+ fiaTensors.queryPaddingGe = host_api_ctx->GetOptionalInputTensor(QUERY_PADDING_INDEX);
162+ fiaTensors.kvPaddingGe = host_api_ctx->GetOptionalInputTensor(KV_PADDING_INDEX);
163+ fiaTensors.keyAntiquantScaleGe = host_api_ctx->GetOptionalInputTensor(KEY_ANTIQUANT_SCALE_INDEX);
164+ fiaTensors.keyAntiquantOffsetGe = host_api_ctx->GetOptionalInputTensor(KEY_ANTIQUANT_OFFSET_INDEX);
165+ fiaTensors.valueAntiquantScaleGe = host_api_ctx->GetOptionalInputTensor(VALUE_ANTIQUANT_SCALE_INDEX);
166+ fiaTensors.valueAntiquantOffsetGe = host_api_ctx->GetOptionalInputTensor(VALUE_ANTIQUANT_OFFSET_INDEX);
167+ fiaTensors.keySharedPrefixGe = host_api_ctx->GetOptionalInputTensor(KEY_SHARED_PREFIX_INDEX);
168+ fiaTensors.valueSharedPrefixGe = host_api_ctx->GetOptionalInputTensor(VALUE_SHARED_PREFIX_INDEX);
169+ fiaTensors.actualSharedPrefixLenGe = host_api_ctx->GetOptionalInputTensor(ACTUAL_SHARED_PREFIX_LEN_INDEX);
170+ fiaTensors.queryRopeGe = host_api_ctx->GetOptionalInputTensor(QUERY_ROPE_INDEX);
171+ fiaTensors.keyRopeGe = host_api_ctx->GetOptionalInputTensor(KEY_ROPE_INDEX);
172+ fiaTensors.keyRopeAntiquantScaleGe = host_api_ctx->GetOptionalInputTensor(KEY_ROPE_ANTIQUANT_SCALE_INDEX);
173+ fiaTensors.dequantScaleQueryGe = host_api_ctx->GetOptionalInputTensor(DEQUANT_SCALE_QUERY_INDEX);
174+ fiaTensors.learnableSinkGe = host_api_ctx->GetOptionalInputTensor(LEARNABLE_SINK_INDEX);
175+ 
176+ return GRAPH_SUCCESS;
177+}
178+ 
179+struct ActualSeqInfo {
180+ std::vector<int64_t> actSeqArray;
181+ std::vector<int64_t> actSeqArrayKv;
182+ std::vector<int64_t> actSeqSharedPrefix;
183+};
184+ 
185+static void FillActualSeqInfo(const FusedInferHostTensorParams &fiaTensors, ActualSeqInfo &actualSeqInfo) {
186+ if (fiaTensors.actualSeqLengthsGe != nullptr) {
187+ const int64_t *actSeqData = fiaTensors.actualSeqLengthsGe->GetData<int64_t>();
188+ const size_t len = static_cast<size_t>(fiaTensors.actualSeqLengthsGe->GetShapeSize());
189+ for (size_t i = 0; i < len; i++) {
190+ actualSeqInfo.actSeqArray.push_back(actSeqData[i]);
191+ }
192+ }
193+ 
194+ if (fiaTensors.actualSeqLengthsGeKv != nullptr) {
195+ const int64_t *actSeqData = fiaTensors.actualSeqLengthsGeKv->GetData<int64_t>();
196+ const size_t len = static_cast<size_t>(fiaTensors.actualSeqLengthsGeKv->GetShapeSize());
197+ for (size_t i = 0; i < len; i++) {
198+ actualSeqInfo.actSeqArrayKv.push_back(actSeqData[i]);
199+ }
200+ }
201+ 
202+ std::vector<int64_t> actSeqSharedPrefix;
203+ if (fiaTensors.actualSharedPrefixLenGe != nullptr) {
204+ const int64_t *actSeqData = fiaTensors.actualSharedPrefixLenGe->GetData<int64_t>();
205+ const size_t len = static_cast<size_t>(fiaTensors.actualSharedPrefixLenGe->GetShapeSize());
206+ for (size_t i = 0; i < len; i++) {
207+ actualSeqInfo.actSeqSharedPrefix.push_back(actSeqData[i]);
208+ }
209+ }
210+}
211+ 
212+struct FusedInferHostAttrPtrs {
213+ const uint32_t *getNumHeads = nullptr;
214+ const float *scaleValue = nullptr;
215+ const int64_t *getPreTokens = nullptr;
216+ const int64_t *getNextTokens = nullptr;
217+ const char *layout = nullptr;
218+ const uint32_t *getKVHeadNum = nullptr;
219+ const uint32_t *getSparseMode = nullptr;
220+ const uint32_t *getInnerPrecise = nullptr;
221+ const uint32_t *getBlockSize = nullptr;
222+ const uint32_t *getAntiquantMode = nullptr;
223+ const bool *getSoftmaxLseFlag = nullptr;
224+ const uint32_t *getKeyAntiquantMode = nullptr;
225+ const uint32_t *getValueAntiquantMode = nullptr;
226+ const uint32_t *getQueryQuantMode = nullptr;
227+ const int64_t *getPseType = nullptr;
228+};
229+ 
230+static void FillAttrPointers(const gert::RuntimeAttrs *attrs, FusedInferHostAttrPtrs &attrPtrs) {
231+ attrPtrs.getNumHeads = attrs->GetAttrPointer<uint32_t>(ATTR_N_INDEX);
232+ attrPtrs.scaleValue = attrs->GetAttrPointer<float>(ATTR_SCALE_INDEX);
233+ attrPtrs.getPreTokens = attrs->GetAttrPointer<int64_t>(ATTR_PRE_TOKEN_INDEX);
234+ attrPtrs.getNextTokens = attrs->GetAttrPointer<int64_t>(ATTR_NEXT_TOKEN_INDEX);
235+ attrPtrs.layout = attrs->GetAttrPointer<char>(ATTR_INPUT_LAYOUT_INDEX);
236+ attrPtrs.getKVHeadNum = attrs->GetAttrPointer<uint32_t>(ATTR_NUM_KV_HEADS_INDEX);
237+ attrPtrs.getSparseMode = attrs->GetAttrPointer<uint32_t>(ATTR_SPARSE_MODE_INDEX);
238+ attrPtrs.getInnerPrecise = attrs->GetAttrPointer<uint32_t>(ATTR_INNER_PRECISE_INDEX);
239+ attrPtrs.getBlockSize = attrs->GetAttrPointer<uint32_t>(ATTR_BLOCK_SIZE_INDEX);
240+ attrPtrs.getAntiquantMode = attrs->GetAttrPointer<uint32_t>(ATTR_ANTIQUANT_MODE_INDEX);
241+ attrPtrs.getSoftmaxLseFlag = attrs->GetAttrPointer<bool>(ATTR_SOFTMAX_LSE_FLAG_INDEX);
242+ attrPtrs.getKeyAntiquantMode = attrs->GetAttrPointer<uint32_t>(ATTR_KEY_ANTIQUANT_MODE_INDEX);
243+ attrPtrs.getValueAntiquantMode = attrs->GetAttrPointer<uint32_t>(ATTR_VALUE_ANTIQUANT_MODE_INDEX);
244+ attrPtrs.getQueryQuantMode = attrs->GetAttrPointer<uint32_t>(ATTR_QUERY_QUANT_MODE_INDEX);
245+ attrPtrs.getPseType = attrs->GetAttrPointer<int64_t>(ATTR_PSE_TYPE_INDEX);
246+}
247+ 
248+struct FusedInferHostScalarParams {
249+ int64_t numHeads = 1;
250+ double dScaleValue = 1.0f;
251+ int64_t preTokens = SPARSE_MODE_INT_MAX;
252+ int64_t nextTokens = SPARSE_MODE_INT_MAX;
253+ int64_t kvHeadNum = 0;
254+ int64_t sparseMode = 0;
255+ int64_t innerPrecise = 1;
256+ int64_t blockSize = 0;
257+ int64_t antiquantMode = 0;
258+ bool softmaxLseFlag = false;
259+ int64_t keyAntiquantMode = 0;
260+ int64_t valueAntiquantMode = 0;
261+ int64_t queryQuantMode = 0;
262+ int64_t pseType = 0; // not supported in Pytorch interfaces, default 0
263+};
264+ 
265+static void GetFusedInferHostScalarParams(
266+ const FusedInferHostAttrPtrs &attrPointers, FusedInferHostScalarParams &params) {
267+ params.numHeads = *(attrPointers.getNumHeads);
268+ params.dScaleValue = *(attrPointers.scaleValue);
269+ params.preTokens = *(attrPointers.getPreTokens);
270+ params.nextTokens = *(attrPointers.getNextTokens);
271+ params.kvHeadNum = *(attrPointers.getKVHeadNum);
272+ params.sparseMode = *(attrPointers.getSparseMode);
273+ params.innerPrecise = *(attrPointers.getInnerPrecise);
274+ params.blockSize = *(attrPointers.getBlockSize);
275+ params.antiquantMode = *(attrPointers.getAntiquantMode);
276+ params.softmaxLseFlag = *(attrPointers.getSoftmaxLseFlag);
277+ params.keyAntiquantMode = *(attrPointers.getKeyAntiquantMode);
278+ params.valueAntiquantMode = *(attrPointers.getValueAntiquantMode);
279+ params.queryQuantMode = *(attrPointers.getQueryQuantMode);
280+ params.pseType = *(attrPointers.getPseType);
281+}
atomgit-bot
atomgit-botatomgit-bot7月3日

🟠 High Priority

在 fallback_fused_infer_attention_score.cpp 中,FillAttrPointers 函数(第 232-249 行)通过 attrs->GetAttrPointer(index) 获取属性指针,但未检查返回值是否为 nullptr。随后 GetFusedInferHostScalarParams 函数(第 268-284 行)直接对所有指针进行解引用(如 (attrPointers.getNumHeads)、(attrPointers.scaleValue) 等),不做任何空指针检查。如果算子图中某个属性缺失,GetAttrPointer 返回 nullptr,将导致运行时段错误崩溃。受影响的所有属性包括:numHeads、scaleValue、preTokens、nextTokens、layout、kvHeadNum、sparseMode、innerPrecise、blockSize、antiquantMode、softmaxLseFlag、keyAntiquantMode、valueAntiquantMode、queryQuantMode、pseType,共计 15 个指针。

建议:在 FillAttrPointers 中对每个 GetAttrPointer 返回值做空指针检查,若为 nullptr 则记录错误日志并返回失败(或抛出/返回错误码);或者在 GetFusedInferHostScalarParams 解引用之前逐个判空并提前退出。推荐在 FillAttrPointers 中集中校验,将错误尽早暴露。

likedislike
282+ 
283+static graphStatus FusedInferHostExecuteFunc(OpExecuteContext *host_api_ctx) {
284+ OP_CHECK_IF(host_api_ctx == nullptr, OP_LOGE("aclnnfallback", "host_api_ctx is null"), return GRAPH_FAILED);
285+ FusedInferHostTensorParams fiaTensors{};
286+ auto apiRet = FiaFillTensorParams(host_api_ctx, fiaTensors);
287+ OP_CHECK_IF(apiRet != GRAPH_SUCCESS, OP_LOGE("aclnnfallback", "Input Tensors invalid"), return GRAPH_FAILED);
288+ 
289+ std::vector<const gert::Tensor *> ge_tenserListKey;
290+ ge_tenserListKey.push_back(fiaTensors.key);
291+ 
292+ std::vector<const gert::Tensor *> ge_tenserListValue;
293+ ge_tenserListValue.push_back(fiaTensors.value);
294+ 
295+ ActualSeqInfo actualSeqInfo{};
296+ FillActualSeqInfo(fiaTensors, actualSeqInfo);
297+ 
298+ FusedInferHostAttrPtrs attrPointers{};
299+ auto attrs = host_api_ctx->GetAttrs();
300+ OP_CHECK_IF(attrs == nullptr, OP_LOGE("aclnnfallback", "host_api_ctx Attrs is null"), return GRAPH_FAILED);
301+ FillAttrPointers(attrs, attrPointers);
302+ 
303+ FusedInferHostScalarParams scalarParams{};
304+ GetFusedInferHostScalarParams(attrPointers, scalarParams);
305+ 
306+ if (scalarParams.innerPrecise < 0 ||
307+ scalarParams.innerPrecise >
308+ 3) { // innerPrecise=2,3 corresponds to rows with invalid high precision and high performance
309+ std::string reason = "The value of inner_precise must be in 0, 1, 2, 3";
310+ OP_LOGE_FOR_INVALID_VALUE_WITH_REASON(host_api_ctx->GetNodeName(), "inner_precise",
311+ std::to_string(scalarParams.innerPrecise).c_str(), reason.c_str());
312+ return GRAPH_FAILED;
313+ }
314+ OP_LOGD(host_api_ctx->GetNodeName(), "FusedInferAttentionScore fallback begin, numHeads = %ld, dScaleValue = %lf",
315+ scalarParams.numHeads, scalarParams.dScaleValue);
316+ OP_LOGD(host_api_ctx->GetNodeName(),
317+ "preTokens = %ld, nextTokens = %ld, kvHeadNum = %ld, sparseMode = %ld, innerPrecise = %ld",
318+ scalarParams.preTokens, scalarParams.nextTokens, scalarParams.kvHeadNum, scalarParams.sparseMode,
319+ scalarParams.innerPrecise);
320+ 
321+ if (scalarParams.sparseMode >= 10 && scalarParams.sparseMode <= 14) { // 10: min 14: max
322+ scalarParams.innerPrecise = 0;
323+ scalarParams.sparseMode -= 10; // subtract 10 to modify sparseMode
324+ OP_LOGD(host_api_ctx->GetNodeName(),
325+ "because sparseMode in range [10, 14], after modification, sparseMode = %ld, innerPrecise = %ld.",
326+ scalarParams.sparseMode, scalarParams.innerPrecise);
327+ }
328+ 
329+ apiRet = EXEC_OPAPI_CMD(aclnnEagleFusedInferAttentionScoreV5, fiaTensors.query, ge_tenserListKey,
330+ ge_tenserListValue, fiaTensors.pseShiftGe, fiaTensors.attenMaskGe, actualSeqInfo.actSeqArray,
331+ actualSeqInfo.actSeqArrayKv, fiaTensors.deqScale1, fiaTensors.quantScale1, fiaTensors.deqScale2,
332+ fiaTensors.quantScale2, fiaTensors.quantOffset2, fiaTensors.antiquantScaleGe, fiaTensors.antiquantOffsetGe,
333+ fiaTensors.blocktableGe, fiaTensors.queryPaddingGe, fiaTensors.kvPaddingGe, fiaTensors.keyAntiquantScaleGe,
334+ fiaTensors.keyAntiquantOffsetGe, fiaTensors.valueAntiquantScaleGe, fiaTensors.valueAntiquantOffsetGe,
335+ fiaTensors.keySharedPrefixGe, fiaTensors.valueSharedPrefixGe, actualSeqInfo.actSeqSharedPrefix,
336+ fiaTensors.queryRopeGe, fiaTensors.keyRopeGe, fiaTensors.keyRopeAntiquantScaleGe,
337+ fiaTensors.dequantScaleQueryGe, fiaTensors.learnableSinkGe, fiaTensors.qStartIdx, fiaTensors.kvStartIdx,
338+ scalarParams.numHeads, scalarParams.dScaleValue, scalarParams.preTokens, scalarParams.nextTokens,
339+ attrPointers.layout, scalarParams.kvHeadNum, scalarParams.sparseMode, scalarParams.innerPrecise,
340+ scalarParams.blockSize, scalarParams.antiquantMode, scalarParams.softmaxLseFlag, scalarParams.keyAntiquantMode,
341+ scalarParams.valueAntiquantMode, scalarParams.queryQuantMode, scalarParams.pseType, fiaTensors.output,
342+ fiaTensors.softmaxLse);
343+ 
344+ OP_CHECK_IF(
345+ apiRet != GRAPH_SUCCESS, OP_LOGE(host_api_ctx->GetNodeName(), "apiRet failed:%u", apiRet), return GRAPH_FAILED);
346+ 
347+ return GRAPH_SUCCESS;
348+}
349+ 
350+IMPL_OP(EagleFusedInferAttentionScore).OpExecuteFunc(FusedInferHostExecuteFunc).HostInputs({5, 6, 23});
351+} // namespace fallback
352+ 
353+#ifdef __cplusplus
354+}
355+#endif