已合并
将matmul_compress_dequant算子从math仓迁到nn仓 #4166
将matmul_compress_dequant算子从math仓迁到nn仓 #4166
已合并
wmg1创建于 4月24日
33 个文件变更+3864-0
@@ -293,6 +293,7 @@
293| [aclnnMatmul](../../matmul/mat_mul_v3/docs/aclnnMatmul.md) | 完成1到6维张量self与张量mat2的矩阵乘计算。 | 默认确定性实现 | 默认确定性实现 |293| [aclnnMatmul](../../matmul/mat_mul_v3/docs/aclnnMatmul.md) | 完成1到6维张量self与张量mat2的矩阵乘计算。 | 默认确定性实现 | 默认确定性实现 |
294| [aclnnMatmulWeightNz](../../matmul/mat_mul_v3/docs/aclnnMatmulWeightNz.md) | 完成张量self与张量mat2的矩阵乘计算,mat2仅支持昇腾亲和数据排布格式。 | 默认确定性实现 | 默认确定性实现 |294| [aclnnMatmulWeightNz](../../matmul/mat_mul_v3/docs/aclnnMatmulWeightNz.md) | 完成张量self与张量mat2的矩阵乘计算,mat2仅支持昇腾亲和数据排布格式。 | 默认确定性实现 | 默认确定性实现 |
295| [aclnnMatmulCompress](../../matmul/matmul_compress/docs/aclnnMatmulCompress.md) | 进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩,矩阵乘,反量化计算。 | 默认确定性实现 | - |295| [aclnnMatmulCompress](../../matmul/matmul_compress/docs/aclnnMatmulCompress.md) | 进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩,矩阵乘,反量化计算。 | 默认确定性实现 | - |
296+| [aclnnMatmulCompressDequant](../../matmul/matmul_v2_compress_dequant/docs/aclnnMatmulCompressDequant.md) | 进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩,矩阵乘,反量化计算。 | 默认确定性实现 | - |
oscillated
oscillatedoscillated5月11日

在docs/zh/op_list.md也check下,是否要新增算子条目。

