已关闭
[WIP]tqbmm_tiling #10797
jgx创建于 9月20日关闭于 24 天前
[WIP]tqbmm_tiling #10797
已关闭
jgx创建于 9月20日关闭于 24 天前
共 5 个文件变更+341-13
@@ -35,12 +35,12 @@ ge::graphStatus TransposeQuantBatchMatMulAswTiling::DoOpTiling()
35 runInfo_.baseK = BASIC_BLOCK_K_128_BYTE;35 runInfo_.baseK = BASIC_BLOCK_K_128_BYTE;
36 precisionMode_ = TQBMMPrecisionMode::PRECISION_MODE_MXFP4;36 precisionMode_ = TQBMMPrecisionMode::PRECISION_MODE_MXFP4;
37 apiLevel_ = TQBMMApiLevel::TENSOR_LEVEL;37 apiLevel_ = TQBMMApiLevel::TENSOR_LEVEL;
38- CalL1Tiling();38+ ApplyMxL1Tiling();
39 } else if (IsMxFp8(context_->GetInputDesc(X1_IDX), context_->GetInputDesc(X2_IDX),39 } else if (IsMxFp8(context_->GetInputDesc(X1_IDX), context_->GetInputDesc(X2_IDX),
40 context_->GetOptionalInputDesc(SCALE_X1_IDX), context_->GetOptionalInputDesc(SCALE_X2_IDX))) {40 context_->GetOptionalInputDesc(SCALE_X1_IDX), context_->GetOptionalInputDesc(SCALE_X2_IDX))) {
41 precisionMode_ = TQBMMPrecisionMode::PRECISION_MODE_MXFP8;41 precisionMode_ = TQBMMPrecisionMode::PRECISION_MODE_MXFP8;
42 apiLevel_ = TQBMMApiLevel::TENSOR_LEVEL;42 apiLevel_ = TQBMMApiLevel::TENSOR_LEVEL;
43- CalL1Tiling();43+ ApplyMxL1Tiling();
44 } else if (IsHIFP8(context_->GetInputDesc(X1_IDX), context_->GetInputDesc(X2_IDX))) {44 } else if (IsHIFP8(context_->GetInputDesc(X1_IDX), context_->GetInputDesc(X2_IDX))) {
45 precisionMode_ = TQBMMPrecisionMode::PRECISION_MODE_HIFP8;45 precisionMode_ = TQBMMPrecisionMode::PRECISION_MODE_HIFP8;
46 CalL1Tiling();46 CalL1Tiling();
@@ -92,6 +92,42 @@ void TransposeQuantBatchMatMulAswTiling::GetTransposeBatchMatMulInfo()
92 }92 }
93}93}
94 94 
95+void TransposeQuantBatchMatMulAswTiling::ApplyMxL1Tiling()
96+{
97+ TqbmmMxL1Params params;
98+ params.mSize = args_.mValue;
99+ params.kSize = args_.kValue;
100+ params.baseM = runInfo_.baseM;
101+ params.baseN = runInfo_.baseN;
102+ params.baseK = runInfo_.baseK;
103+ params.aDtype = args_.aType;
104+ params.bDtype = args_.bType;
105+ params.scaleDtype = context_->GetOptionalInputDesc(SCALE_X2_IDX)->GetDataType();
106+ params.perTokenScaleDtype = context_->GetOptionalInputDesc(SCALE_X1_IDX)->GetDataType();
107+ params.biasDtype = args_.biasType;
108+ params.cDtype = context_->GetOutputDesc(0)->GetDataType();
109+ params.hasBias = args_.hasBias;
110+ params.transB = args_.isBTrans;
111+ params.l1Size = compileInfo_.l1Size;
112+ params.l0CSize = compileInfo_.l0CSize;
113+ 
114+ const TqbmmMxL1Result res = CalcTqbmmMxL1Tiling(params);
115+ runInfo_.baseM = res.baseM;
116+ runInfo_.singleCoreM = res.baseM;
117+ runInfo_.stepKa = res.stepKa;
118+ runInfo_.stepKb = res.stepKb;
119+ runInfo_.depthA1 = res.depthA1;
120+ runInfo_.depthB1 = res.depthB1;
121+ runInfo_.dbL0C = res.dbL0C;
122+ runInfo_.l1BufferNum = res.nBufferNum;
123+ scaleKL1_ = static_cast<uint32_t>(res.scaleKL1);
124+ const uint64_t kL1 = static_cast<uint64_t>(res.stepKa) * runInfo_.baseK;
125+ const uint64_t scaleFactor = kL1 == 0UL ? SCALER_FACTOR_MIN : res.scaleKL1 / kL1;
126+ scaleFactorA_ = static_cast<uint32_t>(std::min(scaleFactor, static_cast<uint64_t>(SCALER_FACTOR_MAX)));
127+ scaleFactorB_ = scaleFactorA_;
128+ isMxL1Tiled_ = true;
129+}
130+ 
95void TransposeQuantBatchMatMulAswTiling::CalL1Tiling()131void TransposeQuantBatchMatMulAswTiling::CalL1Tiling()
96{132{
97 uint64_t leftL1Size = compileInfo_.l1Size;133 uint64_t leftL1Size = compileInfo_.l1Size;
@@ -265,6 +301,10 @@ ge::graphStatus TransposeQuantBatchMatMulAswTiling::GetTilingDataProcess(BatchMa
265 }301 }
266 }302 }
267 tilingData.batchSplitFactor = batchSplitFactor_;303 tilingData.batchSplitFactor = batchSplitFactor_;
304+ if (isMxL1Tiled_) {
305+ // tqbmm 无 streamk 模板,MX 借用空闲的 kTailCnt 承载全 K scale 预载窗口;0 表示随 kL1 窗口重载
306+ tilingData.matMulTilingData.kTailCnt = scaleKL1_;
307+ }
268 return ret;308 return ret;
269}309}
270 310 
@@ -15,6 +15,7 @@
15 15 
16#pragma once16#pragma once
17#include "matmul/mat_mul_v3/op_host/op_tiling/arch35/matmul_v3_base_tiling_advanced.h"17#include "matmul/mat_mul_v3/op_host/op_tiling/arch35/matmul_v3_base_tiling_advanced.h"
18+#include "transpose_quant_batch_mat_mul_mx_l1_tiling.h"
18#include "../../../op_kernel/arch35/transpose_quant_batch_mat_mul_tiling_key_public.h"19#include "../../../op_kernel/arch35/transpose_quant_batch_mat_mul_tiling_key_public.h"
19#include "../../../op_kernel/arch35/transpose_quant_batch_mat_mul_tiling_key.h"20#include "../../../op_kernel/arch35/transpose_quant_batch_mat_mul_tiling_key.h"
20 21 
@@ -41,6 +42,7 @@ protected:
41 42 
42 std::vector<size_t> GetWorkspaceSize() const override;43 std::vector<size_t> GetWorkspaceSize() const override;
43 void CalL1Tiling();44 void CalL1Tiling();
45+ void ApplyMxL1Tiling();
44 void CalStepKs();46 void CalStepKs();
45 uint64_t GetDepthA1B1(uint64_t leftSize, uint64_t perDepthSize, uint64_t depthInit);47 uint64_t GetDepthA1B1(uint64_t leftSize, uint64_t perDepthSize, uint64_t depthInit);
46 void CalScaleFactors(uint64_t baseASize, uint64_t baseBSize, uint64_t baseScaleASize, uint64_t baseScaleBSize);48 void CalScaleFactors(uint64_t baseASize, uint64_t baseBSize, uint64_t baseScaleASize, uint64_t baseScaleBSize);
@@ -55,7 +57,9 @@ private:
55 uint32_t batchSplitFactor_ = 1;57 uint32_t batchSplitFactor_ = 1;
56 uint32_t scaleFactorA_ = 1;58 uint32_t scaleFactorA_ = 1;
57 uint32_t scaleFactorB_ = 1;59 uint32_t scaleFactorB_ = 1;
60+ uint32_t scaleKL1_ = 0;
58 bool isMXFP4_ = false;61 bool isMXFP4_ = false;
62+ bool isMxL1Tiled_ = false;
59};63};
60} // namespace transpose_quant_batch_mat_mul_advanced64} // namespace transpose_quant_batch_mat_mul_advanced
61} // namespace optiling65} // namespace optiling
@@ -0,0 +1,279 @@
1+/**
2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
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").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file transpose_quant_batch_mat_mul_mx_l1_tiling.h
13+ * \brief tqbmm MXFP8/MXFP4 的 L1 tiling,从 qbmm 基础模板
14+ * (matmul/quant_batch_matmul_v3/op_host/op_tiling/arch35/) 简化迁移。
15+ *
16+ * 迁移来源(函数级对应关系):
17+ * CalcTqbmmMxL1Tiling <- AdaptiveSlidingWindowMXBasicAPITiling::CalL1Tiling(:151-186)
18+ * + CalculateNBufferNum(:220-268) 主干
19+ * CalcTqbmmMxDepth <- L1TilingDataCalculator::GetDepthA1B1(l1_tiling_data_calculator.cpp:541-564)
20+ * CalcTqbmmMxStepKs <- L1TilingDataCalculator::CalStepKs(l1_tiling_data_calculator.cpp:348-396)
21+ * CalcTqbmmMxScaleKL1 <- L1TilingDataCalculator::CalScaleFactors(l1_tiling_data_calculator.cpp:398-439)
22+ * CalcTqbmmMxDbL0C <- CalL1Tiling 的 dbL0c 三目(mx_basic_api_tiling.cpp:165-170)
23+ * + CheckBiasAndScale(adaptive_sliding_window_tiling.cpp:358-369)
24+ * CalcTqbmmMxUsedL1Size <- CalcUsedL1Size(mx_basic_api_tiling.cpp:368-389)
25+ * GetTqbmmMxHalfFallback <- GetHalfKFallbackScaleKL1(mx_basic_api_tiling.cpp:306-320)
26+ * GetTqbmmMxFullCoverKL1 <- GetFullCoverScaleKL1IfPossible(mx_basic_api_tiling.cpp:322-333)
27+ * CanTqbmmMxReduceStepK <- CanReduceStepKToTwo(mx_basic_api_tiling.cpp:286-304)
28+ *
29+ * 相对 qbmm 删除的逻辑(tqbmm 用不到):
30+ * 1. A 全载(isAFullLoad,tqbmm 无 FULL_LOAD_MODE=1 内核实例,batchC 也不受限为 1)
31+ * 2. 3-buffer 分支(qbmm 用 IsMxMte2Bound 带宽模型门控;tqbmm MVP 不接,只做 4->2 兜底)
32+ * 3. isTensorapiCapable 判断(tqbmm MX 恒为 TENSOR_LEVEL/Blaze)
33+ * 4. transA 分支(tqbmm perm_x1 恒 [1,0,2],isATrans 恒 false)
34+ * 5. L0C 乒乓模板的 scaleKL1 收缩(AdjustScaleFactorForL0CPingpong,qbmm KERNELTYPE=9/10 专用)
35+ * 6. isPertoken(MX 恒非 pertoken,isUbQuant 只看 cDtype==BF16)
36+ *
37+ * 出参约定:tiling data 沿用 BatchMatMulV3TilingData 不新增字段,MX 模式下用
38+ * matMulTilingData.kTailCnt(tqbmm 无 streamk 模板,该字段空闲)承载 scaleKL1,
39+ * kernel 侧 transpose_quant_batch_mat_mul_mx.h 读 kTailCnt,0 表示退化为 kL1。
40+ */
41+ 
42+#pragma once
43+ 
44+#include <algorithm>
45+#include <cstdint>
46+ 
47+#include "graph/types.h"
48+ 
49+namespace optiling {
50+namespace transpose_quant_batch_mat_mul_advanced {
51+ 
52+constexpr uint64_t TQBMM_MX_GROUP_SIZE = 32UL;
53+constexpr uint64_t TQBMM_MX_DIVISOR_SIZE = 64UL;
54+constexpr uint64_t TQBMM_MX_MULTI_BASE_SIZE = 2UL;
55+constexpr uint64_t TQBMM_MX_ALIGN_128B = 128UL;
56+constexpr uint64_t TQBMM_MX_ALIGN_256B = 256UL;
57+constexpr uint64_t TQBMM_MX_SCALE_K_ESTIMATE = 4096UL;
58+constexpr uint64_t TQBMM_MX_MAX_STEP_K = 4UL;
59+constexpr uint64_t TQBMM_MX_DOUBLE_BUFFER = 2UL;
60+constexpr uint64_t TQBMM_MX_FOUR_BUFFER = 4UL;
61+constexpr uint64_t TQBMM_MX_CUBE_BLOCK = 16UL;
62+ 
63+struct TqbmmMxL1Params {
64+ uint64_t mSize = 0UL;
65+ uint64_t kSize = 0UL;
66+ uint64_t baseM = 0UL;
67+ uint64_t baseN = 0UL;
68+ uint64_t baseK = 0UL;
69+ ge::DataType aDtype = ge::DT_FLOAT8_E4M3FN;
70+ ge::DataType bDtype = ge::DT_FLOAT8_E4M3FN;
71+ ge::DataType scaleDtype = ge::DT_FLOAT8_E8M0;
72+ ge::DataType perTokenScaleDtype = ge::DT_FLOAT8_E8M0;
73+ ge::DataType biasDtype = ge::DT_FLOAT;
74+ ge::DataType cDtype = ge::DT_BF16;
75+ bool hasBias = false;
76+ bool transB = false;
77+ uint64_t l1Size = 0UL;
78+ uint64_t l0CSize = 0UL;
79+};
80+ 
81+struct TqbmmMxL1Result {
82+ uint64_t baseM = 0UL;
83+ uint32_t stepKa = 1U;
84+ uint32_t stepKb = 1U;
85+ uint32_t depthA1 = 2U;
86+ uint32_t depthB1 = 2U;
87+ uint64_t scaleKL1 = 0UL;
88+ uint32_t nBufferNum = 2U;
89+ uint32_t dbL0C = 1U;
90+};
91+ 
92+inline uint64_t TqbmmMxCeilDiv(uint64_t a, uint64_t b) { return (a + b - 1UL) / b; }
93+ 
94+inline uint64_t TqbmmMxCeilAlign(uint64_t a, uint64_t b) { return TqbmmMxCeilDiv(a, b) * b; }
95+ 
96+inline uint64_t TqbmmMxDataSize(uint64_t elemCnt, ge::DataType dtype)
97+{
98+ if (dtype == ge::DT_INT4 || dtype == ge::DT_FLOAT4_E2M1 || dtype == ge::DT_FLOAT4_E1M2) {
99+ return (elemCnt + 1UL) >> 1UL;
100+ }
101+ return elemCnt * static_cast<uint64_t>(ge::GetSizeByDataType(dtype));
102+}
103+ 
104+inline uint64_t CalcTqbmmMxDepth(const TqbmmMxL1Params& p, uint64_t leftL1)
105+{
106+ const uint64_t baseABSize = TqbmmMxDataSize(p.baseM * p.baseK, p.aDtype) +
107+ TqbmmMxDataSize(p.baseN * p.baseK, p.bDtype);
108+ const uint64_t baseScaleSize = TqbmmMxDataSize(p.baseM, p.perTokenScaleDtype) +
109+ TqbmmMxDataSize(p.baseN, p.scaleDtype);
110+ uint64_t scaleKL1 = std::min(p.kSize, TQBMM_MX_SCALE_K_ESTIMATE);
111+ uint64_t scaleL1Size = baseScaleSize * TqbmmMxCeilDiv(scaleKL1, TQBMM_MX_DIVISOR_SIZE) * TQBMM_MX_MULTI_BASE_SIZE *
112+ TQBMM_MX_DOUBLE_BUFFER;
113+ uint64_t depth = 1UL;
114+ while (depth * baseABSize + scaleL1Size <= leftL1) {
115+ depth *= 2UL;
116+ const uint64_t kL1 = depth / TQBMM_MX_DOUBLE_BUFFER * p.baseK;
117+ if (kL1 > scaleKL1) {
118+ scaleKL1 = kL1;
119+ scaleL1Size = baseScaleSize * TqbmmMxCeilDiv(scaleKL1, TQBMM_MX_DIVISOR_SIZE) * TQBMM_MX_MULTI_BASE_SIZE *
120+ TQBMM_MX_DOUBLE_BUFFER;
121+ }
122+ }
123+ return depth == 1UL ? depth : depth / 2UL;
124+}
125+ 
126+inline void CalcTqbmmMxStepKs(const TqbmmMxL1Params& p, uint64_t depth, uint32_t& stepKa, uint32_t& stepKb,
127+ uint32_t& depthA1, uint32_t& depthB1)
128+{
129+ uint64_t ka = std::max(depth / TQBMM_MX_DOUBLE_BUFFER, 1UL);
130+ uint64_t kb = ka;
131+ if (ka * p.baseK > p.kSize) {
132+ ka = TqbmmMxCeilDiv(p.kSize, p.baseK);
133+ }
134+ if (kb * p.baseK > p.kSize) {
135+ kb = TqbmmMxCeilDiv(p.kSize, p.baseK);
136+ }
137+ if (ka > kb) {
138+ ka = ka / kb * kb;
139+ }
140+ if (kb > ka) {
141+ kb = kb / ka * ka;
142+ }
143+ ka = std::min(ka, TQBMM_MX_MAX_STEP_K);
144+ kb = std::min(kb, TQBMM_MX_MAX_STEP_K);
145+ stepKa = static_cast<uint32_t>(ka);
146+ stepKb = static_cast<uint32_t>(kb);
147+ depthA1 = static_cast<uint32_t>(ka * TQBMM_MX_DOUBLE_BUFFER);
148+ depthB1 = static_cast<uint32_t>(kb * TQBMM_MX_DOUBLE_BUFFER);
149+}
150+ 
151+inline uint64_t CalcTqbmmMxScaleKL1(const TqbmmMxL1Params& p, uint64_t leftL1, uint32_t stepKa, uint32_t stepKb,
152+ uint32_t depthA1, uint32_t depthB1)
153+{
154+ const uint64_t usedABSize = TqbmmMxDataSize(p.baseM * p.baseK, p.aDtype) * depthA1 +
155+ TqbmmMxDataSize(p.baseN * p.baseK, p.bDtype) * depthB1;
156+ if (leftL1 <= usedABSize) {
157+ return 0UL;
158+ }
159+ const uint64_t leftAfterAB = leftL1 - usedABSize;
160+ const uint64_t kL1 = std::min(stepKa, stepKb) * p.baseK;
161+ if (kL1 == 0UL) {
162+ return 0UL;
163+ }
164+ const uint64_t scaleGroupL1Size = (TqbmmMxDataSize(p.baseM, p.perTokenScaleDtype) +
165+ TqbmmMxDataSize(p.baseN, p.scaleDtype)) *
166+ TQBMM_MX_MULTI_BASE_SIZE * TQBMM_MX_DOUBLE_BUFFER;
167+ const uint64_t maxScaleKL1ByL1 = leftAfterAB / scaleGroupL1Size * TQBMM_MX_DIVISOR_SIZE;
168+ const uint64_t maxScaleKL1 = TqbmmMxCeilAlign(p.kSize, kL1);
169+ uint64_t scaleKL1 = std::min(maxScaleKL1ByL1, maxScaleKL1);
170+ return scaleKL1 / kL1 * kL1;
171+}
172+ 
173+inline uint32_t CalcTqbmmMxDbL0C(const TqbmmMxL1Params& p)
174+{
175+ constexpr uint32_t db = 2U;
176+ constexpr uint64_t maxBiasBaseN = 512UL;
177+ constexpr uint64_t maxScaleBaseN = 256UL;
178+ const bool isBiasInvalid = p.hasBias && p.biasDtype != ge::DT_BF16 && p.baseN > maxBiasBaseN;
179+ const bool isUbQuant = p.cDtype == ge::DT_BF16;
180+ const bool isScaleInvalid = !isUbQuant && p.baseN > maxScaleBaseN;
181+ const bool l0cEnough = p.baseM * p.baseN * 4UL * TQBMM_MX_DOUBLE_BUFFER <= p.l0CSize;
182+ return (l0cEnough && !isBiasInvalid && !isScaleInvalid) ? db : 1U;
183+}
184+ 
185+inline uint64_t CalcTqbmmMxUsedL1Size(const TqbmmMxL1Params& p, uint64_t kL1, uint64_t scaleKL1, uint32_t l1BufferNum)
186+{
187+ uint64_t usedL1Size = TqbmmMxDataSize(p.baseN * kL1, p.bDtype) * l1BufferNum;
188+ usedL1Size += TqbmmMxDataSize(p.baseN * TqbmmMxCeilDiv(scaleKL1, TQBMM_MX_GROUP_SIZE), p.scaleDtype) *
189+ TQBMM_MX_DOUBLE_BUFFER;
190+ if (p.hasBias) {
191+ usedL1Size += TqbmmMxDataSize(p.baseN, p.biasDtype) * TQBMM_MX_DOUBLE_BUFFER;
192+ }
193+ usedL1Size += TqbmmMxDataSize(p.baseM * kL1, p.aDtype) * l1BufferNum;
194+ usedL1Size += TqbmmMxDataSize(p.baseM * TqbmmMxCeilDiv(scaleKL1, TQBMM_MX_GROUP_SIZE), p.perTokenScaleDtype) *
195+ TQBMM_MX_DOUBLE_BUFFER;
196+ return usedL1Size;
197+}
198+ 
199+inline uint64_t GetTqbmmMxHalfFallback(const TqbmmMxL1Params& p, uint64_t scaleKL1Init, uint64_t kL1)
200+{
201+ uint64_t scaleKL1 = scaleKL1Init;
202+ if (scaleKL1 % TQBMM_MX_SCALE_K_ESTIMATE == 0UL) {
203+ return scaleKL1;
204+ }
205+ const uint64_t halfK = TqbmmMxCeilDiv(p.kSize, 2UL);
206+ if (scaleKL1 > halfK && scaleKL1 < p.kSize) {
207+ const uint64_t adjusted = TqbmmMxCeilAlign(halfK, kL1);
208+ scaleKL1 = adjusted < scaleKL1 ? adjusted : scaleKL1;
209+ }
210+ return scaleKL1;
211+}
212+ 
213+inline uint64_t GetTqbmmMxFullCoverKL1(const TqbmmMxL1Params& p, uint64_t kL1, uint64_t scaleKL1, uint32_t l1BufferNum)
214+{
215+ const uint64_t fullCover = TqbmmMxCeilAlign(p.kSize, kL1);
216+ if (fullCover <= scaleKL1) {
217+ return scaleKL1;
218+ }
219+ return CalcTqbmmMxUsedL1Size(p, kL1, fullCover, l1BufferNum) <= p.l1Size ? fullCover : scaleKL1;
220+}
221+ 
222+inline bool CanTqbmmMxReduceStepK(const TqbmmMxL1Params& p, uint64_t stepKTwoKL1)
223+{
224+ const bool isAInnerKAligned = TqbmmMxDataSize(p.kSize, p.aDtype) % TQBMM_MX_ALIGN_128B == 0UL;
225+ const bool isBInnerKAligned = !p.transB || TqbmmMxDataSize(p.kSize, p.bDtype) % TQBMM_MX_ALIGN_128B == 0UL;
226+ const bool isStepKTwoAAligned = TqbmmMxDataSize(stepKTwoKL1, p.aDtype) % TQBMM_MX_ALIGN_256B == 0UL;
227+ const bool isStepKTwoBAligned = !p.transB || TqbmmMxDataSize(stepKTwoKL1, p.bDtype) % TQBMM_MX_ALIGN_256B == 0UL;
228+ return isAInnerKAligned && isBInnerKAligned && isStepKTwoAAligned && isStepKTwoBAligned;
229+}
230+ 
231+inline TqbmmMxL1Result CalcTqbmmMxL1Tiling(const TqbmmMxL1Params& p)
232+{
233+ TqbmmMxL1Result res;
234+ res.baseM = std::min(p.baseM, TqbmmMxCeilAlign(p.mSize, TQBMM_MX_CUBE_BLOCK));
235+ 
236+ TqbmmMxL1Params aligned = p;
237+ aligned.baseM = res.baseM;
238+ res.dbL0C = CalcTqbmmMxDbL0C(aligned);
239+ 
240+ uint64_t leftL1 = aligned.l1Size;
241+ if (aligned.hasBias) {
242+ leftL1 -= TqbmmMxDataSize(aligned.baseN, aligned.biasDtype) * TQBMM_MX_DOUBLE_BUFFER;
243+ }
244+ const uint64_t depth = CalcTqbmmMxDepth(aligned, leftL1);
245+ CalcTqbmmMxStepKs(aligned, depth, res.stepKa, res.stepKb, res.depthA1, res.depthB1);
246+ const uint64_t scaleKL1Init = CalcTqbmmMxScaleKL1(aligned, leftL1, res.stepKa, res.stepKb, res.depthA1,
247+ res.depthB1);
248+ 
249+ const uint64_t stepK = std::min(res.stepKa, res.stepKb);
250+ const uint64_t currentKL1 = stepK * aligned.baseK;
251+ uint64_t currentScaleKL1 = GetTqbmmMxHalfFallback(aligned, scaleKL1Init, currentKL1);
252+ if (CalcTqbmmMxUsedL1Size(aligned, currentKL1, currentScaleKL1, TQBMM_MX_FOUR_BUFFER) <= aligned.l1Size) {
253+ res.scaleKL1 = GetTqbmmMxFullCoverKL1(aligned, currentKL1, currentScaleKL1, TQBMM_MX_FOUR_BUFFER);
254+ res.nBufferNum = TQBMM_MX_FOUR_BUFFER;
255+ return res;
256+ }
257+ 
258+ const uint64_t stepKTwoKL1 = 2UL * aligned.baseK;
259+ const bool canReduceStepK = currentKL1 * TQBMM_MX_DOUBLE_BUFFER < aligned.kSize && (stepK == 3UL || stepK == 4UL) &&
260+ CanTqbmmMxReduceStepK(aligned, stepKTwoKL1);
261+ if (canReduceStepK) {
262+ const uint64_t twoScaleKL1 = GetTqbmmMxHalfFallback(aligned, scaleKL1Init, stepKTwoKL1);
263+ if (CalcTqbmmMxUsedL1Size(aligned, stepKTwoKL1, twoScaleKL1, TQBMM_MX_FOUR_BUFFER) <= aligned.l1Size) {
264+ res.stepKa = static_cast<uint32_t>(stepKTwoKL1 / aligned.baseK);
265+ res.stepKb = res.stepKa;
266+ res.depthA1 = static_cast<uint32_t>(res.stepKa * TQBMM_MX_DOUBLE_BUFFER);
267+ res.depthB1 = res.depthA1;
268+ res.scaleKL1 = GetTqbmmMxFullCoverKL1(aligned, stepKTwoKL1, twoScaleKL1, TQBMM_MX_FOUR_BUFFER);
269+ res.nBufferNum = TQBMM_MX_FOUR_BUFFER;
270+ return res;
271+ }
272+ }
273+ 
274+ res.scaleKL1 = currentScaleKL1;
275+ res.nBufferNum = 2U;
276+ return res;
277+}
278+} // namespace transpose_quant_batch_mat_mul_advanced
279+} // namespace optiling
@@ -48,9 +48,13 @@ __aicore__ inline void TqbmmMxTensorApiKernel(GM_ADDR aGM, GM_ADDR bGM, GM_ADDR
48 using MatmulKernel = Blaze::Gemm::Kernel::GemmUniversal<ProblemShape, BlockMmad, BlockEpilogue, BlockScheduler>;48 using MatmulKernel = Blaze::Gemm::Kernel::GemmUniversal<ProblemShape, BlockMmad, BlockEpilogue, BlockScheduler>;
49 using Params = typename MatmulKernel::Params;49 using Params = typename MatmulKernel::Params;
50 const auto& tCubeTiling = tilingData.matMulTilingData.tCubeTiling;50 const auto& tCubeTiling = tilingData.matMulTilingData.tCubeTiling;
51+ // host 侧 MX 借用空闲的 kTailCnt 承载 scaleKL1(全 K scale 预载窗口);0 表示随 kL1 窗口重载
52+ const uint64_t mxScaleKL1 = tilingData.matMulTilingData.kTailCnt != 0 ?
53+ static_cast<uint64_t>(tilingData.matMulTilingData.kTailCnt) :
54+ static_cast<uint64_t>(tilingData.kL1);
51 Params params = {{tCubeTiling.M, tCubeTiling.N, tCubeTiling.Ka, tilingData.cBatchDimAll},55 Params params = {{tCubeTiling.M, tCubeTiling.N, tCubeTiling.Ka, tilingData.cBatchDimAll},
52 {aGM, bGM, cGM, bias, perTokenScale, scale},56 {aGM, bGM, cGM, bias, perTokenScale, scale},
53- {tilingData.kL1, tilingData.kL1, tilingData.l1BufferNum},57+ {tilingData.kL1, mxScaleKL1, tilingData.l1BufferNum},
54 {static_cast<int64_t>(tCubeTiling.baseM), static_cast<int64_t>(tCubeTiling.baseN),58 {static_cast<int64_t>(tCubeTiling.baseM), static_cast<int64_t>(tCubeTiling.baseN),
55 tilingData.matMulTilingData.mTailCnt, tilingData.matMulTilingData.nTailCnt,59 tilingData.matMulTilingData.mTailCnt, tilingData.matMulTilingData.nTailCnt,
56 tilingData.matMulTilingData.mBaseTailSplitCnt, tilingData.matMulTilingData.nBaseTailSplitCnt,60 tilingData.matMulTilingData.mBaseTailSplitCnt, tilingData.matMulTilingData.nBaseTailSplitCnt,
@@ -437,9 +437,9 @@ static TilingTestParam ascend950_cases_params[] = {
437 0,437 0,
438 32,438 32,
439 135185UL,439 135185UL,
440- "32 35 744 192 192 256 256 192 256 256 128 4 4 1 1 0 0 0 0 18432 8192 0 1 1 1 1 2 2 0 0 2 2 1 0 0 0 0 0 0 0 0 "440+ "32 35 744 192 192 48 256 192 48 256 128 4 4 1 1 0 0 0 0 18432 8192 0 1 1 1 1 2 2 0 0 2 2 2 0 0 0 0 0 0 0 0 "
441- "0 0 0 0 0 0 0 0 16843009 1 1 1 1 1 0 0 0 4 0 32 32 32 1 1 1 1 1 1 1 1 1 1 32 32 32 0 1 1 48 256 256 16843264 "441+ "0 0 0 0 0 0 0 0 16843009 1 1 256 1 1 0 0 0 4 0 32 32 32 1 1 1 1 1 1 1 1 1 1 32 32 32 0 1 1 48 256 256 16843776 "
442- "256 1 0 1 1 4 4 ",442+ "48 1 0 1 1 4 4 ",
443 1,443 1,
444 32,444 32,
445 {1, 0, 2},445 {1, 0, 2},
@@ -542,9 +542,9 @@ static TilingTestParam ascend950_cases_params[] = {
542 0,542 0,
543 32,543 32,
544 143377UL,544 143377UL,
545- "32 35 744 192 192 256 256 192 256 256 128 4 4 1 1 0 0 0 0 9216 8192 0 1 1 1 1 2 2 0 0 2 2 1 0 0 0 0 0 0 0 0 "545+ "32 35 744 192 192 48 256 192 48 256 128 4 4 1 1 0 0 0 0 9216 8192 0 1 1 1 1 2 2 0 0 2 2 2 0 0 0 0 0 0 0 0 "
546- "0 0 0 0 0 0 0 0 16843009 1 1 1 1 1 0 0 0 4 2 32 32 32 1 1 1 1 1 1 1 1 1 1 32 32 32 0 1 1 48 256 256 16843264 "546+ "0 0 0 0 0 0 0 0 16843009 1 1 256 1 1 0 0 0 4 2 32 32 32 1 1 1 1 1 1 1 1 1 1 32 32 32 0 1 1 48 256 256 16843776 "
547- "256 1 0 1 1 4 4 ",547+ "48 1 0 1 1 4 4 ",
548 1,548 1,
549 32,549 32,
550 {1, 0, 2},550 {1, 0, 2},
@@ -632,9 +632,10 @@ TEST(TransposeQuantBatchMatMulTilingRuntimeExtra, WeightNzMxFp8Success_0)
632 ASSERT_EQ(opImpl->tiling(tiling_context), ge::GRAPH_SUCCESS);632 ASSERT_EQ(opImpl->tiling(tiling_context), ge::GRAPH_SUCCESS);
633 uint64_t tiling_key = tiling_context->GetTilingKey();633 uint64_t tiling_key = tiling_context->GetTilingKey();
634 auto tiling_data_result = TilingData2Str(tiling_context->GetRawTilingData());634 auto tiling_data_result = TilingData2Str(tiling_context->GetRawTilingData());
635- string golden_tiling_data = "32 425 64 640 640 256 256 640 256 256 128 4 4 1 1 0 0 0 0 98304 8192 0 1 1 1 1 2 2 0 "635+ string
636- "0 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16843266 1 1 1 1 1 0 0 0 4 1 2057 2057 2057 1 "636+ golden_tiling_data = "32 425 64 640 640 256 256 640 256 256 128 4 4 1 1 0 0 0 0 98304 8192 0 1 1 1 1 2 2 0 "
637- "1 1 1 1 1 1 1 1 1 2057 2057 2057 0 1 1 256 64 256 16843264 256 1 0 1 1 4 4 ";637+ "0 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16843523 1 1 768 1 1 0 0 0 4 1 2057 2057 2057 1 "
638+ "1 1 1 1 1 1 1 1 1 2057 2057 2057 0 1 1 256 64 256 16843264 256 1 0 1 1 4 4 ";
638 ASSERT_EQ(tiling_key, 135169);639 ASSERT_EQ(tiling_key, 135169);
639 ASSERT_EQ(tiling_data_result, golden_tiling_data);640 ASSERT_EQ(tiling_data_result, golden_tiling_data);
640}641}
@@ -714,7 +715,7 @@ TEST(TransposeQuantBatchMatMulTilingRuntimeExtra, WeightNzMxFp8Success_1)
714 uint64_t tiling_key = tiling_context->GetTilingKey();715 uint64_t tiling_key = tiling_context->GetTilingKey();
715 auto tiling_data_result = TilingData2Str(tiling_context->GetRawTilingData());716 auto tiling_data_result = TilingData2Str(tiling_context->GetRawTilingData());
716 string golden_tiling_data = "32 284 192 1472 1472 256 256 1472 256 256 128 4 4 1 1 0 0 0 0 172032 12288 0 1 1 1 "717 string golden_tiling_data = "32 284 192 1472 1472 256 256 1472 256 256 128 4 4 1 1 0 0 0 0 172032 12288 0 1 1 1 "
717- "1 2 2 0 0 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16844037 1 1 1 1 1 0 0 0 4 0 1172 "718+ "1 2 2 0 0 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16844294 1 1 1536 1 1 0 0 0 4 0 1172 "
718 "1172 1172 1 1 1 1 1 1 1 1 1 1 1172 1172 1172 0 1 1 256 192 256 16843264 256 1 0 1 1 4 "719 "1172 1172 1 1 1 1 1 1 1 1 1 1 1172 1172 1172 0 1 1 256 192 256 16843264 256 1 0 1 1 4 "
719 "4 ";720 "4 ";
720 ASSERT_EQ(tiling_key, 135185);721 ASSERT_EQ(tiling_key, 135185);