Merged
fix(cumsum): 修复整数空Tensor tiling除零 #7177
fix(cumsum): 修复整数空Tensor tiling除零 #7177
Merged
wangweidongAdd on 4 days ago
Total: 4 files changed+68-20
@@ -328,6 +328,13 @@ ge::graphStatus Cumsum4IntTiling::CalcTilingData()
328 OP_LOGE(context_->GetNodeName(), "Cumsum4IntTiling failed to get input shape info."),328 OP_LOGE(context_->GetNodeName(), "Cumsum4IntTiling failed to get input shape info."),
329 return ge::GRAPH_FAILED);329 return ge::GRAPH_FAILED);
330 330 
331+ if (leftAxisLen == 0 || midAxisLen == 0 || rightAxisLen == 0) {
332+ tilingKey_ = CUM_EMPTY;
333+ usedCoreCnt_ = 1;
334+ OP_LOGI(context_->GetNodeName(), "Cumsum integer empty tensor, skip kernel computation.");
335+ return ge::GRAPH_SUCCESS;
336+ }
337+ 
331 GetAxisLpUnit();338 GetAxisLpUnit();
332 GetMCTilingInfo();339 GetMCTilingInfo();
333 CalcTilingKey();340 CalcTilingKey();
@@ -1,5 +1,5 @@
1/**1/**
2-* Copyright (c) 2025 Huawei Technologies Co., Ltd.2+ * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 * CANN Open Software License Agreement Version 2.0 (the "License").4 * CANN Open Software License Agreement Version 2.0 (the "License").
5 * Please refer to the License for details. You may not use this file except in compliance with the License.5 * Please refer to the License for details. You may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@ END_TILING_DATA_DEF;
47REGISTER_TILING_DATA_CLASS(Cumsum_11000, Cum4IntTilingData);47REGISTER_TILING_DATA_CLASS(Cumsum_11000, Cum4IntTilingData);
48REGISTER_TILING_DATA_CLASS(Cumsum_11001, Cum4IntTilingData);48REGISTER_TILING_DATA_CLASS(Cumsum_11001, Cum4IntTilingData);
49REGISTER_TILING_DATA_CLASS(Cumsum_11002, Cum4IntTilingData);49REGISTER_TILING_DATA_CLASS(Cumsum_11002, Cum4IntTilingData);
50+REGISTER_TILING_DATA_CLASS(Cumsum_11003, Cum4IntTilingData);
50 51 
51ge::graphStatus TilingCumsum4Int(gert::TilingContext* context);52ge::graphStatus TilingCumsum4Int(gert::TilingContext* context);
52 53 
@@ -56,6 +57,7 @@ constexpr int64_t CORE_GATE = 4;
56constexpr int64_t CUM_NO_SPLIT = 11000;57constexpr int64_t CUM_NO_SPLIT = 11000;
57constexpr int64_t CUM_AR_SPLIT = 11001;58constexpr int64_t CUM_AR_SPLIT = 11001;
58constexpr int64_t CUM_WITH_GROUP = 11002;59constexpr int64_t CUM_WITH_GROUP = 11002;
60+constexpr int64_t CUM_EMPTY = 11003;
59constexpr int64_t MAX_TENSOR_SIZE = 0xff00; // to avoid index overflow when B861constexpr int64_t MAX_TENSOR_SIZE = 0xff00; // to avoid index overflow when B8
60 62 
61class Cumsum4IntTiling {63class Cumsum4IntTiling {
@@ -98,24 +100,24 @@ private:
98 int64_t maxTensorSize = 0;100 int64_t maxTensorSize = 0;
99 int64_t rsvUB = 2048;101 int64_t rsvUB = 2048;
100 102 
101- int64_t tilingKey_;103+ int64_t tilingKey_{0};
102- int64_t isExclusive_;104+ int64_t isExclusive_{0};
103- int64_t isReverse_;105+ int64_t isReverse_{0};
104- int64_t isRBlockAxis_;106+ int64_t isRBlockAxis_{0};
105- int64_t tensorSize_;107+ int64_t tensorSize_{0};
106- int64_t usedCoreCnt_;108+ int64_t usedCoreCnt_{0};
107- int64_t blockOffset_;109+ int64_t blockOffset_{0};
108- int64_t ntcLALen_;110+ int64_t ntcLALen_{0};
109- int64_t tcLALen_;111+ int64_t tcLALen_{0};
110- int64_t laLpUnit_;112+ int64_t laLpUnit_{0};
111- int64_t laOffset_;113+ int64_t laOffset_{0};
112- int64_t ntcRLen_;114+ int64_t ntcRLen_{0};
113- int64_t tcRLen_;115+ int64_t tcRLen_{0};
114- int64_t rLpUnit_;116+ int64_t rLpUnit_{0};
115- int64_t rOffset_;117+ int64_t rOffset_{0};
116- int64_t ntcRALen_;118+ int64_t ntcRALen_{0};
117- int64_t tcRALen_;119+ int64_t tcRALen_{0};
118- int64_t raLpUnit_;120+ int64_t raLpUnit_{0};
119};121};
120} // namespace cumsum122} // namespace cumsum
121 123 
@@ -42,6 +42,7 @@ using namespace Cum;
42#define CUM_NO_SPLIT 1100042#define CUM_NO_SPLIT 11000
43#define CUM_AR_SPLIT 1100143#define CUM_AR_SPLIT 11001
44#define CUM_WITH_GROUP 1100244#define CUM_WITH_GROUP 11002
45+#define CUM_EMPTY 11003
45 46 
46static __aicore__ inline void cumsumSimd(GM_ADDR x, GM_ADDR axis, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling)47static __aicore__ inline void cumsumSimd(GM_ADDR x, GM_ADDR axis, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling)
47{48{
@@ -182,7 +183,11 @@ static __aicore__ inline void cumsumSimdInt(GM_ADDR x, GM_ADDR axis, GM_ADDR y,
182 TPipe pipe;183 TPipe pipe;
183 KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_AIV_ONLY);184 KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_AIV_ONLY);
184 185 
185- if (TILING_KEY_IS(CUM_NO_SPLIT)) {186+ if (TILING_KEY_IS(CUM_EMPTY)) {
187+ // 空 Tensor 无数据搬运或计算。保留 tiling struct 读取,供 opc 推导该 key 的 tiling 数据大小。
188+ GET_TILING_DATA_WITH_STRUCT(Cum4IntTilingData, emptyTilingData, tiling);
189+ return;
190+ } else if (TILING_KEY_IS(CUM_NO_SPLIT)) {
atomgit-bot
atomgit-botatomgit-bot4 days ago

🟡 Medium Priority

变更点:cumsum_apt.cpp 在 cumsumSimdInt 中新增 TILING_KEY_IS(CUM_EMPTY) 空 Tensor 分支(186-189 行),配套的 tiling 兜底只加在 Cumsum4IntTiling::CalcTilingData(host 331 行)。

问题链条:本 PR 的背景说明中确认“ACLNN 通路已有 self->IsEmpty() 早返回,但 TTK kernel/GE direct 会直接进入 tiling”,因此空 Tensor 的兜底必须由算子自身在 所有 AICore 通路上完成。然而同文件的兄弟函数 cumsumSimd(half/float/bfloat16,处理 1001/1002/1011/1012/1101/1102/1111/1112/3011/3012/3112 等 key)完全没有 CUM_EMPTY 分支,host 侧的浮点 tiling 也不在本 diff 的改动范围内(只改了 cumsum_tiling_ascendc_int_arch35.*)。

失效模式:当 half/float/bfloat16 的空 Tensor 走 TTK direct(tests/st/arch35/ttk_kernel_cumsum_st.csv 这类直调)或 GE direct(不经过 ACLNN 的 IsEmpty 早返回)时,浮点 tiling 仍按原始逻辑计算,rightAxisLen/leftAxisLen/midAxisLen 为 0 会重演本 PR 描述的除 0(SIGFPE)或非法分核,kernel 侧也没有 any key 可退化为空实现 —— 即整数通路已修、浮点通路保持旧形态,两条路径的处理约定出现分歧。

建议:先确认浮点 tiling(cumsum_tiling_ascendc_arch35.cpp)是否已有空 Tensor 早返回;若没有,则在浮点/半精度 tiling 中同样下发 empty tilingKey,并在 cumsumSimd 中增加对应的空分支早返回,保持两条通路的约定一致,同时补 float 空 Tensor 的 UT/ST 用例。

likedislike
Incorrect?
186 GET_TILING_DATA_WITH_STRUCT(Cum4IntTilingData, tilingDataInt, tiling);191 GET_TILING_DATA_WITH_STRUCT(Cum4IntTilingData, tilingDataInt, tiling);
187 if constexpr (std::is_same<DTYPE_X, int32_t>::value || std::is_same<DTYPE_X, int64_t>::value ||192 if constexpr (std::is_same<DTYPE_X, int32_t>::value || std::is_same<DTYPE_X, int64_t>::value ||
188 std::is_same<DTYPE_X, int8_t>::value || std::is_same<DTYPE_X, uint8_t>::value ||193 std::is_same<DTYPE_X, int8_t>::value || std::is_same<DTYPE_X, uint8_t>::value ||
@@ -77,3 +77,37 @@ TEST_F(CumsumTiling, Cumsum_test_tiling_uint8_workspace)
77 &compileInfo);77 &compileInfo);
78 ExecuteTestCase(tilingContextPara, ge::GRAPH_SUCCESS, 11001, std::vector<size_t>{0});78 ExecuteTestCase(tilingContextPara, ge::GRAPH_SUCCESS, 11001, std::vector<size_t>{0});
79}79}
80+ 
81+TEST_F(CumsumTiling, Cumsum_test_tiling_integer_empty_tensor)
82+{
83+ optiling::CumsumCompileInfo compileInfo = {56, 253952, 0, 0, 1, 1, 0, 32, 256, 256};
84+ const std::vector<int32_t> axes = {0, 3, 5};
85+ const std::vector<ge::DataType> dtypes = {ge::DT_INT32, ge::DT_INT64, ge::DT_UINT8};
86+ 
87+ for (ge::DataType dtype : dtypes) {
88+ for (int32_t axis : axes) {
89+ SCOPED_TRACE("dtype=" + std::to_string(static_cast<int32_t>(dtype)) + ", axis=" + std::to_string(axis));
90+ gert::TilingContextPara tilingContextPara(
91+ "Cumsum",
92+ {
93+ {{{1, 2, 3, 0, 4, 5}, {1, 2, 3, 0, 4, 5}}, dtype, ge::FORMAT_ND},
94+ {{{1}, {1}}, ge::DT_INT32, ge::FORMAT_ND, true, &axis},
95+ },
96+ {
97+ {{{1, 2, 3, 0, 4, 5}, {1, 2, 3, 0, 4, 5}}, dtype, ge::FORMAT_ND},
98+ },
99+ {
100+ gert::TilingContextPara::OpAttr("exclusive", Ops::Math::AnyValue::CreateFrom<bool>(false)),
101+ gert::TilingContextPara::OpAttr("reverse", Ops::Math::AnyValue::CreateFrom<bool>(false)),
102+ },
103+ &compileInfo);
104+ 
105+ TilingInfo tilingInfo;
106+ ASSERT_TRUE(ExecuteTiling(tilingContextPara, tilingInfo));
107+ EXPECT_EQ(tilingInfo.tilingKey, 11003);
108+ EXPECT_EQ(tilingInfo.blockNum, 1);
109+ ASSERT_EQ(tilingInfo.workspaceSizes.size(), 1U);
110+ EXPECT_EQ(tilingInfo.workspaceSizes[0], 0U);
111+ }
112+ }
113+}