likedislike
wmg1
wmg1
5月14日 评论:
296| [aclnnMaxPool](../../pooling/max_pool_v3/docs/aclnnMaxPool.md) | 对于dim=3 或4维的输入张量,进行最大池化(max pooling)操作。 | 默认确定性实现 | 默认确定性实现 |297| [aclnnMaxPool](../../pooling/max_pool_v3/docs/aclnnMaxPool.md) | 对于dim=3 或4维的输入张量,进行最大池化(max pooling)操作。 | 默认确定性实现 | 默认确定性实现 |
297| [aclnnMaxPool2dWithIndices](../../pooling/max_pool3d_with_argmax_v2/docs/aclnnMaxPool2dWithIndices.md) | 对于输入信号的输入通道,提供2维(H,W维度)最大池化(max pooling)操作,输出池化后的值out和索引indices。 | 默认确定性实现 | 默认确定性实现 |298| [aclnnMaxPool2dWithIndices](../../pooling/max_pool3d_with_argmax_v2/docs/aclnnMaxPool2dWithIndices.md) | 对于输入信号的输入通道,提供2维(H,W维度)最大池化(max pooling)操作,输出池化后的值out和索引indices。 | 默认确定性实现 | 默认确定性实现 |
298| [aclnnMaxPool2dWithIndicesBackward](../../pooling/max_pool3d_grad_with_argmax/docs/aclnnMaxPool2dWithIndicesBackward.md) | 正向最大池化aclnnMaxPool2dWithIndices的反向传播。 | 默认非确定性实现,支持配置开启。 | 默认确定性实现 |299| [aclnnMaxPool2dWithIndicesBackward](../../pooling/max_pool3d_grad_with_argmax/docs/aclnnMaxPool2dWithIndicesBackward.md) | 正向最大池化aclnnMaxPool2dWithIndices的反向传播。 | 默认非确定性实现,支持配置开启。 | 默认确定性实现 |
@@ -2397,6 +2397,16 @@
2397 <td>AI Core</td>2397 <td>AI Core</td>
2398 <td>完成无损压缩矩阵乘计算。</td>2398 <td>完成无损压缩矩阵乘计算。</td>
2399 </tr>2399 </tr>
2400+ <tr>
2401+ <td>matmul</td>
2402+ <td><a href="../../matmul/matmul_v2_compress_dequant/README.md">matmul_v2_compress_dequant</a></td>
2403+ <td>✗</td>
2404+ <td>✗</td>
2405+ <td>✓</td>
2406+ <td>✗</td>
2407+ <td>AI Core</td>
2408+ <td>完成无损解压缩、矩阵乘、反量化计算。</td>
2409+ </tr>
2400 <tr>2410 <tr>
2401 <td>matmul</td>2411 <td>matmul</td>
2402 <td><a href="../../matmul/mv/README.md">mv</a></td>2412 <td><a href="../../matmul/mv/README.md">mv</a></td>
@@ -0,0 +1,20 @@
1+# ----------------------------------------------------------------------------
2+# This program is free software, you can redistribute it and/or modify it.
3+# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4+# This file is a part of the CANN Open Software.
5+# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").
6+# Please refer to the License for details. You may not use this file except in compliance with the License.
7+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
8+# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
9+# See LICENSE in the root of the software repository for the full text of the License.
10+# ----------------------------------------------------------------------------
11+ 
12+file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
13+if(NOT ENABLE_TEST AND NOT BENCHMARK)
14+ list(REMOVE_ITEM CURRENT_DIRS tests)
15+endif()
16+foreach(SUB_DIR ${CURRENT_DIRS})
17+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
18+ add_subdirectory(${SUB_DIR})
19+ endif()
20+endforeach()
@@ -0,0 +1,114 @@
1+# MatMulV2CompressDequant
2+ 
3+## 产品支持情况
4+ 
5+| 产品 | 是否支持 |
6+| ---- | :----:|
7+|Ascend 950PR/Ascend 950DT|×|
8+|Atlas A3 训练系列产品/Atlas A3 推理系列产品|×|
9+|Atlas A2 训练系列产品/Atlas A2 推理系列产品|×|
10+|Atlas 200I/500 A2推理产品|×|
11+|Atlas 推理系列产品|√|
12+|Atlas 训练系列产品|×|
13+ 
14+## 功能说明
15+ 
16+- **算子功能**:进行矩阵乘计算时,可先通过msModelSlim工具对右矩阵进行无损压缩,减少内存占用,然后通过本接口完成无损解压缩、矩阵乘和反量化计算。
17+- **计算公式**
18+
19+ ```
20+ x2_unzip = unzip(x2, compressIndex, compressInfo)
21+ result = (x1 @ x2_unzip + bias) * deqScale
22+ ```
23+
24+ 其中x2表示右矩阵经过msModelSlim工具压缩后的一维数据,x2_unzip是接口内部进行无损解压缩后的数据(与原始右矩阵数据一致)。
25+ 
26+## 参数说明
27+ 
28+<table style="undefined;table-layout: fixed; width: 869px"><colgroup>
29+<col style="width: 144px">
30+<col style="width: 166px">
31+<col style="width: 343px">
32+<col style="width: 114px">
33+<col style="width: 102px">
34+</colgroup>
35+<thead>
36+ <tr>
37+ <th>参数名</th>
38+ <th>输入/输出/属性</th>
39+ <th>描述</th>
40+ <th>数据类型</th>
41+ <th>数据格式</th>
42+ </tr></thead>
43+<tbody>
44+ <tr>
45+ <td>x1</td>
46+ <td>输入张量</td>
47+ <td>矩阵乘的左输入,2维张量。</td>
48+ <td>INT8</td>
49+ <td>ND</td>
50+ </tr>
51+ <tr>
52+ <td>x2</td>
53+ <td>输入张量</td>
54+ <td>压缩后的矩阵乘右输入,1维张量。</td>
55+ <td>INT8</td>
56+ <td>ND</td>
57+ </tr>
58+ <tr>
59+ <td>compressIndex</td>
60+ <td>输入张量</td>
61+ <td>矩阵乘右输入的压缩索引表,1维张量。</td>
62+ <td>INT8</td>
63+ <td>ND</td>
64+ </tr>
65+ <tr>
66+ <td>bias</td>
67+ <td>输入张量</td>
68+ <td>偏置项,支持空指针传入。</td>
69+ <td>INT32</td>
70+ <td>ND</td>
71+ </tr>
72+ <tr>
73+ <td>deqScale</td>
74+ <td>输入张量</td>
75+ <td>反量化参数,数据类型为UINT64。</td>
76+ <td>UINT64</td>
77+ <td>ND</td>
78+ </tr>
79+ <tr>
80+ <td>offsetW</td>
81+ <td>输入张量</td>
82+ <td>矩阵乘右输入的偏移量,当前仅支持空指针传入。</td>
83+ <td>INT8</td>
84+ <td>ND</td>
85+ </tr>
86+ <tr>
87+ <td>offsetX</td>
88+ <td>输入属性</td>
89+ <td>矩阵乘左输入的偏移量,当前仅支持0。</td>
90+ <td>INT32</td>
91+ <td>-</td>
92+ </tr>
93+ <tr>
94+ <td>compressInfo</td>
95+ <td>输入数组</td>
96+ <td>压缩数据相关信息,包括压缩块信息和原始shape等。</td>
97+ <td>INT64</td>
98+ <td>-</td>
99+ </tr>
100+ <tr>
101+ <td>out</td>
102+ <td>输出张量</td>
103+ <td>计算结果输出。</td>
104+ <td>FLOAT16</td>
105+ <td>ND</td>
106+ </tr>
107+</tbody></table>
108+ 
109+## 约束说明
110+ 
111+- x1和x2_unzip的Reduce维度大小必须相等。
112+- 所有输入张量不支持非连续的Tensor。
113+- deqScale需要将原始float类型参数转换为UINT64数据格式。
114+- 当前offsetW仅支持空指针,offsetX仅支持0。
@@ -0,0 +1,609 @@
1+# aclnnMatmulCompressDequant
2+ 
3+[📄 查看源码](https://gitcode.com/cann/ops-nn/tree/master/matmul/matmul_v2_compress_dequant)
4+ 
5+## 产品支持情况
6+ 
7+| 产品 | 是否支持 |
8+| :----------------------------------------------------------- | :------: |
9+| <term>Ascend 950PR/Ascend 950DT</term> | × |
10+| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | × |
11+| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | × |
12+| <term>Atlas 200I/500 A2 推理产品</term> | × |
13+| <term>Atlas 推理系列产品 </term> | √ |
14+| <term>Atlas 训练系列产品</term> | × |
15+ 
16+## 功能说明
17+ 
18+- 接口功能:进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩、矩阵乘、反量化计算。
19+- 计算公式:
20+ 
21+ $$
22+ x2\_unzip = unzip(x2, compressIndex, compressInfo)\\
23+ result=(x1 @ x2\_unzip + bias)*deqScale
24+ $$
25+ 
26+ 其中x2表示r矩阵经过msModelSlim工具进行压缩后的一维数据,compressIndex以及compressInfo表示压缩算法相关的信息,$x2\_unzip$是本接口内部进行无损解压缩后的数据(与原始r矩阵数据一致),压缩和调用本接口的详细使用样例参考[调用示例](#调用示例)。
27+ 
28+## 函数原型
29+ 
30+每个算子分为[两段式接口](../../../docs/zh/context/两段式接口.md),必须先调用“aclnnMatmulCompressDequantGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnMatmulCompressDequant”接口执行计算。
31+ 
32+```cpp
33+aclnnStatus aclnnMatmulCompressDequantGetWorkspaceSize(
34+ const aclTensor* x1,
35+ const aclTensor* x2,
36+ const aclTensor* compressIndex,
37+ const aclTensor* bias,
38+ const aclTensor* deqScale,
39+ const aclTensor* offsetW,
40+ int offsetX,
41+ const aclIntArray* compressInfo,
42+ aclTensor* out,
43+ uint64_t* workspaceSize,
44+ aclOpExecutor** executor)
45+```
46+ 
47+```cpp
48+aclnnStatus aclnnMatmulCompressDequant(
49+ void* workspace,
50+ uint64_t workspaceSize,
51+ aclOpExecutor* executor,
52+ aclrtStream stream)
53+```
54+ 
55+## aclnnMatmulCompressDequantGetWorkspaceSize
56+ 
57+- **参数说明**
58+ <table style="undefined;table-layout: fixed; width: 1475px"><colgroup>
59+ <col style="width: 167px">
60+ <col style="width: 123px">
61+ <col style="width: 325px">
62+ <col style="width: 230px">
63+ <col style="width: 128px">
64+ <col style="width: 118px">
65+ <col style="width: 239px">
66+ <col style="width: 145px">
67+ </colgroup>
68+ <thead>
69+ <tr>
70+ <th>参数名</th>
71+ <th>输入/输出</th>
72+ <th>描述</th>
73+ <th>使用说明</th>
74+ <th>数据类型</th>
75+ <th>数据格式</th>
76+ <th>维度(shape)</th>
77+ <th>非连续tensor</th>
78+ </tr></thead>
79+ <tbody>
80+ <tr>
81+ <td>x1</td>
82+ <td>输入</td>
83+ <td>表示矩阵乘的左输入。</td>
84+ <td>-</td>
85+ <td>INT8</td>
86+ <td>ND</td>
87+ <td>2</td>
88+ <td>-</td>
89+ </tr>
90+ <tr>
91+ <td>x2</td>
92+ <td>输入</td>
93+ <td>表示压缩后的矩阵乘的右输入,为通过msModelSlim工具中weight_compression模块压缩后的输入。</td>
94+ <td>-</td>
95+ <td>INT8</td>
96+ <td>ND</td>
97+ <td>1</td>
98+ <td>-</td>
99+ </tr>
100+ <tr>
101+ <td>compressIndex</td>
102+ <td>输入</td>
103+ <td>表示矩阵乘右输入的压缩索引表。</td>
104+ <td>通过示例中的msModelSlim工具中获取</td>
105+ <td>INT8</td>
106+ <td>ND</td>
107+ <td>1</td>
108+ <td>-</td>
109+ </tr>
110+ <tr>
111+ <td>bias</td>
112+ <td>输入</td>
113+ <td>参与矩阵乘计算的偏置项。</td>
114+ <td>支持空指针传入。</td>
115+ <td>INT8</td>
116+ <td>ND</td>
117+ <td>2维,shape仅支持(1, n)或者(n),其中n为输出shape(m, n)的n</td>
118+ <td>-</td>
119+ </tr>
120+ <tr>
121+ <td>deqScale</td>
122+ <td>输入</td>
123+ <td>表示反量化参数。</td>
124+ <td>tensor中的值为float通过下述示例中转换后的UINT64的数据。</td>
125+ <td>UINT64</td>
126+ <td>ND</td>
127+ <td>2维,shape支持(1, n)或者(1, 1), 其中n为输出shape(m, n)中的n。</td>
128+ <td>-</td>
129+ </tr>
130+ <tr>
131+ <td>offsetW</td>
132+ <td>输入</td>
133+ <td>标量,表示矩阵乘右输入的偏移量。</td>
134+ <td>当前仅支持空指针传入。</td>
135+ <td>INT8</td>
136+ <td>-</td>
137+ <td>与x2_unzip一致。</td>
138+ <td>-</td>
139+ </tr>
140+ <tr>
141+ <td>offsetX</td>
142+ <td>输入</td>
143+ <td>标量,表示矩阵乘左输入的偏移量。</td>
144+ <td>当前仅支持0。</td>
145+ <td>INT32</td>
146+ <td>-</td>
147+ <td>-</td>
148+ <td>-</td>
149+ </tr>
150+ <tr>
151+ <td>compressInfo</td>
152+ <td>输入</td>
153+ <td>整型数据列表,数据类型为INT64。其中包括压缩块信息tilingN、tilingK(通过msModelSlim工具中weight_compression模块压缩后获取,分别表示压缩前shape(n, k)在n方向和k方向上一个基本压缩块的大小),压缩前x2矩阵原始shape(shape为2维,用(n, k)表示),以及压缩块遍历方向的标识。</td>
154+ <td>-</td>
155+ <td>INT64</td>
156+ <td>-</td>
157+ <td>-</td>
158+ <td>-</td>
159+ </tr>
160+ <tr>
161+ <td>out</td>
162+ <td>输出</td>
163+ <td>计算输出。</td>
164+ <td>-</td>
165+ <td>FLOAT16</td>
166+ <td>ND</td>
167+ <td>2</td>
168+ <td>-</td>
169+ </tr>
170+ <tr>
171+ <td>workspaceSize</td>
172+ <td>出参</td>
173+ <td>返回需要在Device侧申请的workspace大小。</td>
174+ <td>-</td>
175+ <td>-</td>
176+ <td>-</td>
177+ <td>-</td>
178+ <td>-</td>
179+ </tr>
180+ <tr>
181+ <td>executor</td>
182+ <td>出参</td>
183+ <td>返回op执行器,包含了算子计算流程。</td>
184+ <td>-</td>
185+ <td>-</td>
186+ <td>-</td>
187+ <td>-</td>
188+ <td>-</td>
189+ </tr>
190+ </tbody>
191+ </table>
192+ 
193+- **返回值**
194+
195+ aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../docs/zh/context/aclnn返回码.md)。
196+ 
197+ 第一段接口完成入参校验,出现以下场景时报错:
198+ 
199+ <table style="undefined;table-layout: fixed; width: 1475px"><colgroup>
200+ <col style="width: 300px">
201+ <col style="width: 200px">
202+ <col style="width: 975px">
203+ </colgroup>
204+ <thead>
205+ <tr>
206+ <th>返回值</th>
207+ <th>错误码</th>
208+ <th>描述</th>
209+ </tr></thead>
210+ <tbody>
211+ <tr>
212+ <td>ACLNN_ERR_PARAM_NULLPTR</td>
213+ <td>161001</td>
214+ <td>传入的x1、x2或out是空指针。</td>
215+ </tr>
216+ <tr>
217+ <td rowspan="3">ACLNN_ERR_PARAM_INVALID</td>
218+ <td rowspan="3">161002</td>
219+ <td>x1或x2的数据类型和数据格式不在支持的范围之内。</td>
220+ </tr>
221+ <tr>
222+ <td>x1或x2无法做数据类型推导。</td>
223+ </tr>
224+ <tr>
225+ <td>推导出的数据类型无法转换为指定输出out的类型。</td>
226+ </tr>
227+ </tbody>
228+ </table>
229+ 
230+## aclnnMatmulCompressDequant
231+ 
232+- **参数说明**
233+ <table style="undefined;table-layout: fixed; width: 1475px"><colgroup>
234+ <col style="width: 300px">
235+ <col style="width: 200px">
236+ <col style="width: 975px">
237+ </colgroup>
238+ <thead>
239+ <tr>
240+ <th>参数名</th>
241+ <th>输入/输出</th>
242+ <th>描述</th>
243+ </tr></thead>
244+ <tbody>
245+ <tr>
246+ <td>workspace</td>
247+ <td>输入</td>
248+ <td>在Device侧申请的workspace内存地址。</td>
249+ </tr>
250+ <tr>
251+ <td>workspaceSize</td>
252+ <td>输入</td>
253+ <td>在Device侧申请的workspace大小,由第一段接口aclnnMatmulCompressDequantGetWorkspaceSize获取。</td>
254+ </tr>
255+ <tr>
256+ <td>executor</td>
257+ <td>输入</td>
258+ <td>op执行器,包含了算子计算流程。</td>
259+ </tr>
260+ <tr>
261+ <td>stream</td>
262+ <td>输入</td>
263+ <td>指定执行任务的Stream。</td>
264+ </tr>
265+ </tbody>
266+ </table>
267+ 
268+- **返回值**
269+ 
270+ aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../docs/zh/context/aclnn返回码.md)。
271+ 
272+## 约束说明
273+ 
274+- 确定性计算:
275+ - aclnnMatmulCompressDequant默认确定性实现。
276+ 
277+## 调用示例
278+ 
279+- **准备压缩前的数据**
280+
281+ 假设通过脚本gen_data.py生成输入数据,示例如下,仅供参考:
282+
283+ ```python
284+ import numpy as np
285+ import os
286+ import sys
287+ from numpy import random
288+ 
289+ def write2file(data, path):
290+ with open(path, 'wb') as f:
291+ data.tofile(f)
292+ 
293+ if not os.path.exists("./data"):
294+ os.mkdir("./data")
295+ 
296+ if len(sys.argv) != 4:
297+ print("Usage: python gen_data.py m k n")
298+ sys.exit(1)
299+ 
300+ m = int(sys.argv[1])
301+ k = int(sys.argv[2])
302+ n = int(sys.argv[3])
303+ 
304+ if m <= 0 or k <= 0 or n <= 0:
305+ print("Error: m, k and n must be positive integers.")
306+ sys.exit(1)
307+ 
308+ # 随机生成矩阵mat1,shape为(m,k )
309+ mat1 = random.randn(m, k).astype(np.int8)
310+ write2file(mat1, "./data/mat1.bin")
311+ 
312+ # 随机生成矩阵mat2,shape为(n, k)
313+ mat2 = random.randint(0, 100, size=(n, k)).astype(np.int8)
314+ np.save("./data/weight.npy", {'weight': mat2})
315+ os.chmod("./data/weight.npy", 0o0640)
316+ 
317+ # 生成output
318+ output = np.random.randn(m, n).astype(np.float16)
319+ write2file(output, "./data/output.bin")
320+ 
321+ # 生成bias
322+ bias = random.randn(n).astype(np.float32)
323+ write2file(bias, "./data/bias.bin")
324+ 
325+ # 生成deq_scale
326+ deq_scale = random.randn(n).astype(np.float32)
327+ write2file(deq_scale, "./data/deqScale_ori.bin")
328+ deq_scale_int64 = np.fromfile("./data/deqScale_ori.bin", dtype=np.int32).astype(np.int64)
329+ deq_scale_int64.tofile("./data/deqScale.bin")
330+ ```
331+ 
332+ 执行gen_data.py,假设mat1和mat2的shape入参为m=512、k=1024、n=1024。
333+
334+ ```shell
335+ python3 gen_data.py 512 1024 1024
336+ ```
337+ 
338+- **对数据进行预处理**
339+ 
340+ - **原始权重通过msModelSlim压缩工具生成压缩后的x2、compressIndex以及compressInfo**
341+
342+ 使用以下接口时,需对CANN包中msModelSlim压缩工具进行编译,具体操作参考[Gitee msit仓](https://gitee.com/ascend/msit/tree/master/msmodelslim)中msmodelslim/pytorch/weight_compression目录下的README.md。
343+ 
344+ ```python
345+ from msmodelslim.pytorch.weight_compression import CompressConfig, Compressor
346+ 
347+ compress_config = CompressConfig(do_pseudo_sparse=False, sparse_ratio=1)
348+ compressor = Compressor(compress_config, weight_path=weight_path)
349+ 
350+ compress_weight, compress_index, compress_info = compressor.run()
351+ # 压缩后的权重,对应aclnnMatmulCompressDequantGetWorkspaceSize接口的x2
352+ compressor.export(compress_weight, './data/weight')
353+ # 压缩权重的索引,对应aclnnMatmulCompressDequantGetWorkspaceSize接口的compressIndex
354+ compressor.export(compress_index, './data/index')
355+ # 压缩数据的相关信息,对应aclnnMatmulCompressDequantGetWorkspaceSize接口的compressInfo
356+ compressor.export(compress_info, './data/compress_info')
357+ ```
358+ 
359+ - **将原始float类型的反量化参数deqscale进行转换, 得到aclnn接口需要的uint64数据**
360+ 
361+ deqScale原始为float类型,以int32读取并转换为int64
362+ 
363+ ```python
364+ import numpy as np
365+ data = np.fromfile('./deqScale_original.bin', dtype=np.int32).astype(np.int64)
366+ data.tofile('./deqScale.bin')
367+ ```
368+ 
369+- **调用aclnn接口运算**
370+
371+ 示例代码如下,仅供参考,具体编译和执行过程请参考[编译与运行样例](../../../docs/zh/context/编译与运行样例.md)。
372+ 
373+```Cpp
374+#include <iostream>
375+#include <vector>
376+#include <acl/acl.h>
377+#include <aclnnop/aclnn_matmul_compress_dequant.h>
378+#include <fstream>
379+#include <unistd.h>
380+#include <sys/stat.h>
381+#include <stdio.h>
382+#include <cstdlib>
383+#include <string>
384+ 
385+#define CHECK_RET(cond, return_expr) \
386+ do { \
387+ if (!(cond)) { \
388+ return_expr; \
389+ } \
390+ } while (0)
391+ 
392+#define LOG_PRINT(message, ...) \
393+ do { \
394+ printf(message, ##__VA_ARGS__); \
395+ } while (0)
396+ 
397+int64_t GetShapeSize(const std::vector<int64_t>& shape) {
398+ int64_t shapeSize = 1;
399+ for (auto i : shape) {
400+ shapeSize *= i;
401+ }
402+ return shapeSize;
403+}
404+ 
405+int Init(int32_t deviceId, aclrtStream* stream) {
406+ // 固定写法,资源初始化
407+ auto ret = aclInit(nullptr);
408+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
409+ ret = aclrtSetDevice(deviceId);
410+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
411+ ret = aclrtCreateStream(stream);
412+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
413+ return 0;
414+}
415+ 
416+int ReadBinFileNNop(std::string filePath, void* buffer, size_t bufferSize)
417+{
418+ struct stat sBuf;
419+ int fileStatus = stat(filePath.data(), &sBuf);
420+ CHECK_RET(fileStatus == ACL_SUCCESS, LOG_PRINT("Failed to get file %s\n", filePath); return -1);
421+ 
422+ std::ifstream file;
423+ file.open(filePath, std::ios::binary);
424+ CHECK_RET(file.is_open(), LOG_PRINT("Open file failed.\n"); return -1);
425+ 
426+ file.seekg(0, file.end);
427+ uint64_t binFileBufferLen = file.tellg();
428+ CHECK_RET(binFileBufferLen > 0,
429+ std::cout<<"File size is 0.\n";
430+ file.close();
431+ return -1);
432+ 
433+ file.seekg(0, file.beg);
434+ file.read(static_cast<char *>(buffer), binFileBufferLen);
435+ file.close();
436+ return ACL_SUCCESS;
437+}
438+ 
439+int CreateAclTensor(std::string filePath, const std::vector<int64_t>& shape, int typeSize,
440+ void** deviceAddr, aclDataType dataType, aclTensor** tensor) {
441+ auto size = GetShapeSize(shape) * typeSize;
442+ // 调用aclrtMalloc申请device侧内存
443+ auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
444+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
445+ 
446+ // 调用aclrtMallocHost申请host侧内存
447+ void* binBufferHost = nullptr;
448+ ret = aclrtMallocHost(&binBufferHost, size);
449+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMallocHost failed. ERROR: %d\n", ret); return ret);
450+ 
451+ // 读取文件
452+ ret = ReadBinFileNNop(filePath, binBufferHost, size);
453+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("ReadBinFileNNop failed. ERROR: %d\n", ret); return ret);
454+ 
455+ // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上
456+ ret = aclrtMemcpy(*deviceAddr, size, binBufferHost, size, ACL_MEMCPY_HOST_TO_DEVICE);
457+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
458+ 
459+ // 计算连续tensor的strides
460+ std::vector<int64_t> strides(shape.size(), 1);
461+ for (int64_t i = shape.size() - 2; i >= 0; i--) {
462+ strides[i] = shape[i + 1] * strides[i + 1];
463+ }
464+ 
465+ // 调用aclCreateTensor接口创建aclTensor
466+ *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND,
467+ shape.data(), shape.size(), *deviceAddr);
468+ return 0;
469+}
470+ 
471+int main(int argc, char* argv[]) {
472+ // 1. (固定写法)device/stream初始化,参考acl API手册
473+ // 根据自己的实际device填写deviceId
474+ int32_t deviceId = 0;
475+ aclrtStream stream;
476+ auto ret = Init(deviceId, &stream);
477+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
478+ 
479+ if (argc != 6) {
480+ std::cerr << "Error: Invalid number of arguments. Usage: <program> m k n wCompressedSize indexSize" << std::endl;
481+ return -1;
482+ }
483+ 
484+ // 2. 构造输入与输出,需要根据API的接口自定义构造
485+ int m = atoi(argv[1]);
486+ int k = atoi(argv[2]);
487+ int n = atoi(argv[3]);
488+ // wShape是右矩阵压缩后数据的大小
489+ int wCompressedSize = atoi(argv[4]);
490+ // indexShape是压缩索引数据的大小
491+ int indexSize = atoi(argv[5]);
492+ 
493+ if (m <= 0 || k <= 0 || n <= 0 || wCompressedSize <= 0 || indexSize <= 0) {
494+ std::cerr << "Error: m, k, n, wCompressedSize and indexSize must be positive integers." << std::endl;
495+ return -1;
496+ }
497+ 
498+ std::vector<int64_t> mat1Shape = {m, k};
499+ std::vector<int64_t> mat2CompressedShape = {wCompressedSize};
500+ std::vector<int64_t> indexShape = {indexSize};
501+ std::vector<int64_t> biasShape = {n};
502+ std::vector<int64_t> deqScaleShape = {n};
503+ std::vector<int64_t> outputShape = {m, n};
504+ 
505+ std::vector<int64_t> compressInfoHostData = {8, 8, k, n, 1};
506+ 
507+ void* mat1DeviceAddr = nullptr;
508+ void* mat2CompressedDeviceAddr = nullptr;
509+ void* indexDeviceAddr = nullptr;
510+ void* biasDeviceAddr = nullptr;
511+ void* deqScaleDeviceAddr = nullptr;
512+ void* outputDeviceAddr = nullptr;
513+ 
514+ aclTensor* mat1 = nullptr;
515+ aclTensor* mat2Compressed = nullptr;
516+ aclTensor* index = nullptr;
517+ aclTensor* bias = nullptr;
518+ aclTensor* deqScale = nullptr;
519+ aclTensor* output = nullptr;
520+ aclIntArray* compressInfo = nullptr;
521+ 
522+ std::string rootPath = "./data/";
523+ 
524+ // 创建mat1 aclTensor
525+ std::string mat1FilePath = rootPath + "mat1.bin";
526+ ret = CreateAclTensor(mat1FilePath, mat1Shape, sizeof(int8_t), &mat1DeviceAddr, aclDataType::ACL_INT8, &mat1);
527+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create mat1 tensor failed. ERROR: %d\n", ret); return ret);
528+ // 创建mat2Compressed aclTensor
529+ std::string mat2FilePath = rootPath + "weight/weight.dat";
530+ ret = CreateAclTensor(mat2FilePath, mat2CompressedShape, sizeof(int8_t), &mat2CompressedDeviceAddr,
531+ aclDataType::ACL_INT8, &mat2Compressed);
532+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create mat2 tensor failed. ERROR: %d\n", ret); return ret);
533+ // 创建index aclTensor
534+ std::string indexFilePath = rootPath + "index/weight.dat";
535+ ret = CreateAclTensor(indexFilePath, indexShape, sizeof(int8_t), &indexDeviceAddr, aclDataType::ACL_INT8, &index);
536+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create index tensor failed. ERROR: %d\n", ret); return ret);
537+ // 创建bias aclTensor
538+ std::string biasFilePath = rootPath + "bias.bin";
539+ ret = CreateAclTensor(biasFilePath, biasShape, sizeof(int32_t), &biasDeviceAddr, aclDataType::ACL_INT32, &bias);
540+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create bias tensor failed. ERROR: %d\n", ret); return ret);
541+ // 创建deqScale aclTensor
542+ std::string deqScaleFilePath = rootPath + "deqScale.bin";
543+ ret = CreateAclTensor(deqScaleFilePath, deqScaleShape, sizeof(int32_t), &deqScaleDeviceAddr, aclDataType::ACL_UINT64,
544+ &deqScale);
545+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create deqScale tensor failed. ERROR: %d\n", ret); return ret);
546+ // 创建compressInfo
547+ compressInfo = aclCreateIntArray(compressInfoHostData.data(), aclDataType::ACL_INT64);
548+ // 创建out aclTensor
549+ std::string outputFilePath = rootPath + "output.bin";
550+ ret = CreateAclTensor(outputFilePath, outputShape, 2, &outputDeviceAddr, aclDataType::ACL_FLOAT16, &output);
551+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create output tensor failed. ERROR: %d\n", ret); return ret);
552+ 
553+ int32_t offsetX = 0;
554+ 
555+ // 3. 调用CANN算子库API,需要修改为具体的Api名称
556+ uint64_t workspaceSize = 0;
557+ aclOpExecutor* executor;
558+ // 调用aclnnMm第一段接口
559+ ret = aclnnMatmulCompressDequantGetWorkspaceSize(mat1, mat2Compressed, index, bias, deqScale, nullptr, offsetX, compressInfo, output, &workspaceSize, &executor);
560+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMatmulCompressDequantGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
561+ // 根据第一段接口计算出的workspaceSize申请device内存
562+ void* workspaceAddr = nullptr;
563+ if (workspaceSize > 0) {
564+ ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
565+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
566+ }
567+ // 调用aclnnMm第二段接口
568+ ret = aclnnMatmulCompressDequant(workspaceAddr, workspaceSize, executor, stream);
569+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMatmulCompressDequant failed. ERROR: %d\n", ret); return ret);
570+ 
571+ // 4. (固定写法)同步等待任务执行结束
572+ ret = aclrtSynchronizeStream(stream);
573+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
574+ 
575+ // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改
576+ auto size = GetShapeSize(outputShape);
577+ std::vector<float> resultData(size, 0);
578+ ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outputDeviceAddr,
579+ size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST);
580+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
581+ for (int64_t i = 0; i < size; i++) {
582+ LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]);
583+ }
584+ 
585+ // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改
586+ aclDestroyTensor(mat1);
587+ aclDestroyTensor(mat2Compressed);
588+ aclDestroyTensor(index);
589+ aclDestroyTensor(bias);
590+ aclDestroyTensor(deqScale);
591+ aclDestroyTensor(output);
592+ aclDestroyIntArray(compressInfo);
593+ 
594+ // 7.释放硬件资源,需要根据具体API的接口定义修改
595+ aclrtFree(mat1DeviceAddr);
596+ aclrtFree(mat2CompressedDeviceAddr);
597+ aclrtFree(indexDeviceAddr);
598+ aclrtFree(biasDeviceAddr);
599+ aclrtFree(deqScaleDeviceAddr);
600+ aclrtFree(outputDeviceAddr);
601+ if (workspaceSize > 0) {
602+ aclrtFree(workspaceAddr);
603+ }
604+ aclrtDestroyStream(stream);
605+ aclrtResetDevice(deviceId);
606+ aclFinalize();
607+ return 0;
608+}
609+```
@@ -0,0 +1,14 @@
1+# ----------------------------------------------------------------------------
2+# This program is free software, you can redistribute it and/or modify it.
3+# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4+# This file is a part of the CANN Open Software.
5+# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").
6+# Please refer to the License for details. You may not use this file except in compliance with the License.
7+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
8+# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
9+# See LICENSE in the root of the software repository for the full text of the License.
10+# ----------------------------------------------------------------------------
11+ 
12+# add_modules_sources(OPTYPE matmul_v2_compress_dequant ACLNNTYPE aclnn_exclude)
13+# add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE matmul_v2_compress_dequant)
14+add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE matmul_v2_compress_dequant ACLNNTYPE aclnn_exclude DEPENDENCIES transpose_batch_mat_mul)
@@ -0,0 +1,95 @@
1+{
2+ "op_type": "MatMulV2CompressDequant",
3+ "op_list": [
4+ {
5+ "bin_filename": "MatmulV2CompressDequant_Int8",
6+ "inputs": [
7+ {
8+ "name": "x1",
9+ "index": 0,
10+ "dtype": "int8",
11+ "format": "ND",
12+ "paramType": "required",
13+ "shape": [-2]
14+ },
15+ {
16+ "name": "x2",
17+ "index": 1,
18+ "dtype": "int8",
19+ "format": "ND",
20+ "paramType": "required",
21+ "shape": [-2]
22+ },
23+ {
24+ "name": "compress_index",
25+ "index": 2,
26+ "dtype": "int8",
27+ "format": "ND",
28+ "paramType": "required",
29+ "shape": [-2]
30+ },
31+ {
32+ "name": "deq_scale",
33+ "index": 3,
34+ "dtype": "uint64",
35+ "format": "ND",
36+ "paramType": "required",
37+ "shape": [-2]
38+ },
39+ {
40+ "name": "bias",
41+ "index": 4,
42+ "dtype": "int32",
43+ "format": "ND",
44+ "paramType": "required",
45+ "shape": [-2]
46+ },
47+ {
48+ "name": "offset_w",
49+ "index": 5,
50+ "dtype": "int8",
51+ "format": "ND",
52+ "paramType": "optional",
53+ "shape": [-2]
54+ }
55+ ],
56+ "outputs": [
57+ {
58+ "name": "out",
59+ "index": 0,
60+ "dtype": "float16",
61+ "format": "ND",
62+ "paramType": "required",
63+ "shape": [-2]
64+ }
65+ ],
66+ "attrs": [
67+ {
68+ "name": "transpose_x1",
69+ "dtype": "bool",
70+ "value": null
71+ },
72+ {
73+ "name": "transpose_x2",
74+ "dtype": "bool",
75+ "value": null
76+ },
77+ {
78+ "name": "compress_info",
79+ "dtype": "list_int",
80+ "value": null
81+ },
82+ {
83+ "name": "offset_x",
84+ "dtype": "int",
85+ "value": null
86+ },
87+ {
88+ "name": "alg",
89+ "dtype": "string",
90+ "value": null
91+ }
92+ ]
93+ }
94+ ]
95+}
@@ -0,0 +1,74 @@
1+/**
2+ * Copyright (c) 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 matmul_v2_compress_dequant_def.cpp
13+ * \brief MatMulV2CompressDequant op definition for ascend310p
14+ */
15+#include "register/op_def_registry.h"
16+ 
17+namespace ops {
18+class MatMulV2CompressDequant : public OpDef {
19+public:
20+ explicit MatMulV2CompressDequant(const char* name) : OpDef(name)
21+ {
22+ this->Input("x1")
23+ .ParamType(REQUIRED)
24+ .DataType({ge::DT_INT8})
25+ .Format({ge::FORMAT_ND})
26+ .UnknownShapeFormat({ge::FORMAT_ND});
27+ this->Input("x2")
28+ .ParamType(REQUIRED)
29+ .DataType({ge::DT_INT8})
30+ .Format({ge::FORMAT_ND})
31+ .UnknownShapeFormat({ge::FORMAT_ND});
32+ this->Input("compress_index")
33+ .ParamType(REQUIRED)
34+ .DataType({ge::DT_INT8})
35+ .Format({ge::FORMAT_ND})
36+ .UnknownShapeFormat({ge::FORMAT_ND});
37+ this->Input("deq_scale")
38+ .ParamType(REQUIRED)
39+ .DataType({ge::DT_UINT64})
40+ .Format({ge::FORMAT_ND})
41+ .UnknownShapeFormat({ge::FORMAT_ND});
42+ this->Input("bias")
43+ .ParamType(REQUIRED)
44+ .DataType({ge::DT_INT32})
45+ .Format({ge::FORMAT_ND})
46+ .UnknownShapeFormat({ge::FORMAT_ND});
47+ this->Input("offset_w")
48+ .ParamType(OPTIONAL)
49+ .DataType({ge::DT_INT8})
50+ .Format({ge::FORMAT_ND})
51+ .UnknownShapeFormat({ge::FORMAT_ND});
52+ this->Attr("transpose_x1").AttrType(OPTIONAL).Bool(false);
53+ this->Attr("transpose_x2").AttrType(OPTIONAL).Bool(false);
54+ this->Attr("compress_info").AttrType(OPTIONAL).ListInt({1, 1, 1, 1, 1});
55+ this->Attr("offset_x").AttrType(OPTIONAL).Int(0);
56+ this->Attr("alg").AttrType(OPTIONAL).String("weight_unzip");
57+ this->Output("out")
58+ .ParamType(REQUIRED)
59+ .DataType({ge::DT_FLOAT16})
60+ .Format({ge::FORMAT_ND})
61+ .UnknownShapeFormat({ge::FORMAT_ND});
62+ 
63+ OpAICoreConfig config_310p;
64+ config_310p.DynamicCompileStaticFlag(true)
65+ .DynamicRankSupportFlag(true)
66+ .DynamicShapeSupportFlag(true)
67+ .NeedCheckSupportFlag(false)
68+ .ExtendCfgInfo("opFile.value", "matmul_v2_compress_dequant");
69+ this->AICore().AddConfig("ascend310p", config_310p);
70+ }
71+};
72+ 
73+OP_ADD(MatMulV2CompressDequant);
74+} // namespace ops
@@ -0,0 +1,301 @@
1+/**
ww-blue
ww-blueww-blue5月19日

tiling文件建议放到单独的文件夹下,op_tiling

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
2+ * Copyright (c) 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 matmul_v2_compress_dequant_tiling.cpp
13+ * \brief Tiling implementation for matmul_v2_compress_dequant
14+ * Core algorithm ported from pp_matmul_i8_nz_tiling.cpp
15+ */
16+#include "matmul_v2_compress_dequant_tiling.h"
17+#include "op_host/tiling_util.h"
18+#include "log/log.h"
19+#include <algorithm>
20+#include <cmath>
21+#include "pp_matmul_default.h"
22+#include "pp_matmul_info.h"
23+ 
24+namespace optiling {
25+namespace {
26+ 
27+// ============================================================
28+// Constants (aligned with pp_matmul common_tiling.h)
29+// ============================================================
30+constexpr uint32_t BLOCK_SIZE_16 = 16;
31+constexpr uint32_t BLOCK_SIZE_INT8_K = 32;
32+constexpr uint32_t BASE_BLOCK_STEP = 2;
33+constexpr uint32_t FP16_BYTE_SIZE = 2;
34+constexpr uint32_t FP32_BYTE_SIZE = 4;
35+constexpr float INT8_DTYPE_SIZE = 1.0f;
36+constexpr uint32_t AXES_ALIGN_SIZE = 512;
37+constexpr uint32_t AXES_ALIGN_SIZE_INT8 = 256;
38+constexpr uint32_t L0AB_PP_BUF_LEN_FP16 = 131072; // 128 KB
39+constexpr uint32_t L1AB_PP_BUF_LEN_INT8_SPARSE = 163840; // 160 KB
40+constexpr uint32_t ALIGNMENT_16 = 16;
41+constexpr uint32_t CONST_3 = 3;
42+constexpr uint32_t CONST_4 = 4;
43+constexpr uint32_t CONST_256 = 256;
44+constexpr uint32_t TRANS_B_MASK = 0b001000;
45+constexpr float L2_BW_RATIO = 5.0f;
46+constexpr uint64_t DEFAULT_L2_SIZE = 48UL * 1024 * 1024; // 48 MB
47+constexpr uint64_t DEFAULT_L0C_SIZE = 256UL * 1024; // 256 KB
48+ 
49+constexpr size_t TRANSPOSE_X1_ATTR_IDX = 0;
50+constexpr size_t TRANSPOSE_X2_ATTR_IDX = 1;
51+constexpr size_t COMPRESS_INFO_ATTR_IDX = 2;
52+ 
53+constexpr size_t CI_IDX_TILING_K = 0;
54+constexpr size_t CI_IDX_TILING_N = 1;
55+constexpr size_t CI_IDX_K = 2;
56+constexpr size_t CI_IDX_N = 3;
57+constexpr size_t COMPRESS_INFO_MIN_ELEMS = 4;
58+ 
59+constexpr size_t INPUT_IDX_X1 = 0;
60+constexpr size_t INPUT_IDX_BIAS = 4;
61+ 
62+// ============================================================
63+// Utility functions
64+// ============================================================
65+ 
66+ 
67+inline uint32_t CeilDivU32(uint32_t dividend, uint32_t divisor)
68+{
69+ if (divisor == 0 || dividend + divisor - 1 < dividend) {
70+ return dividend;
71+ }
72+ return (dividend + divisor - 1) / divisor;
73+}
74+ 
75+ 
76+// // ============================================================
77+// // Compute k0 and compressOverlapN
78+// // Ported from PpTilingData310P::End
79+// // ============================================================
80+uint32_t ComputeK0(uint32_t n0, uint32_t n,
81+ bool isCompress, uint32_t tilingNVal,
82+ uint32_t &compressOverlapN)
83+{
84+ compressOverlapN = 0;
85+ 
86+ if (isCompress) {
87+ if (n0 == 0) {
88+ return 1;
89+ }
90+ uint32_t nTail = n % n0;
91+ uint32_t compressNTile = (tilingNVal > 0) ? (CeilDivU32(nTail, ALIGNMENT_16) % tilingNVal) : 0;
92+ compressOverlapN = (compressNTile == 0) ? 0 : tilingNVal - compressNTile;
93+ }
94+ return 0;
95+}
96+ 
97+// ============================================================
98+// Extract M, K, N, batchSize from TilingContext
99+// Handles both ND shapes (2D: [M, K]) and NZ shapes (4D)
100+// ============================================================
101+ge::graphStatus ExtractMatmulDims(const gert::TilingContext *context, uint32_t &batchSize, uint32_t &m, uint32_t &k,
102+ uint32_t &n, const int64_t *compressInfoData, size_t compressInfoCount)
103+{
104+ const auto *x1ShapePtr = context->GetInputShape(INPUT_IDX_X1);
105+ if (x1ShapePtr == nullptr) {
106+ OP_LOGE("MatMulV2CompressDequant", "x1 shape is nullptr.");
107+ return ge::GRAPH_FAILED;
108+ }
109+ const auto &x1Shape = x1ShapePtr->GetOriginShape();
110+ 
111+ m = static_cast<uint32_t>(x1Shape.GetDim(0));
112+ k = static_cast<uint32_t>(x1Shape.GetDim(1));
113+ // 输入是个2维
114+ batchSize = 1;
115+ 
116+ n = 0;
117+ if (compressInfoCount > CI_IDX_N && compressInfoData != nullptr) {
118+ n = static_cast<uint32_t>(compressInfoData[CI_IDX_N]);
119+ }
120+ if (n == 0) {
121+ const auto *outShapePtr = context->GetOutputShape(0);
122+ if (outShapePtr != nullptr) {
123+ const auto &outShape = outShapePtr->GetStorageShape();
124+ size_t outNdim = outShape.GetDimNum();
125+ if (outNdim >= 4) {
126+ n = static_cast<uint32_t>(outShape.GetDim(outNdim - 4) *
127+ outShape.GetDim(outNdim - 1));
128+ } else if (outNdim >= 2) {
129+ n = static_cast<uint32_t>(outShape.GetDim(outNdim - 1));
130+ }
131+ }
132+ }
133+ 
134+ if (m == 0 || k == 0 || n == 0) {
135+ OP_LOGE("MatMulV2CompressDequant", "Invalid dims: m=%u, k=%u, n=%u.", m, k, n);
136+ return ge::GRAPH_FAILED;
137+ }
138+ return ge::GRAPH_SUCCESS;
139+}
140+ 
141+} // namespace
142+ 
143+ 
144+static ge::graphStatus TbmmEinsumTilingFunc (gert::TilingContext* context,
145+ uint32_t &batchSize, uint32_t &m, uint32_t &k, uint32_t &n,
146+ uint32_t& tilingK, uint32_t& tilingN)
147+{
148+ if (context == nullptr) {
149+ OP_LOGE("MatMulV2CompressDequant", "context is null.");
150+ return ge::GRAPH_FAILED;
151+ }
152+ auto compileInfo = reinterpret_cast<const MatmulV2CompressDequantCompileInfo *>(context->GetCompileInfo());
153+ uint32_t coreNum = static_cast<uint32_t>(compileInfo->aivNum);
154+ 
155+ size_t sysWorkspaceSize = static_cast<size_t>(24 * 1024 * 1024); // 24M same as ppmatmul tiling
V
Vvoid_ptr5月19日

[Minor] TbmmEinsumTilingFunc 内将 workspace 设为 24MB,但 TilingForMatmulV2CompressDequant 末尾又用 compileInfo->workSpaceSize 覆盖。若最终只保留后者,建议删除中间的 24MB 赋值,避免误导后续维护者。

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
156+ size_t* currentWorkSpace = context->GetWorkspaceSizes(1);
157+ currentWorkSpace[0] = sysWorkspaceSize;
158+ 
159+ optiling::pp_matmul::matmulCompressDequant::PpMatMulDefault tbmmEinsumTiling(context);
160+ auto inputDType = context->GetInputDesc(0)->GetDataType();
161+ 
162+ tbmmEinsumTiling.matMulInfo_.isInt8 = (inputDType == ge::DT_INT8);
163+ tbmmEinsumTiling.matMulInfo_.inDtype = ge::GetSizeByDataType(inputDType);
164+ (void)tbmmEinsumTiling.GetHardwareInfo();
165+ 
166+ // 设置一个m, k, n
167+ tbmmEinsumTiling.matMulInfo_.m = m;
168+ tbmmEinsumTiling.matMulInfo_.k = k;
169+ tbmmEinsumTiling.matMulInfo_.n = n;
170+ tbmmEinsumTiling.matMulInfo_.batchSize = batchSize;
171+ (void)tbmmEinsumTiling.GetMatMulTilingData();
172+ (void)tbmmEinsumTiling.PrintTiling();
173+ 
174+ uint32_t compressOverlapN = 0;
175+ (void)ComputeK0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n0,
176+ tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n, true, tilingN, compressOverlapN);
177+ // PostTiling
178+ uint32_t blockDim = std::min(tbmmEinsumTiling.ppMatmulDefaultTilingData_.coreLoop, (uint64_t)coreNum);
179+ context->SetBlockDim(blockDim);
180+ MatmulV2CompressDequantTilingData tiling;
181+ tiling.set_batchSize(batchSize);
182+ tiling.set_m(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.m);
183+ tiling.set_k(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.k);
184+ tiling.set_n(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n);
185+ tiling.set_m0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.m0);
186+ tiling.set_k0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.k0);
187+ tiling.set_n0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n0);
188+ tiling.set_mLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.mLoop);
189+ tiling.set_kLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.kLoop);
190+ tiling.set_nLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.nLoop);
191+ tiling.set_coreLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.coreLoop);
192+ tiling.set_swizzlCount(tbmmEinsumTiling.ppMatmulDefaultTilingData_.swizzlCount);
193+ tiling.set_tilingK(tilingK);
194+ tiling.set_tilingN(tilingN);
195+ tiling.set_compressOverlapN(compressOverlapN);
196+ tiling.set_tilingKey(0);
197+ tiling.set_blockDimVal(blockDim);
198+ tiling.set_splitK(0);
199+ tiling.SaveToBuffer(context->GetRawTilingData()->GetData(), context->GetRawTilingData()->GetCapacity());
200+ context->GetRawTilingData()->SetDataSize(tiling.GetDataSize());
201+ 
202+ return ge::GRAPH_SUCCESS;
203+}
204+ 
205+ 
206+// ============================================================
207+// Main tiling function
208+// ============================================================
209+ge::graphStatus TilingForMatmulV2CompressDequant(gert::TilingContext *context)
210+{
211+ OP_LOGI(context->GetNodeName(), "TbmmEinsum Tiling start.");
212+ 
213+ uint32_t batchSize = 1;
214+ uint32_t m = 0;
215+ uint32_t k = 0;
216+ uint32_t n = 0;
217+ const int64_t *compressInfoData = nullptr;
218+ size_t compressInfoCount = 0;
219+ auto *attrs = context->GetAttrs();
220+ const auto *compressInfoVec = attrs->GetAttrPointer<gert::ContinuousVector>(COMPRESS_INFO_ATTR_IDX);
221+ compressInfoCount = compressInfoVec->GetSize();
222+ compressInfoData = reinterpret_cast<const int64_t *>(compressInfoVec->GetData());
223+ 
224+ (void)ExtractMatmulDims(context, batchSize, m, k, n,
V
Vvoid_ptr5月19日

[Major] ExtractMatmulDims 失败时(如 compressInfo 缺 N、m/k/n 为 0)返回 GRAPH_FAILED,但此处用 (void) 忽略返回值后仍调用 TbmmEinsumTilingFunc,会在非法维度下继续 tiling。

建议在失败时直接 return ge::GRAPH_FAILED,不要继续执行后续 tiling。

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
225+ compressInfoData, compressInfoCount);
226+ 
227+ uint32_t tilingKVal = 0;
228+ uint32_t tilingNVal = 0;
229+ if (compressInfoData != nullptr && compressInfoCount >= 2) {
230+ tilingKVal = static_cast<uint32_t>(compressInfoData[CI_IDX_TILING_K]);
231+ tilingNVal = static_cast<uint32_t>(compressInfoData[CI_IDX_TILING_N]);
232+ }
233+ TbmmEinsumTilingFunc(context, batchSize, m, k, n, tilingKVal, tilingNVal);
234+ 
235+ auto compileInfo = reinterpret_cast<const MatmulV2CompressDequantCompileInfo *>(context->GetCompileInfo());
236+ 
237+ // ---- Workspace ----
238+ size_t *currentWorkspace = context->GetWorkspaceSizes(1);
239+ currentWorkspace[0] = compileInfo->workSpaceSize;
240+ return ge::GRAPH_SUCCESS;
241+}
242+ 
243+// ============================================================
244+// TilingPrepare – collect compile-time hardware info
245+// ============================================================
246+ge::graphStatus TilingPrepareForMatmulV2CompressDequant(gert::TilingParseContext *context)
247+{
248+ if (context == nullptr) {
249+ OP_LOGE("MatMulV2CompressDequant", "TilingParse context is nullptr.");
250+ return ge::GRAPH_FAILED;
251+ }
252+ OP_LOGD(context, "TilingPrepareForMatmulV2CompressDequant start.");
253+ 
254+ fe::PlatFormInfos* platformInfo = context->GetPlatformInfo();
255+ if (platformInfo == nullptr) {
256+ OP_LOGE("MatMulV2CompressDequant", "platformInfoPtr is null");
257+ return ge::GRAPH_FAILED;
258+ }
259+ 
260+ auto compileInfoPtr = context->GetCompiledInfo<MatmulV2CompressDequantCompileInfo>();
261+ if (compileInfoPtr == nullptr) {
262+ OP_LOGE("MatMulV2CompressDequant", "compileInfoPtr is null");
263+ return ge::GRAPH_FAILED;
264+ }
265+ auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo);
266+ platformInfo->GetPlatformRes("version", "SoC_version", compileInfoPtr->socVersionStr);
267+ std::string val;
268+ std::string dataMoveL12Bt;
269+ platformInfo->GetPlatformRes("AICoreintrinsicDtypeMap", "Intrinsic_fix_pipe_l0c2out", val);
270+ platformInfo->GetPlatformRes("AICoreintrinsicDtypeMap", "Intrinsic_data_move_l12bt", dataMoveL12Bt);
271+ compileInfoPtr->supportL0c2out = !val.empty();
272+ compileInfoPtr->supportL12BtBf16 = (dataMoveL12Bt.find("bf16") != std::string::npos);
273+ compileInfoPtr->workSpaceSize = ascendcPlatform.GetLibApiWorkSpaceSize();
274+ compileInfoPtr->aivNum = ascendcPlatform.GetCoreNumAiv();
275+ compileInfoPtr->aicNum = ascendcPlatform.GetCoreNumAic();
276+ compileInfoPtr->socVersion = ascendcPlatform.GetSocVersion();
277+ compileInfoPtr->npuArch = ascendcPlatform.GetCurNpuArch();
278+ compileInfoPtr->btSize = compileInfoPtr->supportL0c2out ? 1024UL : 0UL; // 1024 is btSize
279+ compileInfoPtr->btSize = compileInfoPtr->supportL12BtBf16 ? 4096UL : compileInfoPtr->btSize; // 4096 is btSize
280+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, compileInfoPtr->ubSize);
281+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L1, compileInfoPtr->l1Size);
282+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_A, compileInfoPtr->l0ASize);
283+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_B, compileInfoPtr->l0BSize);
284+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_C, compileInfoPtr->l0CSize);
285+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L2, compileInfoPtr->l2Size);
286+ 
287+ compileInfoPtr->isRegbase = Ops::NN::OpTiling::IsRegbaseSocVersion(context);
288+ 
289+ OP_LOGD(context, "TilingPrepare end: aivNum=%lu ubSize=%lu l0CSize=%lu l2Size=%lu",
290+ compileInfoPtr->aivNum, compileInfoPtr->ubSize, compileInfoPtr->l0CSize, compileInfoPtr->l2Size);
291+ return ge::GRAPH_SUCCESS;
292+}
293+ 
294+// ============================================================
295+// Registration
296+// ============================================================
297+IMPL_OP_OPTILING(MatMulV2CompressDequant)
ww-blue
ww-blueww-blue5月19日

