Merged
fix(cumsum): 修复整数空Tensor tiling除零 #7177
wangweidongAdd on 4 days ago
fix(cumsum): 修复整数空Tensor tiling除零 #7177
Merged
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 of | 3 | * 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; | |||
| 47 | REGISTER_TILING_DATA_CLASS(Cumsum_11000, Cum4IntTilingData); | 47 | REGISTER_TILING_DATA_CLASS(Cumsum_11000, Cum4IntTilingData); |
| 48 | REGISTER_TILING_DATA_CLASS(Cumsum_11001, Cum4IntTilingData); | 48 | REGISTER_TILING_DATA_CLASS(Cumsum_11001, Cum4IntTilingData); |
| 49 | REGISTER_TILING_DATA_CLASS(Cumsum_11002, Cum4IntTilingData); | 49 | REGISTER_TILING_DATA_CLASS(Cumsum_11002, Cum4IntTilingData); |
| 50 | +REGISTER_TILING_DATA_CLASS(Cumsum_11003, Cum4IntTilingData); | ||
| 50 | 51 | ||
| 51 | ge::graphStatus TilingCumsum4Int(gert::TilingContext* context); | 52 | ge::graphStatus TilingCumsum4Int(gert::TilingContext* context); |
| 52 | 53 | ||
| @@ -56,6 +57,7 @@ constexpr int64_t CORE_GATE = 4; | |||
| 56 | constexpr int64_t CUM_NO_SPLIT = 11000; | 57 | constexpr int64_t CUM_NO_SPLIT = 11000; |
| 57 | constexpr int64_t CUM_AR_SPLIT = 11001; | 58 | constexpr int64_t CUM_AR_SPLIT = 11001; |
| 58 | constexpr int64_t CUM_WITH_GROUP = 11002; | 59 | constexpr int64_t CUM_WITH_GROUP = 11002; |
| 60 | +constexpr int64_t CUM_EMPTY = 11003; | ||
| 59 | constexpr int64_t MAX_TENSOR_SIZE = 0xff00; // to avoid index overflow when B8 | 61 | constexpr int64_t MAX_TENSOR_SIZE = 0xff00; // to avoid index overflow when B8 |
| 60 | 62 | ||
| 61 | class Cumsum4IntTiling { | 63 | class 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 cumsum | 122 | } // namespace cumsum |
| 121 | 123 | ||
| @@ -42,6 +42,7 @@ using namespace Cum; | |||
| 42 | #define CUM_NO_SPLIT 11000 | 42 | #define CUM_NO_SPLIT 11000 |
| 43 | #define CUM_AR_SPLIT 11001 | 43 | #define CUM_AR_SPLIT 11001 |
| 44 | #define CUM_WITH_GROUP 11002 | 44 | #define CUM_WITH_GROUP 11002 |
| 45 | +#define CUM_EMPTY 11003 | ||
| 45 | 46 | ||
| 46 | static __aicore__ inline void cumsumSimd(GM_ADDR x, GM_ADDR axis, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling) | 47 | static __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)) { | ||
| 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 | +} | ||
🟡 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 用例。