建议tiling入口和具体的tiling计算逻辑放到不同的cpp中,提高可读性

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
298+ .Tiling(TilingForMatmulV2CompressDequant)
299+ .TilingParse<MatmulV2CompressDequantCompileInfo>(TilingPrepareForMatmulV2CompressDequant);
300+ 
301+} // namespace optiling
@@ -0,0 +1,74 @@
1+/**
ww-blue
ww-blueww-blue5月19日

Tilingdata的定义方式建议与库上代码保持一致,统一为C++结构体定义,保持风格一致

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
2+ * Copyright (c) 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 matmul_v2_compress_dequant_tiling.h
13+ * \brief Tiling data and registration for matmul_v2_compress_dequant
14+ */
15+#ifndef OPS_BUILT_IN_OP_TILING_RUNTIME_MATMUL_V2_COMPRESS_DEQUANT_H
16+#define OPS_BUILT_IN_OP_TILING_RUNTIME_MATMUL_V2_COMPRESS_DEQUANT_H
17+ 
18+#include <cstdint>
19+#include "register/op_impl_registry.h"
20+#include "platform/platform_ascendc.h"
21+#include "platform/platform_infos_def.h"
22+#include "register/tilingdata_base.h"
23+#include "tiling/tiling_api.h"
24+ 
25+namespace optiling {
26+ 
27+BEGIN_TILING_DATA_DEF(MatmulV2CompressDequantTilingData)
28+ TILING_DATA_FIELD_DEF(uint32_t, batchSize);
29+ TILING_DATA_FIELD_DEF(uint32_t, m);
30+ TILING_DATA_FIELD_DEF(uint32_t, k);
31+ TILING_DATA_FIELD_DEF(uint32_t, n);
32+ TILING_DATA_FIELD_DEF(uint32_t, m0);
33+ TILING_DATA_FIELD_DEF(uint32_t, k0);
34+ TILING_DATA_FIELD_DEF(uint32_t, n0);
35+ TILING_DATA_FIELD_DEF(uint32_t, mLoop);
36+ TILING_DATA_FIELD_DEF(uint32_t, kLoop);
37+ TILING_DATA_FIELD_DEF(uint32_t, nLoop);
38+ TILING_DATA_FIELD_DEF(uint32_t, coreLoop);
39+ TILING_DATA_FIELD_DEF(uint32_t, swizzlCount);
40+ TILING_DATA_FIELD_DEF(uint32_t, tilingK);
41+ TILING_DATA_FIELD_DEF(uint32_t, tilingN);
42+ TILING_DATA_FIELD_DEF(uint32_t, compressOverlapN);
43+ TILING_DATA_FIELD_DEF(uint32_t, tilingKey);
44+ TILING_DATA_FIELD_DEF(uint32_t, blockDimVal);
45+ TILING_DATA_FIELD_DEF(uint32_t, splitK);
46+END_TILING_DATA_DEF;
47+ 
48+REGISTER_TILING_DATA_CLASS(MatMulV2CompressDequant, MatmulV2CompressDequantTilingData)
49+ 
50+struct MatmulV2CompressDequantCompileInfo {
51+ uint64_t aicNum{0UL};
52+ uint64_t aivNum{0UL};
53+ uint64_t ubSize = 0;
54+ uint64_t l1Size = 0;
55+ uint64_t l2Size = 0;
56+ uint64_t l0CSize = 0;
57+ uint64_t l0ASize{0UL};
58+ uint64_t l0BSize{0UL};
59+ uint64_t btSize{0UL};
60+ float cubeFreq{0};
61+ NpuArch npuArch;
62+ platform_ascendc::SocVersion socVersion;
63+ std::string socVersionStr = "";
64+ bool supportL0c2out = false;
65+ bool supportL12BtBf16 = false;
66+ uint64_t workSpaceSize = 0;
67+ bool isRegbase = false;
68+};
69+ 
70+ge::graphStatus TilingForMatmulV2CompressDequant(gert::TilingContext *context);
71+ 
72+} // namespace optiling
73+ 
74+#endif // OPS_BUILT_IN_OP_TILING_RUNTIME_MATMUL_V2_COMPRESS_DEQUANT_H
@@ -0,0 +1,305 @@
1+/**
2+ * Copyright (c) 2025 Huawei Technologies Co., Ltd.
L
Lliubo755月20日

op_api要移动到op_host外面

likedislike
wmg1
wmg1
5月20日 评论:
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 aclnn_matmul_compress_dequant.cpp
13+ * \brief
14+ */
15+ 
16+#include "aclnn_matmul_compress_dequant.h"
17+#include "matmul_compress_dequant.h"
18+#include "level0/fill.h"
19+ 
20+#include "aclnn_kernels/common/op_error_check.h"
21+#include "opdev/common_types.h"
22+#include "opdev/op_dfx.h"
23+#include "opdev/make_op_executor.h"
24+#include "opdev/op_executor.h"
25+#include "opdev/op_log.h"
26+#include "opdev/platform.h"
27+ 
28+#include "aclnn_kernels/transdata.h"
29+#include "aclnn_kernels/contiguous.h"
30+ 
31+#include "aclnn/aclnn_base.h"
32+ 
33+using namespace op;
34+#ifdef __cplusplus
35+extern "C" {
36+#endif
37+ 
38+#define K_DIMENSION_INDEX 2
39+#define DEQUANT_SCALE_ALIGN_SIZE 16
40+ 
41+static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LIST = {DataType::DT_INT8};
42+static const std::initializer_list<op::DataType> BIAS_DTYPE_SUPPORT_LIST = {DataType::DT_INT32};
43+static const std::initializer_list<op::DataType> DEQ_SCALE_DTYPE_SUPPORT_LIST = {DataType::DT_UINT64};
44+static const std::initializer_list<op::DataType> OUT_DTYPE_SUPPORT_LIST = {DataType::DT_FLOAT16};
45+ 
46+static const std::string ALG_WEIGHT_UNZIP = "weight_unzip";
47+static const std::string ALG_UNKNOWN = "unknown";
48+ 
49+static op::FVector<int64_t> GetShape(const aclTensor* tensor)
50+{
51+ op::FVector<int64_t> shape;
52+ if (tensor == nullptr) {
53+ shape.push_back(1);
54+ OP_LOGW("The input tensor of Func GetShape is nullptr");
55+ return shape;
56+ }
57+ if (tensor->GetViewShape().GetDimNum() == 0U) {
58+ shape.push_back(1);
59+ } else {
60+ size_t dimNum = tensor->GetViewShape().GetDimNum();
61+ for (size_t idx = 0U; idx < dimNum; idx++) {
62+ int64_t tmpVal = tensor->GetViewShape().GetDim(idx);
63+ shape.push_back(tmpVal);
64+ }
65+ }
66+ return shape;
67+}
68+ 
69+enum UnzipMode { UNKNOWN = 0, WEIGHT_UNZIP = 1 };
70+ 
71+inline static const std::string& GetAlgStr(int algMode)
72+{
73+ if (algMode == UnzipMode::WEIGHT_UNZIP) {
74+ return ALG_WEIGHT_UNZIP;
75+ }
76+ return ALG_UNKNOWN;
77+}
78+ 
79+struct MatmulUnzipInput {
80+ const aclTensor* x1;
81+ const aclTensor* x2;
82+ const aclTensor* compressIndex;
83+ const aclTensor* bias;
84+ const aclTensor* deqScale;
85+ const aclTensor* offsetW;
86+};
87+ 
88+inline static bool CheckNotNull(MatmulUnzipInput matmulUnzipInput, const aclIntArray* compressInfo,
89+ const aclTensor* out)
90+{
91+ OP_CHECK_NULL(matmulUnzipInput.x1, return false);
92+ OP_CHECK_NULL(matmulUnzipInput.x2, return false);
93+ OP_CHECK_NULL(matmulUnzipInput.compressIndex, return false);
94+ OP_CHECK_NULL(matmulUnzipInput.bias, return false);
95+ OP_CHECK_NULL(matmulUnzipInput.deqScale, return false);
96+ OP_CHECK_NULL(compressInfo, return false);
97+ OP_CHECK_NULL(out, return false);
98+ return true;
99+}
100+ 
101+inline static bool CheckDtypeValid(MatmulUnzipInput matmulUnzipInput, const aclTensor* out)
102+{
103+ OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.x1, DTYPE_SUPPORT_LIST, return false);
104+ OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.x2, DTYPE_SUPPORT_LIST, return false);
105+ OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.compressIndex, DTYPE_SUPPORT_LIST, return false);
106+ OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.bias, BIAS_DTYPE_SUPPORT_LIST, return false);
107+ OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.deqScale, DEQ_SCALE_DTYPE_SUPPORT_LIST, return false);
108+ OP_CHECK_DTYPE_NOT_SUPPORT(out, OUT_DTYPE_SUPPORT_LIST, return false);
109+ return true;
110+}
111+ 
112+static bool CheckShapeValid(const aclTensor* x1, const aclTensor* x2, const aclIntArray* compressInfo)
113+{
V
Vvoid_ptr5月19日

[Major] 相较同目录 aclnn_matmul_compress.cpp,本接口缺少对 bias/compressIndex/deqScaleout 维度的 shape 一致性校验(例如 bias 最后一维与 out 的 N 维、compressIndex 长度等)。迁移算子建议补齐与 math 仓一致的前端校验,避免非法 shape 落到 kernel/tiling 才失败。

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
114+ op::Shape x1Shape = x1->GetViewShape();
115+ op::Shape x2Shape = x2->GetViewShape();
116+ auto dimTensor1 = x1Shape.GetDimNum();
117+ auto dimTensor2 = x2Shape.GetDimNum();
118+ int64_t x1KDim = 0;
119+ int64_t x2KDim = 0;
120+ 
121+ if (dimTensor1 != 2 || dimTensor2 != 1) { // ND format dims > 2 for x1
122+ OP_LOGE(
123+ ACLNN_ERR_PARAM_INVALID, "MatmulUnzip not support x1 shape %s, x2 shape %s",
124+ op::ToString(x1Shape).GetString(), op::ToString(x2Shape).GetString());
125+ return false;
126+ } else {
127+ x1KDim = x1Shape.GetDim(dimTensor1 - 1);
128+ x2KDim = (*compressInfo)[K_DIMENSION_INDEX];
V
Vvoid_ptr5月19日

[Major] CheckShapeValid 使用 (*compressInfo)[K_DIMENSION_INDEX](下标 2)前未校验 compressInfo 长度。若用户传入长度 < 3 的数组,可能越界访问。

建议在访问前增加:compressInfo->Size() > K_DIMENSION_INDEX(或文档约定的最小长度 5,与示例 {tilingK, tilingN, k, n, ...} 一致)。

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
129+ if (x1KDim != x2KDim) {
130+ OP_LOGE(
131+ ACLNN_ERR_PARAM_INVALID, "The k-axis of the two inputs are different %s, %s",
132+ op::ToString(x1Shape).GetString(), op::ToString(x2Shape).GetString());
133+ return false;
134+ }
135+ }
136+ 
137+ return true;
138+}
139+ 
140+inline static aclnnStatus CheckParam(MatmulUnzipInput matmulUnzipInput, const aclIntArray* compressInfo,
141+ const aclTensor* out)
142+{
143+ // 1. 检查参数是否为空指针
144+ CHECK_RET(CheckNotNull(matmulUnzipInput, compressInfo, out), ACLNN_ERR_PARAM_NULLPTR);
145+ // 2. 检查输入的数据类型是否在API支持的数据类型范围之内,需要根据api定义校验
146+ CHECK_RET(CheckDtypeValid(matmulUnzipInput, out), ACLNN_ERR_PARAM_INVALID);
147+ // 3. 检查Shape是否支持
148+ CHECK_RET(CheckShapeValid(matmulUnzipInput.x1, matmulUnzipInput.x2, compressInfo), ACLNN_ERR_PARAM_INVALID);
149+ 
150+ return ACLNN_SUCCESS;
151+}
152+ 
153+static const aclTensor* ProcessEmptyTensor(const aclTensor* x1, const aclTensor* out, aclOpExecutor* executor)
154+{
155+ // 获取shape信息
156+ op::Shape outShape = out->GetViewShape();
157+ auto output = executor->AllocTensor(outShape, x1->GetDataType());
158+ if (output->IsEmpty()) {
159+ OP_LOGI("Returning an empty tensor without actually doing calculation");
160+ return output;
161+ }
162+ FVector<int64_t> fillShape = GetShape(output);
163+ const aclTensor* dims = executor->ConvertToTensor(fillShape.data(), fillShape.size(), op::DataType::DT_INT64);
164+ aclIntArray* shapeArray = executor->AllocIntArray(fillShape.data(), fillShape.size());
165+ const aclScalar* valueScalar = executor->AllocScalar(0);
166+ const aclTensor* valueTensor = executor->ConvertToTensor(valueScalar, out->GetDataType());
167+ auto fillTensor = l0op::Fill(dims, valueTensor, shapeArray, executor);
168+ return fillTensor;
169+}
170+ 
171+inline static const aclTensor* TensorReformat(const aclTensor* x, const op::Format& format, aclOpExecutor* executor)
172+{
173+ auto formatTensor = executor == nullptr ? const_cast<aclTensor*>(x) :
174+ executor->CreateView(x, x->GetViewShape(), x->GetViewOffset());
175+ formatTensor->SetViewFormat(format);
176+ formatTensor->SetOriginalFormat(format);
177+ formatTensor->SetStorageFormat(format);
178+ return formatTensor;
179+}
180+ 
181+static aclnnStatus InputsContiguousAndTransFormat(const aclTensor* tensor, const aclTensor*& reformatedTensor,
182+ const std::string& tensorName, aclOpExecutor* executor)
183+{
184+ if (tensor == nullptr) {
185+ return ACLNN_SUCCESS;
186+ }
187+ op::Format tensorFormat = tensor->GetStorageFormat();
188+ if (tensorFormat != Format::FORMAT_FRACTAL_NZ) {
189+ reformatedTensor = l0op::Contiguous(tensor, executor);
190+ CHECK_COND(reformatedTensor != nullptr, ACLNN_ERR_INNER_NULLPTR, "%s Contiguous failed.", tensorName.c_str());
191+ 
192+ bool is310P = GetCurrentPlatformInfo().GetSocVersion() == SocVersion::ASCEND310P;
193+ // only in 310P, tensor should be transdata to NZ format
194+ if (!is310P) {
195+ return ACLNN_SUCCESS;
196+ }
197+ 
198+ reformatedTensor = l0op::TransData(reformatedTensor, Format::FORMAT_FRACTAL_NZ, 1, executor);
199+ CHECK_COND(reformatedTensor != nullptr, ACLNN_ERR_INNER_NULLPTR, "%s TransData failed.", tensorName.c_str());
200+ return ACLNN_SUCCESS;
201+ }
202+ reformatedTensor = tensor;
203+ return ACLNN_SUCCESS;
204+}
205+ 
206+static const aclTensor* BuildMatMulUnzipGraph(MatmulUnzipInput matmulUnzipInput, const int offsetX,
207+ const aclIntArray* compressInfo, aclTensor* out,
208+ aclOpExecutor* executor)
209+{
210+ /*
211+ * x1 x2
212+ * | |
213+ * x1FractalNZ x2ReformatFractalZ
214+ * | |
215+ * \ /
216+ * matmulv2_compress_unzip -- compressIndex, bias, deqScale(format?), offsetW, offsetX, compressInfo
217+ * |
218+ * out
219+ * |
220+ * outND
221+ */
222+ 
223+ // 空tensor 处理
224+ if (matmulUnzipInput.x1->IsEmpty() || matmulUnzipInput.x2->IsEmpty()) {
225+ auto emptyOut = ProcessEmptyTensor(matmulUnzipInput.x1, out, executor);
226+ CHECK_RET(emptyOut != nullptr, nullptr);
227+ return emptyOut;
228+ }
229+ const aclTensor* reformatedX = nullptr;
230+ (void)InputsContiguousAndTransFormat(matmulUnzipInput.x1, reformatedX, "x1", executor);
V
Vvoid_ptr5月19日

[Blocker] InputsContiguousAndTransFormat 的返回值被 (void) 丢弃。若 Contiguous/TransData 失败,reformatedX 仍为 nullptr,后续仍会传入 MatMulCompressDequant,存在空指针风险。

建议改为:

CHECK_RET(InputsContiguousAndTransFormat(matmulUnzipInput.x1, reformatedX, "x1", executor) == ACLNN_SUCCESS, nullptr);
CHECK_RET(reformatedX != nullptr, nullptr);
likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
231+ matmulUnzipInput.bias = l0op::Contiguous(matmulUnzipInput.bias, executor);
232+ CHECK_RET(matmulUnzipInput.bias != nullptr, nullptr);
233+ const aclTensor* deqScale5HD = matmulUnzipInput.deqScale;
234+ if (matmulUnzipInput.deqScale->Numel() % DEQUANT_SCALE_ALIGN_SIZE == 0) {
235+ deqScale5HD = TensorReformat(matmulUnzipInput.deqScale, op::Format::FORMAT_NC1HWC0, executor);
236+ } else {
237+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Dequant Scale is invalid Data.");
V
Vvoid_ptr5月19日

[Major]deqScale->Numel() % 16 != 0 时,当前实现打错误日志后走 ProcessEmptyTensor 填零并继续构图,调用方可能拿到全零结果且 GetWorkspaceSize 仍返回成功,与参数非法的预期不符。

建议在 CheckParam 或此处直接返回 ACLNN_ERR_PARAM_INVALID,不要静默填零。

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
238+ return ProcessEmptyTensor(matmulUnzipInput.x1, out, executor);
239+ }
240+ const aclTensor* x2ReFormatFractalZ = TensorReformat(matmulUnzipInput.x2, op::Format::FORMAT_FRACTAL_Z, executor);
241+ const aclTensor* matmulOut = l0op::MatMulCompressDequant(
242+ reformatedX, x2ReFormatFractalZ, matmulUnzipInput.compressIndex, deqScale5HD, matmulUnzipInput.bias, nullptr,
243+ false, false, compressInfo, offsetX, GetAlgStr(UnzipMode::WEIGHT_UNZIP), executor);
244+ CHECK_RET(matmulOut != nullptr, nullptr);
245+ // TransData out format from NZ to ND
246+ auto matmulOutND = l0op::TransData(matmulOut, op::Format::FORMAT_ND, 1, executor);
247+ CHECK_RET(matmulOutND != nullptr, nullptr);
248+ 
249+ return matmulOutND;
250+}
251+ 
252+aclnnStatus aclnnMatmulCompressDequantGetWorkspaceSize(const aclTensor* x1, const aclTensor* x2,
253+ const aclTensor* compressIndex, const aclTensor* bias,
254+ const aclTensor* deqScale, const aclTensor* offsetW,
255+ int offsetX, const aclIntArray* compressInfo, aclTensor* out,
256+ uint64_t* workspaceSize, aclOpExecutor** executor)
257+{
258+ L2_DFX_PHASE_1(
259+ aclnnMatmulCompressDequant, DFX_IN(x1, x2, compressIndex, bias, deqScale, offsetX, compressInfo), DFX_OUT(out));
260+ // 固定写法,创建OpExecutor
261+ auto uniqueExecutor = CREATE_EXECUTOR();
262+ CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
263+ // 入参初始化
264+ MatmulUnzipInput matmulUnzipInput;
265+ matmulUnzipInput.x1 = x1;
266+ matmulUnzipInput.x2 = x2;
267+ matmulUnzipInput.compressIndex = compressIndex;
268+ matmulUnzipInput.bias = bias;
269+ matmulUnzipInput.deqScale = deqScale;
270+ matmulUnzipInput.offsetW = offsetW;
271+ 
272+ // 入参检查
273+ auto ret = CheckParam(matmulUnzipInput, compressInfo, out);
274+ CHECK_RET(ret == ACLNN_SUCCESS, ret);
275+ 
276+ // 构建matmul_unzip计算图
277+ auto matmulOut = BuildMatMulUnzipGraph(matmulUnzipInput, offsetX, compressInfo, out, uniqueExecutor.get());
278+ CHECK_RET(matmulOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
279+ if (matmulOut->IsEmpty()) {
280+ // 当输出为空tensor的场景,空tensor处理
281+ *workspaceSize = 0;
282+ uniqueExecutor.ReleaseTo(executor);
283+ return ACLNN_SUCCESS;
284+ }
285+ 
286+ auto viewCopyResult = l0op::ViewCopy(matmulOut, out, uniqueExecutor.get());
287+ CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
288+ 
289+ // 获取workspace
290+ *workspaceSize = uniqueExecutor->GetWorkspaceSize();
291+ uniqueExecutor.ReleaseTo(executor);
292+ return ACLNN_SUCCESS;
293+}
294+ 
295+aclnnStatus aclnnMatmulCompressDequant(
296+ void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream)
297+{
298+ L2_DFX_PHASE_2(aclnnMatmulCompressDequant);
299+ // 固定写法,调用框架能力,完成计算
300+ return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
301+}
302+ 
303+#ifdef __cplusplus
304+}
305+#endif
@@ -0,0 +1,41 @@
1+/**
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
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+#ifndef OP_API_INC_MM_UNZIP_H_
11+#define OP_API_INC_MM_UNZIP_H_
12+ 
13+#include "aclnn/aclnn_base.h"
14+#include "aclnn_util.h"
15+ 
16+#ifdef __cplusplus
17+extern "C" {
18+#endif
19+ 
20+/**
21+ * @brief aclnnMatmulCompressDequant的第一段接口,根据具体的计算流程,计算workspace大小。
22+ * @domain aclnn_ops_infer
23+ */
24+ACLNN_API aclnnStatus aclnnMatmulCompressDequantGetWorkspaceSize(const aclTensor* x1, const aclTensor* x2,
25+ const aclTensor* compressIndex, const aclTensor* bias,
26+ const aclTensor* deqScale, const aclTensor* offsetW,
27+ int offsetX, const aclIntArray* compressInfo,
28+ aclTensor* out, uint64_t* workspaceSize,
29+ aclOpExecutor** executor);
30+ 
31+/**
32+ * @brief aclnnMatmulCompressDequant的第二段接口,用于执行计算。
33+ */
34+ACLNN_API aclnnStatus aclnnMatmulCompressDequant(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
35+ aclrtStream stream);
36+ 
37+#ifdef __cplusplus
38+}
39+#endif
40+ 
41+#endif // OP_API_INC_MM_UNZIP_H_
@@ -0,0 +1,44 @@
1+/**
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
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+#include "matmul_compress_dequant.h"
12+#include "aclnn_kernels/common/op_error_check.h"
13+#include "opdev/make_op_executor.h"
14+#include "opdev/op_def.h"
15+#include "opdev/op_dfx.h"
16+#include "opdev/op_executor.h"
17+#include "opdev/op_log.h"
18+ 
19+using namespace op;
20+ 
21+namespace l0op {
22+ 
23+OP_TYPE_REGISTER(MatMulV2CompressDequant);
24+// 用大小写区分是否可以区分两个不同的kernel
25+const aclTensor *MatMulCompressDequant(const aclTensor *x1, const aclTensor *x2, const aclTensor *compressIndex,
26+ const aclTensor *deqScale, const aclTensor *bias, const aclTensor *offsetW,
27+ const bool transposeX1, const bool transposeX2, const aclIntArray *compressInfo,
28+ const int offsetX, const std::string &algStr, aclOpExecutor *executor) {
29+ L0_DFX(MatMulCompressDequant, x1, x2, compressIndex, deqScale, bias, offsetW, transposeX1, transposeX2,
30+ compressInfo, offsetX, algStr);
31+ auto mmCompressDequantOut = executor->AllocTensor(DataType::DT_FLOAT16, Format::FORMAT_FRACTAL_NZ, Format::FORMAT_ND);
32+ // 是否可以复用tbe的infershape
33+ auto ret = INFER_SHAPE(MatMulV2CompressDequant, OP_INPUT(x1, x2, compressIndex, deqScale, bias, offsetW),
34+ OP_OUTPUT(mmCompressDequantOut), OP_ATTR(transposeX1, transposeX2, compressInfo, offsetX, algStr));
35+ OP_CHECK_INFERSHAPE(ret != ACLNN_SUCCESS, return nullptr, "MatMulCompressDequant InferShape failed.");
36+ // 使用新的MatmulV2CompressDequant内核
37+ ret = ADD_TO_LAUNCHER_LIST_AICORE(MatMulV2CompressDequant, OP_INPUT(x1, x2, compressIndex, deqScale, bias, offsetW),
38+ OP_OUTPUT(mmCompressDequantOut),
39+ OP_ATTR(transposeX1, transposeX2, compressInfo, offsetX, algStr));
40+ OP_CHECK_ADD_TO_LAUNCHER_LIST_AICORE(ret != ACLNN_SUCCESS, return nullptr,
41+ "MatMulCompressDequant ADD_TO_LAUNCHER_LIST_AICORE failed.");
42+ return mmCompressDequantOut;
43+};
44+} // namespace l0op
@@ -0,0 +1,25 @@
1+/**
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
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+#ifndef PTA_NPU_OP_API_INC_LEVEL0_OP_MATMULV2_COMPRESS_DEQUANT_OP_H_
11+#define PTA_NPU_OP_API_INC_LEVEL0_OP_MATMULV2_COMPRESS_DEQUANT_OP_H_
12+ 
13+#include "opdev/op_executor.h"
14+ 
15+namespace l0op {
16+ 
17+const aclTensor *MatMulCompressDequant(const aclTensor *x1, const aclTensor *x2, const aclTensor *compressIndex,
18+ const aclTensor *deqScale, const aclTensor *bias, const aclTensor *offsetW,
19+ const bool transposeX1, const bool transposeX2, const aclIntArray *compressInfo,
20+ const int offsetX, const std::string &algStr, aclOpExecutor *executor);
21+ 
22+} // namespace l0op
23+ 
24+#endif // PTA_NPU_OP_API_INC_LEVEL0_OP_MATMULV2_COMPRESS_DEQUANT_OP_H_
25+ 
@@ -0,0 +1,254 @@
1+/**
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
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+ 
L
Lliubo755月20日

这些文件命名,有些前面加pp,有些没有,这些要和算子名称对应

likedislike
wmg1
wmg1
5月20日 评论:
11+/*!
12+ * \file pp_matmul_common_tiling.h
13+ * \brief
14+ */
15+ 
16+#ifndef __OP_HOST_PPMAT_MUL_COMMMON_TILING_H__
17+#define __OP_HOST_PPMAT_MUL_COMMMON_TILING_H__
18+ 
19+ 
20+#include <cmath>
21+#include "pp_matmul_info.h"
22+#include "tiling/platform/platform_ascendc.h"
23+ 
24+namespace optiling {
25+namespace pp_matmul {
26+namespace matmulCompressDequant {
27+ 
28+constexpr uint64_t FP16_SIZE = 2;
29+constexpr uint64_t FP32_SIZE = 4;
30+constexpr uint64_t BLOCK_SIZE = 16;
31+constexpr uint64_t BLOCK_SIZE_INT8_K = 32;
32+constexpr uint64_t BASE_BLOCK_STEP = 2;
33+constexpr uint64_t AXES_ALIGN_SIZE = 512;
34+constexpr uint64_t AXES_ALIGN_SIZE_INT8 = 256;
35+constexpr uint64_t ND_SHAPE_SIZE = 2;
36+constexpr uint64_t NZ_SHAPE_SIZE = 4;
37+constexpr uint64_t CUBE_BLOCK_SIZE = 256;
38+constexpr uint64_t CUBE_BLOCK_SIZE_INT8 = 512;
39+constexpr uint64_t L1AB_PINGPONG_BUFFER_SIZE = 262144;
40+constexpr uint64_t L0AB_PINGPONG_BUFFER_SIZE_INT8 = 262144; // 131072 * 2 = 256 KB
41+constexpr uint64_t L0AB_PINGPONG_BUFFER_SIZE_FP16 = 131072; // 128 KB
42+constexpr uint64_t L1AB_PINGPONG_BUFFER_SIZE_INT8_SPARSE = 163840; // 160 * 1024
43+constexpr uint64_t UB_LIMIT_SIZE_910A = 131072; // 128 * 1024
44+ 
45+template <uint64_t DIV>
46+inline uint64_t CeilDiv(uint64_t num)
47+{
48+ if (DIV == 0UL || num + DIV - 1UL < num) {
49+ return num;
50+ }
51+ return (num + DIV - 1UL) / DIV;
52+}
53+ 
54+inline uint64_t CeilDiv(uint64_t dividend, uint64_t divisor)
55+{
56+ if (divisor == 0UL || dividend + divisor - 1UL < dividend) {
57+ return dividend;
58+ }
59+ return (dividend + divisor - 1UL) / divisor;
60+}
61+ 
62+template <uint64_t RND>
63+inline uint64_t Round(uint64_t num)
64+{
65+ if (RND == 0UL || num + RND - 1UL < num) {
66+ return num;
67+ }
68+ return (num + RND - 1UL) / RND * RND;
69+}
70+ 
71+inline uint64_t RoundUp(uint64_t num, uint64_t rnd)
72+{
73+ if (rnd == 0UL || num + rnd - 1UL < num) {
74+ return num;
75+ }
76+ return (num + rnd - 1UL) / rnd * rnd;
77+}
78+ 
79+inline int64_t RoundUp(int64_t num, int64_t rnd)
80+{
81+ if (rnd == 0UL || static_cast<int64_t>(num + rnd - 1) < num) {
82+ return num;
83+ }
84+ return static_cast<int64_t>((num + rnd - 1) / rnd * rnd);
85+}
86+ 
87+inline uint64_t RoundDown(uint64_t num, uint64_t rnd)
88+{
89+ if (rnd == 0UL) {
90+ return 0UL;
91+ }
92+ return num / rnd * rnd;
93+}
94+ 
95+template <typename T1, typename T2>
96+T2 CalcTailSize(T1 num1, T2 num2)
97+{
98+ if (num2 == 0) {
99+ return 0;
100+ }
101+ T1 mod = num1 % static_cast<T1>(num2);
102+ return mod;
103+}
104+ 
105+inline uint64_t GetN0TilingLimit(bool compressFlag, uint64_t tilingN, const platform_ascendc::SocVersion &platformType)
106+{
107+ if (compressFlag) {
108+ return std::min(tilingN * BLOCK_SIZE, AXES_ALIGN_SIZE_INT8);
109+ } else {
110+ return (platformType == platform_ascendc::SocVersion::ASCEND310P
111+ || platformType == platform_ascendc::SocVersion::ASCEND910) ? AXES_ALIGN_SIZE : AXES_ALIGN_SIZE_INT8;
112+ }
113+}
114+ 
115+template <typename OpShareType>
116+inline uint64_t GetN0TilingInit(const OpShareType &opShape, bool compressFlag, uint64_t tilingN)
117+{
118+ const uint64_t RND = 16UL;
119+ if (compressFlag) {
120+ if (tilingN * BLOCK_SIZE > opShape.n) {
121+ return Round<RND>(opShape.n);
122+ } else {
123+ return tilingN * BLOCK_SIZE;
124+ }
125+ } else {
126+ return BLOCK_SIZE;
127+ }
128+}
129+ 
130+template <bool PRI_FLAG>
131+inline bool IsExceedTilingLimit(uint64_t axes0, uint64_t priAxes0,
132+ uint64_t n0TilingLimit, platform_ascendc::SocVersion platformType,
133+ uint64_t basicBlockSize)
134+{
135+ return (PRI_FLAG && axes0 > n0TilingLimit) || (!PRI_FLAG && priAxes0 > n0TilingLimit) ||
136+ (platformType == platform_ascendc::SocVersion::ASCEND910 && basicBlockSize > UB_LIMIT_SIZE_910A);
137+}
138+ 
139+template <bool PRI_FLAG, typename OpShareType>
140+inline void SetOpShapeAxesInfo(OpShareType &opShape, uint64_t priAxes0, uint64_t axes0)
141+{
142+ opShape.m0 = PRI_FLAG ? priAxes0 : axes0;
143+ opShape.n0 = PRI_FLAG ? axes0 : priAxes0;
144+}
145+ 
146+template <typename HardwareType, typename OpShapeType, typename MatMulInfoType>
147+inline float CostFunc(const HardwareType &hwInfor, OpShapeType &shape, const MatMulInfoType &mmInfo)
148+{
149+ float aCoef = 1;
150+ float bCoef = 1;
151+ float bwCoef = static_cast<float>(hwInfor.l2BandWidth) / static_cast<float>(hwInfor.hbmBandWidth);
152+ uint64_t mLoop = CeilDiv(shape.m, shape.m0);
153+ uint64_t nLoop = CeilDiv(shape.n, shape.n0);
154+ if (mLoop == 0UL || nLoop == 0UL) {
155+ return 1;
156+ }
157+ uint64_t coreNeed = shape.batchSize * mLoop * nLoop;
158+ uint64_t blockDim = std::min(coreNeed, hwInfor.coreNum);
159+ uint64_t mOnce = blockDim < nLoop ? shape.m0 : blockDim / nLoop * shape.m0;
160+ uint64_t nOnce = blockDim < nLoop ? hwInfor.coreNum * shape.n0 : shape.n;
161+ (void)mmInfo;
162+ if (mOnce * shape.k * 2 > hwInfor.l2Size) {
163+ aCoef = bwCoef;
164+ }
165+ if (nOnce * shape.k * 2 > hwInfor.l2Size) {
166+ bCoef = bwCoef;
167+ }
168+ return 1 / (aCoef * static_cast<float>(shape.n0)) + 1 / (bCoef * static_cast<float>(shape.m0));
169+}
170+ 
171+// OpShareType is OpShape, TilingType is PpTilingData, HardwareType is HardwareType, MatMulInfoType is MatMulInfo
172+template <bool PRI_FLAG, typename OpShareType, typename TilingType, typename HardwareType, typename MatMulInfoType>
173+void TilingFunc(OpShareType &opShape, TilingType &tilingParam, const HardwareType &hwInfor,
174+ const MatMulInfoType &mmInfo, bool compressFlag = false, const uint64_t tilingN = 1)
175+{
176+ float costMin = 1;
177+ const float CONST_2 = 2.0;
178+ const uint64_t CONST_16 = 16UL;
179+ uint64_t roundBase =
180+ static_cast<uint64_t>(pow(2, ceil(log(CeilDiv(PRI_FLAG ? opShape.n : opShape.m, CONST_16)))) * CONST_16);
181+ uint64_t priAxes = RoundUp(PRI_FLAG ? opShape.m : opShape.n, CONST_16);
182+ uint64_t axes = RoundUp(PRI_FLAG ? opShape.n : opShape.m, roundBase);
183+ float axes0Max = static_cast<float>(AXES_ALIGN_SIZE) / mmInfo.inDtype;
184+ auto platformType = hwInfor.socVersion;
185+ if (mmInfo.isInt8 && (platformType == platform_ascendc::SocVersion::ASCEND310P ||
186+ platformType == platform_ascendc::SocVersion::ASCEND910)) {
187+ axes0Max /= CONST_2;
188+ }
189+ uint64_t n0TilingInit = GetN0TilingInit(opShape, compressFlag, tilingN);
190+ uint64_t n0TilingLimit = GetN0TilingLimit(compressFlag, tilingN, platformType);
191+ uint64_t priAxes0Init = PRI_FLAG ? BLOCK_SIZE : n0TilingInit;
192+ uint64_t axes0Init = PRI_FLAG ? n0TilingInit : BLOCK_SIZE;
193+ bool isAscend310P = platformType == platform_ascendc::SocVersion::ASCEND310P;
194+ for (uint64_t priAxes0 = priAxes0Init; priAxes0 <= priAxes && priAxes0 <= axes0Max; priAxes0 *= BASE_BLOCK_STEP) {
195+ for (uint64_t axes0 = axes0Init; axes0 <= axes && axes0 <= axes0Max; axes0 *= BASE_BLOCK_STEP) {
196+ uint64_t basicBlockSize = priAxes0 * axes0 * FP32_SIZE;
197+ if (basicBlockSize > hwInfor.l0cSize) {
198+ continue;
199+ }
200+ if (mmInfo.isInt8 &&
201+ IsExceedTilingLimit<PRI_FLAG>(axes0, priAxes0, n0TilingLimit, platformType, basicBlockSize)) {
202+ continue;
203+ }
204+ SetOpShapeAxesInfo<PRI_FLAG>(opShape, priAxes0, axes0);
205+ float cost = CostFunc<HardwareType, OpShareType, MatMulInfoType>(hwInfor, opShape, mmInfo);
206+ if (cost >= costMin) {
207+ continue;
208+ }
209+ costMin = cost;
210+ tilingParam.SetBaseOp(hwInfor.coreNum, hwInfor.l0cSize, opShape.m0, opShape.n0, mmInfo, isAscend310P);
211+ }
212+ }
213+}
214+ 
215+template <typename PpTilingDataType>
216+uint64_t Swizzl(PpTilingDataType &tilingData)
217+{
218+ uint64_t swizzlDirect = 0UL;
219+ uint64_t swizzlCount = 1UL;
220+ float m0 = tilingData.opShape.m0;
221+ float n0 = tilingData.opShape.n0;
222+ float m = tilingData.opShape.m;
223+ float k = tilingData.opShape.k;
224+ float n = tilingData.opShape.n;
225+ float mincost = m * k + k * n;
226+ 
227+ for (uint32_t i = 1; i <= tilingData.blockDim; ++i) {
228+ int c = static_cast<int32_t>((tilingData.blockDim + i - 1) / i);
229+ float cost;
230+ // B0 + A < A0 + B
231+ if (i * n0 + m < m0 * c + n) {
232+ swizzlDirect = 1UL; // Nz
233+ cost = n0 * i + m0 * c;
234+ if (cost <= mincost) {
235+ mincost = cost;
236+ swizzlCount = i;
237+ }
238+ } else {
239+ swizzlDirect = 0UL; // Zn
240+ cost = m0 * i + n0 * c;
241+ if (cost < mincost) {
242+ mincost = cost;
243+ swizzlCount = i;
244+ }
245+ }
246+ }
247+ tilingData.swizzlDirect = swizzlDirect;
248+ tilingData.swizzlCount = swizzlCount;
249+ return swizzlDirect;
250+}
251+} // namespace matmulCompressDequant
252+} // namespace pp_matmul
253+} // namespace optiling
254+#endif
@@ -0,0 +1,193 @@
1+/**
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
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,
L
Lliubo755月20日

这个文件的命名也是,所有文件都统一看看,要从文件名就知道是干啥的。

likedislike
wmg1
wmg1
5月20日 评论:
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 pp_matmul_default.h
13+ * \brief
14+ */
15+#ifndef __OP_HOST_PP_MATMUL_DEFAULT_H__
16+#define __OP_HOST_PP_MATMUL_DEFAULT_H__
17+ 
18+#include "register/op_def_registry.h"
19+#include "pp_matmul_info.h"
20+#include "pp_matmul_default.h"
21+#include "pp_matmul_common_tiling.h"
22+#include "op_host/tiling_templates_registry.h"
23+#include "register/op_def_registry.h"
24+#include "platform/platform_infos_def.h"
25+#include "error_util.h"
26+ 
27+namespace {
28+constexpr uint64_t L1_DESCALE_BUFFER_SIZE_MAX = 6144;
29+constexpr uint64_t CONST_3 = 3;
30+constexpr uint64_t CONST_4 = 4;
31+constexpr uint64_t CONST_16 = 16;
32+constexpr uint64_t CONST_32 = 32;
33+constexpr uint64_t CONST_256 = 256;
34+constexpr uint64_t CONST_512 = 512;
35+ 
36+constexpr size_t DIM_2 = 2;
37+constexpr size_t DIM_3 = 3;
38+constexpr size_t DIM_4 = 4;
39+constexpr size_t COMPUTE_TYPE_IDX_CANN = 3;
40+constexpr size_t COMPUTE_TYPE_IDX_ATB = 10;
41+constexpr size_t EINSUM_MODE = 4;
42+ 
43+constexpr uint32_t DTYPE_BIT_COUNT = 2;
44+constexpr uint32_t FORMAT_BIT_COUNT = 1;
45+constexpr uint32_t COMPUTE_TYPE_BIT_COUNT = 3;
46+constexpr uint32_t MAX_ATTRS_NUM = 4;
47+constexpr uint32_t EN_SHUFFFLE_IDX_ATB = 7;
48+}
49+ 
50+namespace optiling {
51+namespace pp_matmul {
52+namespace matmulCompressDequant {
53+ 
54+class PpMatMulDefault
55+{
56+public:
57+ explicit PpMatMulDefault(gert::TilingContext* context) : context_(context) {}
58+ virtual ~PpMatMulDefault() = default;
59+ 
60+ void GetHardwareInfo();
61+ bool GetMatMulTilingData();
62+ void PrintTiling();
63+ gert::TilingContext *context_ = nullptr;
64+ MatMulInfo matMulInfo_;
65+ PpMatmulDefaultTilingData ppMatmulDefaultTilingData_{};
66+ HardwareInfo hardwareInfo_;
67+ uint64_t kernelKey_;
68+};
69+ 
70+ 
71+void PpMatmulDefaultTilingData::SetBaseShape(uint64_t batchSize, uint64_t m, uint64_t k, uint64_t n)
72+{
73+ opShape.batchSize = batchSize;
74+ opShape.m = m;
75+ opShape.k = k;
76+ opShape.n = n;
77+}
78+ 
79+void PpMatmulDefaultTilingData::SetBaseOp(uint64_t coreNum, uint64_t l0cSize, uint64_t mBase, uint64_t nBase,
80+ const MatMulInfo &mmInfo, bool isAscend310P)
81+{
82+ opShape.m0 = mBase;
83+ opShape.n0 = nBase;
84+ mLoop = CeilDiv(opShape.m, opShape.m0);
85+ nLoop = CeilDiv(opShape.n, opShape.n0);
86+ coreLoop = opShape.batchSize * mLoop * nLoop;
87+ if (!isAscend310P && mLoop == 1UL && mmInfo.transB && static_cast<uint64_t>(CalcTailSize(coreLoop,coreNum)) <
88+ static_cast<uint64_t>(coreNum / CONST_4) * CONST_3) {
89+ mBase = RoundUp(opShape.m, CONST_16);
90+ opShape.m0 = mBase;
91+ uint64_t maxN0 = l0cSize / (mBase * sizeof(float));
92+ uint64_t x = CeilDiv(opShape.n, coreNum);
93+ uint64_t y = CeilDiv(x, maxN0);
94+ nBase = RoundUp(CeilDiv(x, y), CONST_16);
95+ uint64_t rqdL0CSize = mBase * nBase * sizeof(float);
96+ if (rqdL0CSize < l0cSize &&
97+ (mBase + nBase) * CONST_256 * sizeof(uint16_t) < L1AB_PINGPONG_BUFFER_SIZE) {
98+ opShape.n0 = nBase;
99+ nLoop = CeilDiv(opShape.n, opShape.n0);
100+ coreLoop = opShape.batchSize * nLoop;
101+ }
102+ }
103+ blockDim = std::min(coreLoop, coreNum);
104+}
105+ 
106+void PpMatmulDefaultTilingData::End(const MatMulInfo &mmInfo, bool isAscend310P)
107+{
108+ uint64_t shapeSum = opShape.m0 + opShape.n0;
109+ if (!isAscend310P) {
110+ uint64_t k0Max = shapeSum == 0UL
111+ ? L1AB_PINGPONG_BUFFER_SIZE
112+ : static_cast<uint64_t>(static_cast<float>(L1AB_PINGPONG_BUFFER_SIZE)
113+ / (shapeSum * mmInfo.inDtype));
114+ opShape.k0 = k0Max < CUBE_BLOCK_SIZE ? RoundDown(k0Max, BLOCK_SIZE) : RoundDown(k0Max, CUBE_BLOCK_SIZE);
115+ if (opShape.k0 > CONST_512) {
116+ opShape.k0 = RoundDown(opShape.k0, CONST_512);
117+ }
118+ } else {
119+ uint32_t k0Max = (shapeSum == 0UL) ? UB_LIMIT_SIZE_910A : (UB_LIMIT_SIZE_910A / shapeSum);
120+ opShape.k0 = k0Max < CUBE_BLOCK_SIZE ? k0Max / BLOCK_SIZE * BLOCK_SIZE : \
121+ k0Max / CUBE_BLOCK_SIZE * CUBE_BLOCK_SIZE; // k0Max less than 256, matrix 16
122+ }
123+ // 删除
124+ opShape.k0 = 512;
125+ kLoop = CeilDiv(opShape.k, opShape.k0);
126+}
127+ 
128+ 
129+void PpMatMulDefault::GetHardwareInfo()
130+{
131+ auto platformInfo = context_->GetPlatformInfo();
132+ if (platformInfo == nullptr) {
133+ OP_LOGE("[PpMatMul]", "platformInfo is nullptr");
134+ return;
135+ }
136+ HardwareInfo hardwareInfo;
137+ 
138+ auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo);
139+ platformInfo->GetPlatformRes("version", "SoC_version", hardwareInfo.socVersionStr);
140+ 
141+ hardwareInfo.coreNum = static_cast<uint64_t>(ascendcPlatform.GetCoreNumAic());
142+ hardwareInfo.socVersion = ascendcPlatform.GetSocVersion();
143+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L2, hardwareInfo.l2Size);
144+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L1, hardwareInfo.l1Size);
145+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_A, hardwareInfo.l0aSize);
146+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_B, hardwareInfo.l0bSize);
147+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_C, hardwareInfo.l0cSize);
148+ hardwareInfo_ = hardwareInfo;
149+}
150+ 
151+ 
152+bool PpMatMulDefault::GetMatMulTilingData()
153+{
154+ ppMatmulDefaultTilingData_.SetBaseShape(matMulInfo_.batchSize, matMulInfo_.m, matMulInfo_.k, matMulInfo_.n);
155+ OpShape opShape = ppMatmulDefaultTilingData_.opShape;
156+ if (opShape.m < opShape.n) {
157+ TilingFunc<false, OpShape, PpMatmulDefaultTilingData, HardwareInfo, MatMulInfo>(opShape,
158+ ppMatmulDefaultTilingData_, hardwareInfo_, matMulInfo_, true, 8);
159+ } else {
160+ TilingFunc<true, OpShape, PpMatmulDefaultTilingData, HardwareInfo, MatMulInfo>(opShape,
161+ ppMatmulDefaultTilingData_, hardwareInfo_, matMulInfo_, true, 8);
162+ }
163+ Swizzl<PpMatmulDefaultTilingData>(ppMatmulDefaultTilingData_);
164+ ppMatmulDefaultTilingData_.End(matMulInfo_, hardwareInfo_.socVersion == platform_ascendc::SocVersion::ASCEND310P);
165+ return true;
166+}
167+ 
168+ 
169+void PpMatMulDefault::PrintTiling()
170+{
171+ OP_LOGD(context_->GetNodeName(), "PpMatMul batchSize: %ld.", ppMatmulDefaultTilingData_.opShape.batchSize);
172+ OP_LOGD(context_->GetNodeName(), "PpMatMul m: %ld.", ppMatmulDefaultTilingData_.opShape.m);
173+ OP_LOGD(context_->GetNodeName(), "PpMatMul k: %ld.", ppMatmulDefaultTilingData_.opShape.k);
174+ OP_LOGD(context_->GetNodeName(), "PpMatMul n: %ld.", ppMatmulDefaultTilingData_.opShape.n);
175+ OP_LOGD(context_->GetNodeName(), "PpMatMul m0: %ld.", ppMatmulDefaultTilingData_.opShape.m0);
176+ OP_LOGD(context_->GetNodeName(), "PpMatMul k0: %ld.", ppMatmulDefaultTilingData_.opShape.k0);
177+ OP_LOGD(context_->GetNodeName(), "PpMatMul n0: %ld.", ppMatmulDefaultTilingData_.opShape.n0);
178+ OP_LOGD(context_->GetNodeName(), "PpMatMul mLoop: %ld.", ppMatmulDefaultTilingData_.mLoop);
179+ OP_LOGD(context_->GetNodeName(), "PpMatMul kLoop: %ld.", ppMatmulDefaultTilingData_.kLoop);
180+ OP_LOGD(context_->GetNodeName(), "PpMatMul nLoop: %ld.", ppMatmulDefaultTilingData_.nLoop);
181+ OP_LOGD(context_->GetNodeName(), "PpMatMul coreLoop: %ld.", ppMatmulDefaultTilingData_.coreLoop);
182+ OP_LOGD(context_->GetNodeName(), "PpMatMul swizzlCount: %ld.", ppMatmulDefaultTilingData_.swizzlCount);
183+ OP_LOGD(context_->GetNodeName(), "PpMatMul tilingKey: %d.", ppMatmulDefaultTilingData_.tilingKey);
184+ OP_LOGD(context_->GetNodeName(), "PpMatMul blockDim: %ld.", ppMatmulDefaultTilingData_.blockDim);
185+ OP_LOGD(context_->GetNodeName(), "PpMatMul swizzlDirect: %ld.", ppMatmulDefaultTilingData_.swizzlDirect);
186+ OP_LOGD(context_->GetNodeName(), "PpMatMul splitk: %ld.", ppMatmulDefaultTilingData_.splitk);
187+ OP_LOGD(context_->GetNodeName(), "PpMatMul enShuffleK: %ld.", ppMatmulDefaultTilingData_.enShuffleK);
188+}
189+ 
190+}
191+}
192+}
193+#endif
@@ -0,0 +1,90 @@
1+/**
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
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 pp_matmul_info.h
13+ * \brief
14+ */
15+#ifndef __OP_HOST_PP_MATMUL_INFO_H__
16+#define __OP_HOST_PP_MATMUL_INFO_H__
17+ 
18+#include <array>
19+#include <iostream>
20+#include <map>
21+#include "tiling/platform/platform_ascendc.h"
22+#include "op_host/tiling_base.h"
23+ 
24+namespace optiling {
25+namespace pp_matmul {
26+namespace matmulCompressDequant {
27+struct MatMulInfo {
28+ uint64_t batchSize{0};
29+ uint64_t m{0}; // 实际输入的 m
30+ uint64_t n{0}; // 实际输入的 n
31+ uint64_t k{0}; // 实际输入的 k
32+ ge::DataType dtypeA = ge::DT_FLOAT16;
33+ ge::DataType dtypeB = ge::DT_FLOAT16;
34+ ge::DataType dtypeC = ge::DT_FLOAT16;
35+ ge::Format formatA = ge::FORMAT_ND;
36+ ge::Format formatB = ge::FORMAT_ND;
37+ ge::Format formatC = ge::FORMAT_ND;
38+ uint64_t transA{0};
39+ uint64_t transB{0};
40+ bool biasFlag{0}; // false: 0, true: 1
41+ bool isInt8{0}; // 是否shi int8融合
42+ float inDtype{0};
43+ float outDtype{0};
44+};
45+ 
46+struct HardwareInfo {
47+ uint64_t coreNum{0};
48+ uint64_t l2Size{0};
49+ uint64_t l1Size{0};
50+ uint64_t l0aSize{0};
51+ uint64_t l0bSize{0};
52+ uint64_t l0cSize{0};
53+ uint64_t hbmBandWidth{1};
54+ uint64_t l2BandWidth{5}; // 5x faster than hbm.
55+ platform_ascendc::SocVersion socVersion = platform_ascendc::SocVersion::ASCEND910B;
56+ std::string socVersionStr = "";
57+};
58+ 
59+struct OpShape {
60+ uint64_t batchSize{0};
61+ uint64_t m{0};
62+ uint64_t k{0};
63+ uint64_t n{0};
64+ uint64_t m0{0};
65+ uint64_t k0{0};
66+ uint64_t n0{0};
67+};
68+ 
69+struct PpMatmulDefaultTilingData {
70+ OpShape opShape{};
71+ uint64_t mLoop{1};
72+ uint64_t kLoop{1};
73+ uint64_t nLoop{1};
74+ uint64_t coreLoop{1};
75+ uint64_t swizzlCount{1};
76+ uint32_t tilingKey{0};
77+ uint64_t blockDim{1};
78+ uint64_t swizzlDirect{0};
79+ uint64_t splitk{0};
80+ uint64_t enShuffleK{0};
81+ 
82+ void SetBaseShape(uint64_t batchSize, uint64_t m, uint64_t k, uint64_t n);
83+ void SetBaseOp(uint64_t coreNum, uint64_t l0cSize, uint64_t mBase, uint64_t nBase,
84+ const MatMulInfo &mmInfo, bool isAscend310P);
85+ void End(const MatMulInfo &mmInfo, bool isAscend310P);
86+};
87+} // namespace matmulCompressDequant
88+} // namespace pp_matmul
89+} // namespace optiling
90+#endif
@@ -0,0 +1,23 @@
1+/*
V
Vvoid_ptr5月19日

[Blocker] 重复代码,TBMM中已有相关实现,应直接复用,下同。

likedislike
wmg1
wmg1
5月19日 评论:
wmg1
wmg1
5月19日 评论:
2+ * Copyright (c) 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+#ifndef INCLUDE_COMMON_H
11+#define INCLUDE_COMMON_H
12+ 
13+#define CONST_2 2
14+ 
15+#define SET_FLAG(trigger, waiter, e) AscendC::SetFlag<AscendC::HardEvent::trigger##_##waiter>((e))
16+#define WAIT_FLAG(trigger, waiter, e) AscendC::WaitFlag<AscendC::HardEvent::trigger##_##waiter>((e))
17+#define PIPE_BARRIER(pipe) AscendC::PipeBarrier<PIPE_##pipe>()
18+ 
19+#ifndef __force_inline__
20+#define __force_inline__ inline __attribute__((always_inline))
21+#endif
22+ 
23+#endif
@@ -0,0 +1,112 @@
1+/*
2+ * Copyright (c) 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+#ifndef INCLUDE_COMMON_FUNC_H
12+#define INCLUDE_COMMON_FUNC_H
13+ 
14+#include <limits>
15+#include <type_traits>
16+ 
17+#ifdef __CCE_KT_TEST__
18+#include "stub_def.h"
19+#include "stub_fun.h"
20+#else
21+#include "kernel_macros.h"
22+#endif
23+ 
24+template <uint32_t ALIGN, typename T = uint32_t>
25+inline __aicore__ T RoundUp(const T val)
26+{
27+ static_assert(ALIGN != 0, "align must not be zero");
28+ static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
29+ T align = ALIGN;
30+ if (val + align - 1 < val) {
31+ return val;
32+ }
33+ return (val + align - 1) / align * align;
34+}
35+ 
36+template <typename T>
37+inline __aicore__ T RoundUp(const T val, const T align)
38+{
39+ static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
40+ if (align == 0 || val + align - 1 < val) {
41+ return val;
42+ }
43+ return (val + align - 1) / align * align;
44+}
45+ 
46+template <uint32_t DIVISOR, typename T = uint32_t>
47+inline __aicore__ T CeilDiv(const T dividend)
48+{
49+ static_assert(DIVISOR != 0, "align must not be zero");
50+ static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
51+ T divisor = DIVISOR;
52+ if (dividend + divisor - 1 < dividend) {
53+ return dividend;
54+ }
55+ return (dividend + divisor - 1) / divisor;
56+}
57+ 
58+template <typename T>
59+constexpr T T_MAX = std::numeric_limits<T>::max();
60+ 
61+template <typename T>
62+inline __aicore__ T CeilDiv(const T dividend, const T divisor)
63+{
64+ static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type");
65+ if (divisor == 0 || dividend + divisor - 1 < dividend) {
66+ return T_MAX<T>;
67+ }
68+ return (dividend + divisor - 1) / divisor;
69+}
70+ 
71+template <typename T>
72+__aicore__ inline T Min(const T lhs, const T rhs)
73+{
74+ return lhs < rhs ? lhs : rhs;
75+}
76+ 
77+template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint32_t BlockSize()
78+{
79+ return 32 / sizeof(Dtype);
80+}
81+ 
82+template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint32_t MatrixSize()
83+{
84+ return 512 / sizeof(Dtype);
85+}
86+ 
87+template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t BlockSizeRoundUp(uint64_t num)
88+{
89+ return (num + BlockSize<Dtype>() - 1) / BlockSize<Dtype>() * BlockSize<Dtype>();
90+}
91+ 
92+template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t NumBlocksRoundUp(uint64_t num)
93+{
94+ return (num + BlockSize<Dtype>() - 1) / BlockSize<Dtype>();
95+}
96+ 
97+template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t MatrixSizeRoundUp(uint64_t num)
98+{
99+ return (num + MatrixSize<Dtype>() - 1) / MatrixSize<Dtype>() * MatrixSize<Dtype>();
100+}
101+ 
102+template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t NumMatrixsRoundUp(uint64_t num)
103+{
104+ return (num + MatrixSize<Dtype>() - 1) / MatrixSize<Dtype>();
105+}
106+ 
107+template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t L0HalfSize()
108+{
109+ return 32 * 1024 / sizeof(Dtype);
110+}
111+ 
112+#endif
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (c) 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+#ifndef INCLUDE_HARDWARE_H
11+#define INCLUDE_HARDWARE_H
12+ 
13+enum class ArchType { ASCEND_V220, ASCEND_V200, ASCEND_M200 };
14+ 
15+template <ArchType ArchTag>
16+struct HardwareInfo {
17+ static uint32_t const l2BW = 5;
L
Lliubo755月20日

这种类似的文件,算子内部就不应该保存

likedislike
wmg1
wmg1
5月20日 评论:
18+ static uint32_t const hbmBW = 1;
19+ static uint32_t const supportMix = 0;
20+ static uint32_t const l1Size = 512 * 1024;
21+ static uint32_t const l0ASize = 64 * 1024;
22+ static uint32_t const l0BSize = 64 * 1024;
23+ static uint32_t const l0CSize = 128 * 1024;
24+ static uint32_t const l2Size = 192 * 1024 * 1024;
25+ static uint32_t const biasSize = 1024;
26+ static uint32_t const fixBufSize = 7 * 1024;
27+ static uint32_t const ubSize = 192 * 1024;
28+ static uint32_t const fractalSize = 512;
29+ static uint32_t const l1l0BlockSize = 32;
30+ static uint32_t const btBlockSize = 64;
31+ static uint32_t const fbBlockSize = 128;
32+};
33+ 
34+#endif
@@ -0,0 +1,116 @@
1+/*
2+ * Copyright (c) 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+#ifndef INCLUDE_ITERTOR_H
11+#define INCLUDE_ITERTOR_H
12+ 
13+#include "common_func.h"
14+#include "hardware.h"
15+#include "kernel_operator.h"
16+#include "layout.h"
17+#include "mem.h"
18+ 
19+/////////////////////////////////////////////////////
20+// gm_to_l1
21+/////////////////////////////////////////////////////
22+template <ArchType ArchTag, typename DataType, DataFormat FormatInGM, DataFormat FormatInL1>
23+struct gm_to_l1 {
24+ __aicore__ gm_to_l1(AscendC::LocalTensor<DataType> l1Tensor,
25+ AscendC::GlobalTensor<DataType> gmTensor,
26+ uint32_t nTileActual,
27+ uint32_t nTileCeil,
28+ uint32_t nVal,
29+ uint32_t dTileActual,
30+ uint32_t dTileCeil,
31+ uint32_t dVal) {};
32+};
33+ 
34+/////////////////////////////////////////////////////
35+// l1_to_l0_a
36+/////////////////////////////////////////////////////
37+template <ArchType ArchTag, typename DataType, bool IsTransPose, DataFormat DFmtIn, DataFormat DFmtOut>
38+struct l1_to_l0_a {
39+ __aicore__ l1_to_l0_a(AscendC::LocalTensor<DataType> l0Tensor,
40+ AscendC::LocalTensor<DataType> l1Tensor,
41+ uint32_t mTileCeil,
42+ uint32_t kPartCeil,
43+ uint32_t mSrcStride,
44+ uint32_t kSrcStride,
45+ uint32_t mDstStride,
46+ uint32_t kDstStride) {};
47+};
48+ 
49+/////////////////////////////////////////////////////
50+// l1_to_l0_b
51+/////////////////////////////////////////////////////
52+template <ArchType ArchTag, typename DataType, bool IsTransPose, DataFormat DFmtIn, DataFormat DFmtOut>
53+struct l1_to_l0_b {
54+ __aicore__ l1_to_l0_b(AscendC::LocalTensor<DataType> l0Tensor,
55+ AscendC::LocalTensor<DataType> l1Tensor,
56+ uint32_t nTileCeil,
57+ uint32_t kPartCeil,
58+ uint32_t nSrcStride,
59+ uint32_t kSrcStride,
60+ uint32_t nDstStride,
61+ uint32_t kDstStride) {};
62+};
63+ 
64+/////////////////////////////////////////////////////
65+// l0c_to_gm
66+/////////////////////////////////////////////////////
67+template <ArchType ArchTag, DataFormat OutFormatType, typename OutDataType, typename L0CDataType>
68+struct l0c_to_gm {
69+ __aicore__ l0c_to_gm(AscendC::GlobalTensor<OutDataType> gmTensor,
70+ AscendC::LocalTensor<L0CDataType> l0cTensor,
71+ uint32_t mTileActual,
72+ uint32_t nTileActual,
73+ uint32_t mTileCeil,
74+ uint32_t nActual,
75+ uint8_t unitFlag = 0) {};
76+};
77+ 
78+/////////////////////////////////////////////////////
79+// l0c_to_l1
80+/////////////////////////////////////////////////////
81+template <ArchType ArchTag, DataFormat LayoutOut, typename ElementOut, typename ElementIn>
82+struct l0c_to_l1 {
83+ __aicore__ l0c_to_l1(AscendC::LocalTensor<ElementOut> l1Tensor,
84+ AscendC::LocalTensor<ElementIn> l0cTensor,
85+ AscendC::LocalTensor<uint64_t> deqTensor,
86+ uint32_t mTileActual,
87+ uint32_t nTileActual,
88+ uint32_t mTileCeil,
89+ uint32_t nActual) {};
90+};
91+ 
92+template <ArchType ArchTag, typename DataType>
93+struct l1_to_bt {
94+ __aicore__ l1_to_bt(uint64_t dst,
95+ const AscendC::LocalTensor<DataType> &src,
96+ uint16_t convControl,
97+ uint16_t nBurst,
98+ uint16_t lenBurst,
99+ uint16_t srcGap,
100+ uint16_t dstGap) {};
101+};
102+ 
103+template <ArchType ArchTag, typename DataType>
104+struct l1_to_fb {
105+ __aicore__ l1_to_fb(AscendC::LocalTensor<DataType> &dst,
106+ AscendC::LocalTensor<DataType> &src,
107+ uint16_t burstNum,
108+ uint16_t burstLen,
109+ uint16_t srcGap,
110+ uint16_t dstGap) {};
111+};
112+#include "../../../../transpose_batch_mat_mul/utils/iterators/gm_to_l1_iterator.h"
113+#include "../../../../transpose_batch_mat_mul/utils/iterators/gm_to_ub_iterator.h"
114+#include "../../../../transpose_batch_mat_mul/utils/iterators/l0c_to_ub_iterator.h"
115+#include "../../../../transpose_batch_mat_mul/utils/iterators/l1_to_l0_iterator.h"
116+#endif
@@ -0,0 +1,16 @@
1+/*
2+ * Copyright (c) 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+#ifndef INCLUDE_LAYOUT_H
12+#define INCLUDE_LAYOUT_H
13+ 
14+enum class DataFormat { ND = 0, NZ, ZN, ZZ, NN, VECTOR };
15+ 
16+#endif
@@ -0,0 +1,82 @@
1+/*
2+ * Copyright (c) 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+#ifndef INCLUDE_MEM_H
11+#define INCLUDE_MEM_H
12+ 
13+#include "hardware.h"
14+#include "kernel_event.h"
15+#include "kernel_tensor.h"
16+ 
17+enum class BufferType { ASCEND_UB, ASCEND_CB, ASCEND_L0A, ASCEND_L0B, ASCEND_L0C, ASCEND_MAX };
18+ 
19+template <BufferType BufferType_>
20+__aicore__ constexpr AscendC::TPosition GetPosition()
21+{
22+ if constexpr (BufferType_ == BufferType::ASCEND_UB) {
23+ return AscendC::TPosition::VECIN;
24+ } else if constexpr (BufferType_ == BufferType::ASCEND_CB) {
25+ return AscendC::TPosition::A1;
26+ } else if constexpr (BufferType_ == BufferType::ASCEND_L0A) {
27+ return AscendC::TPosition::A2;
28+ } else if constexpr (BufferType_ == BufferType::ASCEND_L0B) {
29+ return AscendC::TPosition::B2;
30+ } else if constexpr (BufferType_ == BufferType::ASCEND_L0C) {
31+ return AscendC::TPosition::CO1;
32+ }
33+ return AscendC::TPosition::GM;
34+}
35+ 
36+template <ArchType ArchTag>
37+struct AsdopsBuffer {
38+public:
39+ __aicore__ AsdopsBuffer()
40+ {
41+ constexpr uint32_t bufferSize[(uint32_t)BufferType::ASCEND_MAX] = {HardwareInfo<ArchTag>::ubSize,
42+ HardwareInfo<ArchTag>::l1Size,
43+ HardwareInfo<ArchTag>::l0ASize,
44+ HardwareInfo<ArchTag>::l0BSize,
45+ HardwareInfo<ArchTag>::l0CSize};
46+#ifdef __DAV_C220_VEC__
47+ tensor[(uint32_t)BufferType::ASCEND_UB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_UB]);
48+ tensor[(uint32_t)BufferType::ASCEND_UB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::VECIN);
49+#elif defined(__DAV_C220_CUBE__)
50+ tensor[(uint32_t)BufferType::ASCEND_CB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_CB]);
51+ tensor[(uint32_t)BufferType::ASCEND_CB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A1);
52+ tensor[(uint32_t)BufferType::ASCEND_L0A].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0A]);
53+ tensor[(uint32_t)BufferType::ASCEND_L0A].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A2);
54+ tensor[(uint32_t)BufferType::ASCEND_L0B].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0B]);
55+ tensor[(uint32_t)BufferType::ASCEND_L0B].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::B2);
56+ tensor[(uint32_t)BufferType::ASCEND_L0C].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0C]);
57+ tensor[(uint32_t)BufferType::ASCEND_L0C].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::CO1);
58+#else
59+ tensor[(uint32_t)BufferType::ASCEND_UB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_UB]);
60+ tensor[(uint32_t)BufferType::ASCEND_UB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::VECIN);
61+ tensor[(uint32_t)BufferType::ASCEND_CB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_CB]);
62+ tensor[(uint32_t)BufferType::ASCEND_CB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A1);
63+ tensor[(uint32_t)BufferType::ASCEND_L0A].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0A]);
64+ tensor[(uint32_t)BufferType::ASCEND_L0A].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A2);
65+ tensor[(uint32_t)BufferType::ASCEND_L0B].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0B]);
66+ tensor[(uint32_t)BufferType::ASCEND_L0B].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::B2);
67+ tensor[(uint32_t)BufferType::ASCEND_L0C].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0C]);
68+ tensor[(uint32_t)BufferType::ASCEND_L0C].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::CO1);
69+#endif
70+ };
71+ 
72+ template <BufferType BufferType_, typename DstDataType = half>
73+ __aicore__ AscendC::LocalTensor<DstDataType> GetBuffer(const uint32_t offset) const
74+ {
75+ return tensor[(uint32_t)BufferType_][offset].template ReinterpretCast<DstDataType>();
76+ }
77+ 
78+public:
79+ AscendC::LocalTensor<uint8_t> tensor[(uint32_t)BufferType::ASCEND_MAX];
80+};
81+ 
82+#endif
@@ -0,0 +1,87 @@
1+/*
2+ * Copyright (c) 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+#ifndef INCLUDE_MMA_H
11+#define INCLUDE_MMA_H
12+ 
13+#include "hardware.h"
14+#include "kernel_tensor.h"
15+ 
16+template <ArchType ArchTag, typename ElementA, typename ElementB, typename AccDTypeC, bool IsTransposeA>
17+struct mmad {
18+ __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor,
19+ AscendC::LocalTensor<ElementA> l0aTensor,
20+ AscendC::LocalTensor<ElementB> l0bTensor,
21+ uint32_t mTileActual,
22+ uint32_t nTileActual,
23+ uint32_t kPartActual,
24+ bool initC,
25+ uint8_t unitFlag = 0) {};
26+ 
27+ __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor,
28+ AscendC::LocalTensor<ElementA> l0aTensor,
29+ AscendC::LocalTensor<ElementB> l0bTensor,
30+ uint64_t biasBt,
31+ uint32_t mTileActual,
32+ uint32_t nTileActual,
33+ uint32_t kPartActual,
34+ bool initC,
35+ uint8_t unitFlag = 0) {};
36+};
37+ 
38+// Partial specialization for V220, int8_t, not_vector_A, not TransposeA
39+template <ArchType ArchTag, typename AccDTypeC, typename ElementA, typename ElementB>
40+struct mmad<ArchTag, ElementA, ElementB, AccDTypeC, false> {
41+ __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor,
42+ AscendC::LocalTensor<ElementA> l0aTensor,
43+ AscendC::LocalTensor<ElementB> l0bTensor,
44+ uint32_t mTileActual,
45+ uint32_t nTileActual,
46+ uint32_t kPartActual,
47+ bool initC,
48+ uint8_t unitFlag = 0)
49+ {
50+ AscendC::Mmad(l0cTensor, // C
51+ l0aTensor, // A
52+ l0bTensor, // B
53+ AscendC::MmadParams(mTileActual, // m
54+ nTileActual, // n
55+ kPartActual, // k
56+ unitFlag, // unitFlag
57+ false, // cmatrixSource
58+ initC)); // cmatrixInitVal
59+ };
60+ 
61+ __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor,
62+ AscendC::LocalTensor<ElementA> l0aTensor,
63+ AscendC::LocalTensor<ElementB> l0bTensor,
64+ uint64_t biasBt,
65+ uint32_t mTileActual,
66+ uint32_t nTileActual,
67+ uint32_t kPartActual,
68+ bool initC,
69+ uint8_t unitFlag = 0)
70+ {
71+ AscendC::LocalTensor<AccDTypeC> biasTensor;
72+ biasTensor.InitBuffer(biasBt, nTileActual);
73+ biasTensor.address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::C2);
74+ AscendC::Mmad(l0cTensor, // C
75+ l0aTensor, // A
76+ l0bTensor, // B
77+ biasTensor, // bt
78+ AscendC::MmadParams(mTileActual, // m
79+ nTileActual, // n
80+ kPartActual, // k
81+ unitFlag, // unitFlag
82+ true, // cmatrixSource
83+ false)); // cmatrixInitVal
84+ };
85+};
86+ 
87+#endif