已合并
add AscendAntiQuantV2 #1643
clwsy创建于 2月6日
add AscendAntiQuantV2 #1643
已合并
clwsy创建于 2月6日
37 个文件变更+8959-110
Mdocs/zh/op_api_list.md+1-1文件内容审核中,请稍后刷新重试
Mdocs/zh/op_list.md+3-3
@@ -2927,12 +2927,12 @@
2927 <tr>2927 <tr>
2928 <td>quant</td>2928 <td>quant</td>
2929 <td><a href="../../quant/ascend_anti_quant_v2/README.md">ascend_anti_quant_v2</a></td>2929 <td><a href="../../quant/ascend_anti_quant_v2/README.md">ascend_anti_quant_v2</a></td>
2930- <td>✗</td>
2931 <td>✓</td>2930 <td>✓</td>
2932 <td>✓</td>2931 <td>✓</td>
2933- <td></td>2932+ <td></td>
2933+ <td>✓</td>
2934 <td>AI Core</td>2934 <td>AI Core</td>
2935- <td>该算子暂无Ascend C代码实现,欢迎开发者补充贡献,贡献方式参考<a href="../../CONTRIBUTING.md">贡献指南</a>。</td>2935+ <td>根据输入的scale和offset对输入x进行反量化。</td>
2936 </tr>2936 </tr>
2937 <tr>2937 <tr>
2938 <td>quant</td>2938 <td>quant</td>
Mquant/ascend_anti_quant_v2/README.md+124-1
@@ -1,3 +1,126 @@
1# AscendAntiQuantV21# AscendAntiQuantV2
2 2 
3-本目录仅包含AscendAntiQuantV2算子对应的aclnn接口;如您想要贡献该算子的AscendC实现,请参考[贡献流程](../../CONTRIBUTING.md)。3+## 产品支持情况
4+ 
5+| 产品 | 是否支持 |
6+| :----------------------------------------------------------- | :------: |
7+| <term>Ascend 950PR/Ascend 950DT</term> | √ |
8+| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ |
9+| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品 </term> | √ |
10+| <term>Atlas 200I/500 A2 推理产品</term> | × |
11+| <term>Atlas 推理系列产品 </term> | √ |
12+| <term>Atlas 训练系列产品</term> | × |
13+ 
14+## 功能说明
15+ 
16+- 算子功能:根据输入的scale和offset对输入x进行反量化。
17+ 
18+- 计算公式:
19+ - sqrtMode为true,offset为None时,计算公式为:
20+ 
21+ $$
22+ y = cast\_to\_dst\_type((x) * scale * scale)
23+ $$
24+ 
25+ - sqrtMode为true,offset不为None时,计算公式为:
26+ 
27+ $$
28+ y = cast\_to\_dst\_type((x + offset) * scale * scale)
29+ $$
30+ 
31+ - sqrtMode为false,offset为None时,计算公式为:
32+ 
33+ $$
34+ y = cast\_to\_dst\_type((x) * scale)
35+ $$
36+ 
37+ - sqrtMode为false,offset不为None时,计算公式为:
38+ 
39+ $$
40+ y = cast\_to\_dst\_type((x + offset) * scale)
41+ $$
42+ 
43+## 参数说明
44+ 
C
Cchenjiao3月23日

算子参数说明解释的是quant/ascend_anti_quant_v2/op_host/ascend_anti_quant_v2_def.cpp里参数含义

likedislike
clwsy
clwsy
3月23日 评论:
45+<table style="undefined;table-layout: fixed; width: 1005px"><colgroup>
46+ <col style="width: 170px">
47+ <col style="width: 170px">
48+ <col style="width: 352px">
49+ <col style="width: 213px">
50+ <col style="width: 100px">
51+ </colgroup>
52+ <thead>
53+ <tr>
54+ <th>参数名</th>
55+ <th>输入/输出/属性</th>
56+ <th>描述</th>
57+ <th>数据类型</th>
58+ <th>数据格式</th>
59+ </tr></thead>
60+ <tbody>
61+ <tr>
62+ <td>x</td>
63+ <td>输入</td>
64+ <td><ul><li>表示算子输入的Tensor,对应公式中的x;</li><li>不支持空Tensor;</li><li>当数据类型是INT4时,shape的尾轴为偶数。</td>
65+ <td>INT4、INT8、HIFLOAT8、FLOAT8_E4M3、FLOAT8_E5M2</td>
66+ <td>ND</td>
67+ </tr>
68+ <tr>
69+ <td>scale</td>
70+ <td>输入</td>
71+ <td><ul><li>表示反量化中的scale值。对应公式中的scale;</li><li>不支持空Tensor;</li><li>scale的维数必须与x相同,或者是1维;</li><li>如果x是1维,scale的形状必须是[1]或与x相同;</li><li>如果scale是1维,其大小必须是1、x[-1]或x[-2];</li><li>如果scale是多维,最多只能有一个非1的维度,且这个非1的维度只能是-1或-2轴;</li><li>当输入x的类型为HIFLOAT8、FLOAT8_E4M3、FLOAT8_E5M2时,scale只支持FLOAT32。</td>
72+ <td>FLOAT32、BFLOAT16</td>
73+ <td>ND</td>
74+ </tr>
75+ <tr>
76+ <td>offset</td>
77+ <td>可选输入</td>
78+ <td><ul><li>表示反量化中的offset值。对应公式中的offset;</li><li>不支持空Tensor;</li><li>数据类型和shape需要与scale保持一致。</td>
79+ <td>和scale一致</td>
80+ <td>ND</td>
81+ </tr>
82+ <tr>
83+ <td>dst_type</td>
84+ <td>可选属性</td>
85+ <td><ul><li>表示输出的数据类型;</li><li>支持取值1、27,分别表示FLOAT16、BFLOAT16。</td>
86+ <td>INT64</td>
87+ <td>-</td>
88+ </tr>
89+ <tr>
90+ <td>sqrt_mode</td>
91+ <td>可选属性</td>
92+ <td><ul><li>表示scale参与计算的逻辑。对应公式中的sqrtMode;</li><li>当x的数据类型为HIFLOAT8、FLOAT8_E4M3、FLOAT8_E5M2时,sqrtMode为false。</td>
93+ <td>BOOL</td>
94+ <td>-</td>
95+ </tr>
96+ <tr>
97+ <td>y</td>
98+ <td>输出</td>
99+ <td><ul><li>表示反量化的计算输出。对应公式中的y;</li><li>shape和输入x一致。</td>
100+ <td>FLOAT16、BFLOAT16</td>
101+ <td>ND</td>
102+ </tr>
103+ </tbody>
104+</table>
105+ 
106+- <term>Atlas 推理系列产品</term>
107+ - 数据类型:
108+ - 入参`x`仅支持INT8。
109+ - 入参`scale``offset`和出参`y`不支持BFLOAT16。
110+ - 入参`dstType`仅支持取值1,表示FLOAT16。
111+ - 入参`scale``offset`仅支持一维,且只能等于x尾轴大小或1,当x为int32类型时,必须为x尾轴大小的8倍。
112+- <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品/Atlas A3 训练系列产品/Atlas A3 推理系列产品</term>
113+ - 入参`x`仅支持INT4、INT8。
114+ - 入参`scale``offset`仅支持一维,且只能等于x尾轴大小或1,当x为int32类型时,必须为x尾轴大小的8倍。
115+ 
116+## 约束说明
117+ 
118+
119+ 
120+ 
121+## 调用说明
122+ 
123+| 调用方式 | 样例代码 | 说明 |
124+| ---------------- | --------------------------- | --------------------------------------------------- |
125+| aclnn接口 | [test_aclnn_ascend_anti_quant](examples/test_aclnn_ascend_anti_quant.cpp) | 通过[aclnnAscendAntiQuant](docs/aclnnAscendAntiQuant.md)接口方式调用AscendAntiQuantV2算子。 |
126+| 图模式 | - | 通过[算子IR](op_graph/ascend_anti_quant_v2_proto.h)构图方式调用AscendAntiQuantV2算子。 |
Mquant/ascend_anti_quant_v2/docs/aclnnAscendAntiQuant.md+38-22
@@ -6,7 +6,7 @@
6 6 
7|产品 | 是否支持 |7|产品 | 是否支持 |
8|:-------------------------|:----------:|8|:-------------------------|:----------:|
9-| <term>Ascend 950PR/Ascend 950DT</term> | × |9+| <term>Ascend 950PR/Ascend 950DT</term> | |
10| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ |10| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ |
11| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ |11| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ |
12| <term>Atlas 200I/500 A2 推理产品</term> | × |12| <term>Atlas 200I/500 A2 推理产品</term> | × |
@@ -17,16 +17,28 @@
17 17 
18- 接口功能:根据输入的scale和offset对输入x进行反量化。18- 接口功能:根据输入的scale和offset对输入x进行反量化。
19- 计算公式:19- 计算公式:
20- - sqrtMode为false时,计算公式为:20+ - sqrtMode为true,offset为None时,计算公式为:
21 21 
22 $$22 $$
23- y = float16((x+offset) * scale)23+ y = cast\_to\_dst\_type((x) * scale * scale)
24 $$24 $$
25 25 
26- - sqrtMode为true时,计算公式为:26+ - sqrtMode为true,offset不为None时,计算公式为:
27 27 
28 $$28 $$
29- y = float16((x+offset) * scale * scale)29+ y = cast\_to\_dst\_type((x + offset) * scale * scale)
30+ $$
31+ 
32+ - sqrtMode为false,offset为None时,计算公式为:
33+ 
34+ $$
35+ y = cast\_to\_dst\_type((x) * scale)
36+ $$
37+ 
38+ - sqrtMode为false,offset不为None时,计算公式为:
39+ 
40+ $$
41+ y = cast\_to\_dst\_type((x + offset) * scale)
30 $$42 $$
31 43 
32## 函数原型44## 函数原型
@@ -82,9 +94,9 @@ aclnnStatus aclnnAscendAntiQuant(
82 <tr>94 <tr>
83 <td>x(aclTensor*)</td>95 <td>x(aclTensor*)</td>
84 <td>输入</td>96 <td>输入</td>
85- <td>表示需要做反量化的输入。对应公式中的`x`。</td>97+ <td>表示需要做反量化的输入。对应公式中的x。</td>
86- <td><ul><li>支持空Tensor</li><li>当数据类型是INT32时,每个数据被作为8个INT4数据使用</li><li>当数据类型是INT4时,shape的尾轴为偶数。</li></ul></td>98+ <td><ul><li>支持空Tensor</li><li>当数据类型是INT32时,每个数据被作为8个INT4数据使用</li><li>当数据类型是INT4时,shape的尾轴为偶数。</li></ul></td>
87- <td>INT4、INT8、INT32</td>99+ <td>INT4、INT8、INT32、HIFLOAT8、FLOAT8_E4M3、FLOAT8_E5M2</td>
88 <td>ND</td>100 <td>ND</td>
89 <td>0-8</td>101 <td>0-8</td>
90 <td>√</td>102 <td>√</td>
@@ -92,26 +104,26 @@ aclnnStatus aclnnAscendAntiQuant(
92 <tr>104 <tr>
93 <td>scale(aclTensor*)</td>105 <td>scale(aclTensor*)</td>
94 <td>输入</td>106 <td>输入</td>
95- <td>反量化中的scale值。对应公式中的`scale`。</td>107+ <td>反量化中的scale值。对应公式中的scale。</td>
96- <td><ul><li>支持空Tensor</li><li>shape大小可以为1,如果不为1,在输入`x`为INT4/INT8类型时等于输入`x`的一个维度的大小输入`x`为INT32类型时,等于输入`x`的最后一个维度大小的8倍。</li></ul></td>108+ <td><ul><li>支持空Tensor</li><li>scale维数必须与x相同或者是1维;</li><li>如果x是1scale的形状必须是[1]或与x相同;</li><li>如果scale是1维其大小必须是1、x[-1]或x[-2];</li><li>如果scale是多维,多只能有一个非1的维度,且这个非1维度只能是-1或-2轴</li><li>当输入x为INT32类型且反量化轴为尾轴时,scale的尾轴需要等于x尾轴大小的8倍;</li><li>当x的类型为HIFLOAT8、FLOAT8_E4M3、FLOAT8_E5M2时,scale只支持FLOAT32。</li></ul></td>
97 <td>FLOAT32、BFLOAT16</td>109 <td>FLOAT32、BFLOAT16</td>
98 <td>ND</td>110 <td>ND</td>
99- <td>1</td>111+ <td>1-8</td>
100 <td>√</td>112 <td>√</td>
101 </tr>113 </tr>
102 <tr>114 <tr>
103 <td>offset(aclTensor*)</td>115 <td>offset(aclTensor*)</td>
104 <td>输入</td>116 <td>输入</td>
105- <td>反量化中的offset值。对应公式中的`offset`。</td>117+ <td>反量化中的offset值。对应公式中的offset。</td>
106- <td><ul><li>支持空Tensor</li><li>数据类型和shape需要与`scale`保持一致。</li></ul></td>118+ <td><ul><li>支持空Tensor</li><li>数据类型和shape需要与scale保持一致。</li></ul></td>
107 <td>FLOAT32、BFLOAT16</td>119 <td>FLOAT32、BFLOAT16</td>
108 <td>ND</td>120 <td>ND</td>
109- <td>1</td>121+ <td>1-8</td>
110 <td>√</td>122 <td>√</td>
111 </tr>123 </tr>
112 <tr>124 <tr>
113 <td>dstType(int64_t)</td>125 <td>dstType(int64_t)</td>
114- <td>输入</td>126+ <td>属性</td>
115 <td>指定输出的数据类型。</td>127 <td>指定输出的数据类型。</td>
116 <td>支持取值1、27,分别表示FLOAT16、BFLOAT16。</td>128 <td>支持取值1、27,分别表示FLOAT16、BFLOAT16。</td>
117 <td>-</td>129 <td>-</td>
@@ -121,9 +133,9 @@ aclnnStatus aclnnAscendAntiQuant(
121 </tr>133 </tr>
122 <tr>134 <tr>
123 <td>sqrtMode(bool)</td>135 <td>sqrtMode(bool)</td>
124- <td>输入</td>136+ <td>属性</td>
125- <td>指定scale参与计算的逻辑。对应公式中的`sqrtMode`。</td>137+ <td>指定scale参与计算的逻辑。对应公式中的sqrtMode。</td>
126- <td>-</td>138+ <td>当x的数据类型为HIFLOAT8、FLOAT8_E4M3、FLOAT8_E5M2时,sqrtMode为false。</td>
127 <td>-</td>139 <td>-</td>
128 <td>-</td>140 <td>-</td>
129 <td>-</td>141 <td>-</td>
@@ -132,8 +144,8 @@ aclnnStatus aclnnAscendAntiQuant(
132 <tr>144 <tr>
133 <td>y(aclTensor*)</td>145 <td>y(aclTensor*)</td>
134 <td>输出</td>146 <td>输出</td>
135- <td>反量化的计算输出。对应公式中的`y`。</td>147+ <td>反量化的计算输出。对应公式中的y。</td>
136- <td><ul><li>支持空Tensor。</li><li>当输入`x`INT4或INT8类型时,shape与输入`x`一致。</li><li>当输入`x`为INT32类型时,shape尾轴的大小为输入`x`的尾轴大小的8倍。</li></ul></td>148+ <td><ul><li>支持空Tensor。</li><li>当输入x为INT32类型时,shape尾轴的大小为输入x的尾轴大小的8倍,其余情况shape与输入x一致。</li></ul></td>
137 <td>FLOAT16、BFLOAT16</td>149 <td>FLOAT16、BFLOAT16</td>
138 <td>ND</td>150 <td>ND</td>
139 <td>0-8</td>151 <td>0-8</td>
@@ -167,6 +179,10 @@ aclnnStatus aclnnAscendAntiQuant(
167 - 入参`x`仅支持INT8。179 - 入参`x`仅支持INT8。
168 - 入参`scale``offset`和出参`y`不支持BFLOAT16。180 - 入参`scale``offset`和出参`y`不支持BFLOAT16。
169 - 入参`dstType`仅支持取值1,表示FLOAT16。181 - 入参`dstType`仅支持取值1,表示FLOAT16。
182+ - 入参`scale``offset`仅支持一维,且只能等于x尾轴大小或1,当x为int32类型时,必须为x尾轴大小的8倍。
183+ - <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品/Atlas A3 训练系列产品/Atlas A3 推理系列产品</term>
184+ - 入参`x`仅支持INT4、INT8、INT32。
185+ - 入参`scale``offset`仅支持一维,且只能等于x尾轴大小或1,当x为int32类型时,必须为x尾轴大小的8倍。
170 186 
171- **返回值:**187- **返回值:**
172 188 
@@ -201,9 +217,9 @@ aclnnStatus aclnnAscendAntiQuant(
201 <td>dstType不在有效取值范围。</td>217 <td>dstType不在有效取值范围。</td>
202 </tr>218 </tr>
203 <tr>219 <tr>
204- <td>x的数据类型为INT4时,x的shape尾轴大小不是偶数。</tr>220+ <td>x的数据类型为INT4时,x的反量化轴大小不是偶数。</tr>
205 <tr>221 <tr>
206- <td>x的数据类型为INT32时,y的shape尾轴不是x的shape尾轴大小的8倍,或者x与y的shape的非尾大小不一致。</td>222+ <td>x的数据类型为INT32时,y的反量化轴不是x的反量化轴大小的8倍,或者x与y的其他轴大小不一致。</td>
207 </tr>223 </tr>
208 </tbody></table>224 </tbody></table>
209 225 
Mquant/ascend_anti_quant_v2/op_graph/ascend_anti_quant_v2_proto.h+25-17
@@ -1,5 +1,5 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 * CANN Open Software License Agreement Version 2.0 (the "License").4 * CANN Open Software License Agreement Version 2.0 (the "License").
5 * Please refer to the License for details. You may not use this file except in compliance with the License.5 * Please refer to the License for details. You may not use this file except in compliance with the License.
@@ -15,31 +15,39 @@
15 15 
16namespace ge {16namespace ge {
17/**17/**
18-* @brief Anti quantizes the input . 18+* @brief Anti quantizes the input. \n
19 19 
20* @par Inputs:20* @par Inputs:
21-* @li x: A multi-dimensional tensor of type int8/int4, specifying the input.21+* @li x: A required Tensor. Must be one of the following types: int8, int4, hifloat8, float8_e5m2, float8_e4m3.
22- The maximum dimension should not exceed 8 dimensions. Format support ND. 22+* The format support ND. Shape support 1D ~ 8D. Specifying the input.
23-* @li scale: A 1-D tensor of type float32/bfloat16, specifying the scale.23+* @li scale: A required Tensor. Must be one of the following types: float32, bfloat16.
24- Shape is (n,), where n can be 1. If n is not 1, it must be the same as24+* The format support ND. Shape support 1D ~ 8D. Specifying the scaling ratio.
25- the size of last dimension of x. Format support ND. 25+* @li offset: An optional Tensor. Must be one of the following types: float32, bfloat16.
26-* @li offset: A optional 1-D tensor of type float32/bfloat16, specifying the offset.26+* The format support ND. Shape support 1D ~ 8D. Shape and dataType is same as "scale". Specifying the offset. \n
27- The shape and dtype of offset should be same to scale. Format support ND.
28 27 
29* @par Attributes:28* @par Attributes:
30* @li dst_type: A optional int32, specifying the output data type. Defaults to "DT_FLOAT16".29* @li dst_type: A optional int32, specifying the output data type. Defaults to "DT_FLOAT16".
31-* @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False".30+* @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "true" or "false".
32-* Defaults to "False" . \n31+* Defaults to "false" . \n
32+ 
33+* @attention Constraints:
34+* @li When dst_type of x is DT_INT4, the last axis of its shape is even.
35+# @li When the data type of x is DT_HIFLOAT8, DT_FLOAT8_E5M2, or DT_FLOAT8_E4M3, scale is only supported for DT_FLOAT.
36+# @li When the data type of x is DT_HIFLOAT8, DT_FLOAT8_E5M2, or DT_FLOAT8_E4M3, sqrt_mode must be "false".
37+* @li The dimensionality of scale must match that of x, or be 1-dimensional. The shape of scale must satisfy the following constraints: \n
38+* - If x is 1-dim, the shape of scale must be [1] or the same as x.
39+* - If scale is 1-dim, its size must be either 1, x[-1] or x[-2].
40+# - If scale is multi-dim, it can have at most one non-d dimension, and that dimension must be along the -1st or -2nd axis of x.
33 41 
34* @par Outputs:42* @par Outputs:
35-* y: The dequantized output tensor of type float16 or bfloat16. \n43+* y: The dequantized output tensor of type float16 or bfloat16. The format support ND.
36- 44+* Shape support 1D ~ 8D. Has the same shape as input "x". Dtype should be the same as the attribute dst_type. \n
37*/45*/
38REG_OP(AscendAntiQuantV2)46REG_OP(AscendAntiQuantV2)
39- .INPUT(x, TensorType({DT_INT8, DT_INT4}))47+ .INPUT(x, TensorType({DT_INT8, DT_INT4, DT_HIFLOAT8, DT_FLOAT8_E5M2, DT_FLOAT8_E4M3FN}))
40- .INPUT(scale, TensorType({DT_FLOAT, DT_BFLOAT16}))48+ .INPUT(scale, TensorType({DT_FLOAT, DT_BF16}))
41- .OPTIONAL_INPUT(offset, TensorType({DT_FLOAT, DT_BFLOAT16}))49+ .OPTIONAL_INPUT(offset, TensorType({DT_FLOAT, DT_BF16}))
42- .OUTPUT(y, TensorType({DT_FLOAT16, DT_BFLOAT16}))50+ .OUTPUT(y, TensorType({DT_FLOAT16, DT_BF16}))
43 .ATTR(dst_type, Int, DT_FLOAT16)51 .ATTR(dst_type, Int, DT_FLOAT16)
44 .ATTR(sqrt_mode, Bool, false)52 .ATTR(sqrt_mode, Bool, false)
45 .OP_END_FACTORY_REG(AscendAntiQuantV2)53 .OP_END_FACTORY_REG(AscendAntiQuantV2)
Aquant/ascend_anti_quant_v2/op_host/ascend_anti_quant_v2_def.cpp+68-0
@@ -0,0 +1,68 @@
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 ascend_anti_quant_v2.cpp
13+ * \brief
14+ */
15+#include "register/op_def_registry.h"
16+ 
17+namespace ops {
18+static const std::vector<ge::DataType> INPUT_DATA_TYPE = {ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT4, ge::DT_INT4, ge::DT_INT4, ge::DT_INT4,
19+ ge::DT_HIFLOAT8, ge::DT_HIFLOAT8, ge::DT_FLOAT8_E5M2, ge::DT_FLOAT8_E5M2, ge::DT_FLOAT8_E4M3FN, ge::DT_FLOAT8_E4M3FN};
20+ 
21+static const std::vector<ge::DataType> INPUT_SCALE_DATA_TYPE = {ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BF16,
22+ ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT};
23+ 
24+static const std::vector<ge::DataType> OUTPUT_DATA_TYPE = {ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_BF16,
25+ ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_BF16};
26+ 
27+static const std::vector<ge::Format> FORMAT = {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
28+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND};
29+ 
30+class AscendAntiQuantV2 : public OpDef {
31+public:
32+ explicit AscendAntiQuantV2(const char* name) : OpDef(name)
33+ {
34+ OpAICoreConfig config;
35+ config.Input("x")
36+ .ParamType(REQUIRED)
37+ .DataType(INPUT_DATA_TYPE)
38+ .Format(FORMAT)
39+ .UnknownShapeFormat(FORMAT);
40+ config.Input("scale")
41+ .ParamType(REQUIRED)
42+ .DataType(INPUT_SCALE_DATA_TYPE)
43+ .Format(FORMAT)
44+ .UnknownShapeFormat(FORMAT);
45+ config.Input("offset")
46+ .ParamType(OPTIONAL)
47+ .DataType(INPUT_SCALE_DATA_TYPE)
48+ .Format(FORMAT)
49+ .UnknownShapeFormat(FORMAT);
50+ config.Output("y")
51+ .ParamType(REQUIRED)
52+ .DataType(OUTPUT_DATA_TYPE)
53+ .Format(FORMAT)
54+ .UnknownShapeFormat(FORMAT);
55+ this->Attr("dst_type").AttrType(OPTIONAL).Int(ge::DT_FLOAT16);
56+ this->Attr("sqrt_mode").AttrType(OPTIONAL).Bool(false);
57+
58+ config.DynamicCompileStaticFlag(true)
59+ .DynamicRankSupportFlag(true)
60+ .DynamicShapeSupportFlag(true)
61+ .NeedCheckSupportFlag(false)
62+ .ExtendCfgInfo("opFile.value", "ascend_anti_quant_v2_apt");
63+ this->AICore().AddConfig("ascend950", config);
64+ }
65+};
66+ 
67+OP_ADD(AscendAntiQuantV2);
68+} // namespace ops
Aquant/ascend_anti_quant_v2/op_host/ascend_anti_quant_v2_infershape.cpp+47-0
@@ -0,0 +1,47 @@
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 ascend_quant_v2.cc
13+ * \brief
14+ */
15+#include "log/log.h"
16+#include "register/op_impl_registry.h"
17+ 
18+using namespace ge;
19+namespace ops {
20+constexpr size_t g_AttrDstType = 0;
21+ 
22+static graphStatus InferShapeForAscendAntiQuantV2(gert::InferShapeContext* context)
23+{
24+ OP_LOGD(context->GetNodeName(), "Begin to do InferShapeForAscendAntiQuantV2");
25+ const gert::Shape* inputXShape = context->GetInputShape(0);
26+ OP_CHECK_NULL_WITH_CONTEXT(context, inputXShape);
27+ 
28+ gert::Shape* outputShape = context->GetOutputShape(0);
29+
30+ *outputShape = *inputXShape;
31+ OP_LOGD(context->GetNodeName(), "End to do InferShapeForAscendAntiQuantV2");
32+ return ge::GRAPH_SUCCESS;
33+}
34+ 
35+static ge::graphStatus InferDataTypeForAscendAntiQuantV2(gert::InferDataTypeContext* context)
36+{
37+ OP_LOGD(context->GetNodeName(), "Begin to do InferDataTypeForAscendAntiQuantV2");
38+ const int32_t* dstDtype = context->GetAttrs()->GetAttrPointer<int32_t>(g_AttrDstType);
39+ OP_CHECK_NULL_WITH_CONTEXT(context, dstDtype);
40+ ge::DataType outDtype = static_cast<ge::DataType>(*dstDtype);
41+ context->SetOutputDataType(0, outDtype);
42+ OP_LOGD(context->GetNodeName(), "End to do InferDataTypeForAscendAntiQuantV2");
43+ return ge::GRAPH_SUCCESS;
44+}
45+ 
46+IMPL_OP_INFERSHAPE(AscendAntiQuantV2).InferShape(InferShapeForAscendAntiQuantV2).InferDataType(InferDataTypeForAscendAntiQuantV2);
47+} // namespace ops
Aquant/ascend_anti_quant_v2/op_host/ascend_anti_quant_v2_regbase_tiling.cpp+810-0
@@ -0,0 +1,810 @@
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 ascend_quant_v2_regbase_tiling.cc
13+ * \brief
14+ */
15+ 
16+#include "ascend_anti_quant_v2_regbase_tiling.h"
17+#include "../op_kernel/arch35/ascend_anti_quant_v2_struct.h"
18+ 
19+using namespace std;
20+using namespace ge;
21+using namespace AscendC;
22+using namespace AscendAntiQuantV2Op;
23+ 
24+namespace optiling {
25+constexpr size_t INPUT_X_INDEX = 0;
26+constexpr size_t INPUT_SCALE_INDEX = 1;
27+constexpr size_t INPUT_OFFSET_INDEX = 2;
28+constexpr size_t ATTR_DST_TYPE_INDEX = 0;
29+constexpr size_t ATTR_SQRT_MODE_INDEX = 1;
30+constexpr size_t SYNC_WORKSPACE_SIZE = 16777216;
31+constexpr int64_t CACHE_SIZE_950 = 128;
32+constexpr int64_t g_BaseLen = 128;
33+constexpr int64_t g_BlockSize = 32;
34+constexpr int64_t g_HalfBase = 2;
35+constexpr int32_t g_AxisMax = 2;
36+constexpr size_t g_FirstShapeDim = 0;
37+constexpr size_t g_SecondShapeDim = 1;
38+constexpr size_t g_ThirdShapeDim = 2;
39+constexpr int64_t FP32_BYTE_SIZE = 4;
40+constexpr int64_t FP16_BYTE_SIZE = 2;
41+static constexpr int64_t INT4_NUMS_IN_INT8_SPACE = 2;
42+constexpr int64_t DEFAULT_BASE_LEN = 128;
43+constexpr int64_t LAST_DIM_NUM = 128;
44+constexpr int64_t BUFF_NUM = 2;
45+static const gert::Shape g_vec_1_shape = {1};
46+static const gert::Shape g_vec_8_shape = {8};
47+ 
48+const gert::Shape& AscendAntiQuantV2Regbase::EnsureXAndScaleNotScalar(const gert::Shape& inShape)
49+{
50+ if (inShape.IsScalar()) {
51+ return g_vec_1_shape;
52+ }
53+ return inShape;
54+}
55+ 
56+const gert::Shape& AscendAntiQuantV2Regbase::EnsureYNotScalar(const gert::Shape& inShape)
57+{
58+ if (inShape.IsScalar()) {
59+ return g_vec_8_shape;
60+ }
61+ return inShape;
62+}
63+ 
64+ge::graphStatus AscendAntiQuantV2Regbase::DoAscendAntiQuantV2Tiling()
65+{
66+ OP_CHECK_IF(
67+ (GetCompileInfo() != ge::GRAPH_SUCCESS),
68+ OP_LOGE(context_->GetNodeName(), "DoAscendAntiQuantV2Tiling GetCompileInfo Failed."), return ge::GRAPH_FAILED);
69+ OP_CHECK_IF(
70+ (GetOpParam() != ge::GRAPH_SUCCESS),
71+ OP_LOGE(context_->GetNodeName(), "DoAscendAntiQuantV2Tiling GetOpParam Failed."), return ge::GRAPH_FAILED);
72+ 
73+ CalcTiling();
74+ CalcTilingKey();
75+ return WriteTilingData();
76+}
77+ 
78+ge::graphStatus AscendAntiQuantV2Regbase::GetCompileInfo()
79+{
80+ auto compileInfo = context_->GetCompileInfo<AscendAntiQuantV2CompileInfo>();
81+ OP_CHECK_NULL_WITH_CONTEXT(context_, compileInfo);
82+ coreNum_ = compileInfo->vectorCoreNum;
83+ ubSize_ = compileInfo->ubSize;
84+ OP_CHECK_IF(
85+ (coreNum_ <= 0 || ubSize_ <= 0),
86+ OP_LOGE(
87+ context_->GetNodeName(), "AscendAntiQuantV2 GetCompileInfo Failed, coreNum:%ld, ubSize:%lu.", coreNum_,
88+ ubSize_),
89+ return ge::GRAPH_FAILED);
90+ cacheLine_ = CACHE_SIZE_950;
91+ return ge::GRAPH_SUCCESS;
92+}
93+ 
94+ge::graphStatus AscendAntiQuantV2Regbase::CheckInputDtype()
95+{
96+ auto xInputDesc = context_->GetInputDesc(INPUT_X_INDEX);
97+ OP_CHECK_NULL_WITH_CONTEXT(context_, xInputDesc);
98+ xDtype_ = xInputDesc->GetDataType();
99+ 
100+ auto scaleInputDesc = context_->GetInputDesc(INPUT_SCALE_INDEX);
101+ OP_CHECK_NULL_WITH_CONTEXT(context_, scaleInputDesc);
102+ scaleDtype_ = scaleInputDesc->GetDataType();
103+ 
104+ auto yInputDesc = context_->GetOutputDesc(0);
105+ OP_CHECK_NULL_WITH_CONTEXT(context_, yInputDesc);
106+ yDtype_ = yInputDesc->GetDataType();
107+ 
108+ if (hasOffset_) {
109+ auto offsetInputDesc = context_->GetInputDesc(INPUT_OFFSET_INDEX);
110+ OP_CHECK_NULL_WITH_CONTEXT(context_, offsetInputDesc);
111+ auto offsetDtype = offsetInputDesc->GetDataType();
112+ 
113+ OP_CHECK_IF(
114+ scaleDtype_ != offsetDtype,
115+ OP_LOGE(
116+ context_->GetNodeName(), "input scale dtype %s is not same as input offset dtype %s",
117+ Ops::Base::ToString(scaleDtype_).c_str(), Ops::Base::ToString(offsetDtype).c_str()),
118+ return ge::GRAPH_FAILED);
119+ }
120+ 
121+ if (xDtype_ == ge::DT_HIFLOAT8 || xDtype_ == ge::DT_FLOAT8_E5M2 || xDtype_ == ge::DT_FLOAT8_E4M3FN) {
122+ OP_CHECK_IF(
123+ scaleDtype_ != ge::DT_FLOAT,
124+ OP_LOGE(
125+ context_->GetNodeName(), "when x is of type %s, the scale must be type FP32", Ops::Base::ToString(xDtype_).c_str()),
126+ return ge::GRAPH_FAILED);
127+ }
128+ 
129+ return ge::GRAPH_SUCCESS;
130+}
131+ 
132+ge::graphStatus AscendAntiQuantV2Regbase::CheckInputValid(
133+ const gert::Shape& input1, const gert::Shape& input2, const std::string& param) const
134+{
135+ size_t input1DimNum = input1.GetDimNum();
136+ size_t input2DimNum = input2.GetDimNum();
137+ if (static_cast<int32_t>(input1DimNum) != static_cast<int32_t>(input2DimNum) &&
138+ static_cast<int32_t>(input2DimNum) != 1) {
139+ OP_LOGE(
140+ context_->GetNodeName(), "the dimension(%zu) of %s is invalid, should be same as x(%zu) or 1", input2DimNum,
141+ param.c_str(), input1DimNum);
142+ return ge::GRAPH_FAILED;
143+ }
144+ 
145+ if (input1DimNum == static_cast<size_t>(1) && input2.GetDim(0) != 1 && input2.GetDim(0) != input1.GetDim(0)) {
146+ OP_LOGE(
147+ context_->GetNodeName(),
148+ "when the dim of x is 1, the shape of %s must be either 1 or the same as x", param.c_str());
149+ return ge::GRAPH_FAILED;
150+ }
151+ 
152+ if (input1DimNum > 1) {
153+ if (input2DimNum == static_cast<size_t>(1) && input2.GetDim(0) != input1.GetDim(input1DimNum - 1) &&
154+ input2.GetDim(0) != input1.GetDim(input1DimNum - 2) && input2.GetDim(0) != 1) {
155+ OP_LOGE(
156+ context_->GetNodeName(),
157+ "when the dim of %s is 1, its shape must be either 1, or match the -1 or -2 dim of x", param.c_str());
158+ return ge::GRAPH_FAILED;
159+ }
160+ if (input2DimNum > static_cast<size_t>(1)) {
161+ size_t input2Axis = (input2.GetDim(input2DimNum - 2) != 1 ? input2DimNum - 2 : input2DimNum - 1);
162+ auto input2Size = input2.GetShapeSize();
163+ if (input2Size != input2.GetDim(input2Axis)) {
164+ OP_LOGE(
165+ context_->GetNodeName(),
166+ "the %s can have at most one dimension that is not 1.", param.c_str());
167+ return ge::GRAPH_FAILED;
168+ }
169+ }
170+ }
171+
172+ return ge::GRAPH_SUCCESS;
173+}
174+ 
175+ge::graphStatus AscendAntiQuantV2Regbase::CheckOutputValid(const gert::Shape& input, const gert::Shape& output) const
176+{
177+ size_t inputDimNum = input.GetDimNum();
178+ size_t outputDimNum = output.GetDimNum();
179+ OP_CHECK_IF(
180+ inputDimNum != outputDimNum, OP_LOGE(context_->GetNodeName(), "x dim and y dim must be same."), return ge::GRAPH_FAILED);
181+ 
182+ for (uint32_t i = 0; i < inputDimNum; i++) {
183+ OP_CHECK_IF(input.GetDim(i) != output.GetDim(i), OP_LOGE(context_->GetNodeName(),
184+ "x shape and y shape must be same."), return ge::GRAPH_FAILED);
185+ }
186+ 
187+ return ge::GRAPH_SUCCESS;
188+}
189+ 
190+ge::graphStatus AscendAntiQuantV2Regbase::CheckShapeEqual(const gert::Shape& shape1, const gert::Shape& shape2) const
191+{
192+ size_t x1DimNum = shape1.GetDimNum();
193+ size_t x2DimNum = shape2.GetDimNum();
194+ OP_CHECK_IF(
195+ x1DimNum != x2DimNum, OP_LOGE(context_->GetNodeName(), "scale shape and offset shape must be same."),
196+ return ge::GRAPH_FAILED);
197+ for (uint32_t i = 0; i < x1DimNum; i++) {
198+ OP_CHECK_IF(
199+ shape1.GetDim(i) != shape2.GetDim(i),
200+ OP_LOGE(context_->GetNodeName(), "scale shape and offset shape must be same."), return ge::GRAPH_FAILED);
201+ }
202+ return ge::GRAPH_SUCCESS;
203+}
204+ 
205+ge::graphStatus AscendAntiQuantV2Regbase::CheckAttrs(const gert::Shape& xShape)
206+{
207+ auto* attrs = context_->GetAttrs();
208+ OP_CHECK_NULL_WITH_CONTEXT(context_, attrs);
209+ // get dstType
210+ const int32_t* dstType = attrs->GetAttrPointer<int32_t>(ATTR_DST_TYPE_INDEX);
211+ OP_CHECK_NULL_WITH_CONTEXT(context_, dstType);
212+ dstType_ = *dstType;
213+ // get sqrtMode
214+ const auto* sqrtMode = attrs->GetAttrPointer<bool>(ATTR_SQRT_MODE_INDEX);
215+ OP_CHECK_NULL_WITH_CONTEXT(context_, sqrtMode);
216+ sqrtMode_ = static_cast<int16_t>(*sqrtMode);
217+ 
218+ int32_t xDimNum = static_cast<int32_t>(xShape.GetDimNum());
219+ 
220+ // check dstType and output dtype, must be same
221+ if (dstType_ != ge::DT_FLOAT16 && dstType_ != ge::DT_BF16) {
222+ OP_LOGE(
223+ context_->GetNodeName(), "dst type:%s is invalid",
224+ Ops::Base::ToString(static_cast<ge::DataType>(dstType_)).c_str());
225+ return ge::GRAPH_FAILED;
226+ }
227+ if (dstType_ != yDtype_) {
228+ OP_LOGE(
229+ context_->GetNodeName(), "dst type:%s not equal output y dtype:%s",
230+ Ops::Base::ToString(static_cast<ge::DataType>(dstType_)).c_str(), Ops::Base::ToString(yDtype_).c_str());
231+ return ge::GRAPH_FAILED;
232+ }
233+ if (xDtype_ == ge::DT_INT4 && (xShape.GetDim(xDimNum - 1) % INT4_NUMS_IN_INT8_SPACE)) {
234+ OP_LOGE(
235+ context_->GetNodeName(), "if xDtype represents DT_INT4, x last dim:%ld must be divisible by 2",
236+ xShape.GetDim(xDimNum - 1));
237+ return ge::GRAPH_FAILED;
238+ }
239+ if (xDtype_ == ge::DT_HIFLOAT8 || xDtype_ == ge::DT_FLOAT8_E5M2 || xDtype_ == ge::DT_FLOAT8_E4M3FN) {
240+ OP_CHECK_IF(
241+ sqrtMode_ != 0,
242+ OP_LOGE(
243+ context_->GetNodeName(), "when x is of type %s, sqrtMode must be False", Ops::Base::ToString(xDtype_).c_str()),
244+ return ge::GRAPH_FAILED);
245+ }
246+ 
247+ return ge::GRAPH_SUCCESS;
248+}
249+ 
250+void AscendAntiQuantV2Regbase::MergeInputShape(const gert::Shape& input)
251+{
252+ int64_t shape0 = 1;
253+ int64_t shape1 = static_cast<int64_t>(input.GetDim(input.GetDimNum() - 1));
254+ int64_t shape2 = 1;
255+ if (mode_ == static_cast<uint32_t>(TPL_PER_TENSOR)) {
256+ // pertensor merge [1, x0*x1...*xn, 1]
257+ for (size_t idx = 0; idx < static_cast<size_t>(input.GetDimNum() - 1); ++idx) {
258+ shape1 = shape1 * static_cast<int64_t>(input.GetDim(idx));
259+ }
260+ } else if (mode_ == static_cast<uint32_t>(TPL_PER_HEAD)) {
261+ // perhead merge [x0*x1...*x(n-2), x(n-1), xn]
262+ for (size_t idx = 0; idx < static_cast<size_t>(input.GetDimNum() - 2); ++idx) {
263+ shape0 = shape0 * input.GetDim(idx);
264+ }
265+ shape1 = input.GetDim(input.GetDimNum() - 2);
266+ shape2 = input.GetDim(input.GetDimNum() - 1);
267+ } else {
268+ // perchannel merge [x0*x1*...*x(n-1), xn, 1]
269+ for (size_t idx = 0; idx < static_cast<size_t>(input.GetDimNum() - 1); ++idx) {
270+ shape0 = shape0 * input.GetDim(idx);
271+ }
272+ }
273+ // last dim is 1, perhead is perchannel
274+ if (mode_ == static_cast<uint32_t>(TPL_PER_HEAD) && shape2 == 1) {
275+ mode_ = static_cast<decltype(mode_)>(TPL_PER_CHANNEL);
276+ }
277+ // merge shape to 3 dim
278+ xInputShape_.SetDimNum(3);
279+ xInputShape_.SetDim(g_FirstShapeDim, shape0);
280+ xInputShape_.SetDim(g_SecondShapeDim, shape1);
281+ xInputShape_.SetDim(g_ThirdShapeDim, shape2);
282+ OP_LOGI(context_->GetNodeName(), "merge shape0:%ld, shape1:%ld, shape2:%ld", shape0, shape1, shape2);
283+}
284+ 
285+ge::graphStatus AscendAntiQuantV2Regbase::GetOpParam()
286+{
287+ auto xInput = context_->GetInputShape(INPUT_X_INDEX);
288+ OP_CHECK_NULL_WITH_CONTEXT(context_, xInput);
289+ auto scaleInput = context_->GetInputShape(INPUT_SCALE_INDEX);
290+ OP_CHECK_NULL_WITH_CONTEXT(context_, scaleInput);
291+ auto offsetInput = context_->GetOptionalInputShape(INPUT_OFFSET_INDEX);
292+ if (offsetInput == nullptr) {
293+ hasOffset_ = false;
294+ }
295+ auto yOut = context_->GetOutputShape(0);
296+ OP_CHECK_NULL_WITH_CONTEXT(context_, yOut);
297+ 
298+ // 不支持空tensor
299+ size_t xSizeNum = xInput->GetStorageShape().GetShapeSize();
300+ if (xSizeNum == 0ULL) {
301+ OP_LOGE(context_->GetNodeName(), "ascend_anti_quant_v2 does not support empty tensor.");
302+ return ge::GRAPH_FAILED;
303+ }
304+ 
305+ OP_CHECK_IF(
306+ (CheckInputDtype() != ge::GRAPH_SUCCESS), OP_LOGE(context_->GetNodeName(), "check input dtype failed."),
307+ return ge::GRAPH_FAILED);
308+ 
309+ const gert::Shape& xInputShape = EnsureXAndScaleNotScalar(xInput->GetStorageShape());
310+ const gert::Shape& scaleInputShape = EnsureXAndScaleNotScalar(scaleInput->GetStorageShape());
311+ const gert::Shape& yInputShape = EnsureYNotScalar(yOut->GetStorageShape());
312+ OP_CHECK_IF(
313+ (CheckAttrs(xInputShape) != ge::GRAPH_SUCCESS), OP_LOGE(context_->GetNodeName(), "op attrs is invalid."),
314+ return ge::GRAPH_FAILED);
315+ 
316+ // check the shape of the y is valid
317+ OP_CHECK_IF(
318+ (CheckOutputValid(xInputShape, yInputShape) != ge::GRAPH_SUCCESS),
319+ OP_LOGE(context_->GetNodeName(), "x and y is invalid."), return ge::GRAPH_FAILED);
320+ 
321+ // check the shape of the scale is valid
322+ OP_CHECK_IF(
323+ (CheckInputValid(xInputShape, scaleInputShape, "scale") != ge::GRAPH_SUCCESS),
324+ OP_LOGE(context_->GetNodeName(), "x and scale is invalid."), return ge::GRAPH_FAILED);
325+ // if offset is not null, check the shape of the offset
326+ if (hasOffset_) {
327+ const gert::Shape& offsetInputShape = EnsureXAndScaleNotScalar(offsetInput->GetStorageShape());
328+ // check scale and offset is same
329+ OP_CHECK_IF(
330+ (CheckShapeEqual(scaleInputShape, offsetInputShape) != ge::GRAPH_SUCCESS),
331+ OP_LOGE(context_->GetNodeName(), "scale and offset is invalid."), return ge::GRAPH_FAILED);
332+ // check the shape of the offset is valid
333+ OP_CHECK_IF(
334+ (CheckInputValid(xInputShape, offsetInputShape, "offset") != ge::GRAPH_SUCCESS),
335+ OP_LOGE(context_->GetNodeName(), "x and offset is invalid."), return ge::GRAPH_FAILED);
336+ }
337+ // check excute mode
338+ int32_t xDimNum = static_cast<int32_t>(xInputShape.GetDimNum());
339+ int32_t scaleDimNum = static_cast<int32_t>(scaleInputShape.GetDimNum());
340+ if (scaleInputShape.GetShapeSize() == 1) {
341+ mode_ = static_cast<decltype(mode_)>(TPL_PER_TENSOR);
342+ } else if (scaleDimNum == 1) {
343+ if (xDimNum > 1 && xInputShape.GetDim(xDimNum - 1) != xInputShape.GetDim(xDimNum - 2) &&
344+ scaleInputShape.GetDim(0) == xInputShape.GetDim(xDimNum - 2)) {
345+ mode_ = static_cast<decltype(mode_)>(TPL_PER_HEAD);
346+ } else {
347+ mode_ = static_cast<decltype(mode_)>(TPL_PER_CHANNEL);
348+ }
349+ } else if (scaleDimNum > 1 && scaleInputShape.GetDim(scaleDimNum - 2) != 1) {
350+ mode_ = static_cast<decltype(mode_)>(TPL_PER_HEAD);
351+ } else {
352+ mode_ = static_cast<decltype(mode_)>(TPL_PER_CHANNEL);
353+ }
354+ 
355+ MergeInputShape(xInputShape);
356+ return ge::GRAPH_SUCCESS;
357+}
358+ 
359+uint32_t AscendAntiQuantV2Regbase::GetCoreNum(int64_t factor, int64_t coreNum) const
360+{
361+ int64_t elePerCore = Ops::Base::CeilDiv(factor, static_cast<int64_t>(coreNum));
362+ uint32_t actCore = static_cast<uint32_t>(Ops::Base::CeilDiv(factor, elePerCore));
363+ return actCore;
364+}
365+ 
366+int64_t AscendAntiQuantV2Regbase::CalcMaxBaseLen(int64_t ubSize) const
367+{
368+ // set n == 1 to calc max base
369+ int64_t xDtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
370+ int64_t yDtypeSize = ge::GetSizeByDataType(yDtype_);
371+ int64_t scaleDtypeSize = ge::GetSizeByDataType(scaleDtype_);
372+ int64_t baseInput = hasOffset_ ? 2 : 1; // hasoffset means 2 input, else means 1 input
373+ if (mode_ == static_cast<int64_t>(TPL_PER_TENSOR)) {
374+ baseInput = 0;
375+ }
376+ int64_t totalBytes = (xDtypeSize + scaleDtypeSize * baseInput + yDtypeSize) * BUFF_NUM;
377+ return totalBytes == 0 ? DEFAULT_BASE_LEN : ubSize / totalBytes;
378+}
379+ 
380+int64_t AscendAntiQuantV2Regbase::CalcMaxN(int64_t ubSize, int64_t base) const
381+{
382+ int64_t xDtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
383+ int64_t yDtypeSize = ge::GetSizeByDataType(yDtype_);
384+ int64_t scaleDtypeSize = ge::GetSizeByDataType(scaleDtype_);
385+ int64_t leftXBytes = ubSize - base * scaleDtypeSize * BUFF_NUM;
386+ if (hasOffset_) {
387+ int64_t offsetDtypeSize = ge::GetSizeByDataType(scaleDtype_);
388+ leftXBytes -= base * offsetDtypeSize * BUFF_NUM;
389+ }
390+
391+ if (leftXBytes <= 0) {
392+ return 1;
393+ }
394+ 
395+ int64_t totalNBytes = xDtypeSize + yDtypeSize;
396+ if (totalNBytes == 0 || base == 0 || BUFF_NUM == 0) {
397+ return 0;
398+ }
399+ return leftXBytes / totalNBytes / base / BUFF_NUM;
400+}
401+ 
402+int64_t AscendAntiQuantV2Regbase::CalcPerChannelNddmaMaxN(int64_t ubSize, int64_t base) const
403+{
404+ int64_t xDtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
405+ int64_t yDtypeSize = ge::GetSizeByDataType(yDtype_);
406+ int64_t scalesDtypeSize = ge::GetSizeByDataType(scaleDtype_);
407+ int64_t offsetDtypeSize = 0;
408+ int64_t totalNBytes = 0;
409+ int64_t leftXBytes = 0;
410+ if (hasOffset_) {
411+ offsetDtypeSize = ge::GetSizeByDataType(scaleDtype_);
412+ }
413+ totalNBytes = base * (xDtypeSize + yDtypeSize + scalesDtypeSize + offsetDtypeSize) * BUFF_NUM;
414+ leftXBytes = ubSize - totalNBytes;
415+ if (leftXBytes <= 0) {
416+ return 1;
417+ }
418+ 
419+ return leftXBytes / totalNBytes;
420+}
421+ 
422+void AscendAntiQuantV2Regbase::CalcPerTensorBlockFactor(int64_t size)
423+{
424+ // 以一个cache为基本单位,计算block块的宽度
425+ blockFactor_ = Ops::Base::CeilDiv(size, actCoreNum_);
426+ int64_t shape = xInputShape_.GetDim(blockAxis_);
427+ int64_t dtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
428+ if (dtypeSize == 0) {
429+ return;
430+ }
431+ blockFactor_ = blockFactor_ * cacheLine_ / dtypeSize;
432+ blockTailFactor_ = shape - blockFactor_ * (actCoreNum_ - 1);
433+ blockTailFactor_ = blockTailFactor_ == 0 ? blockFactor_ : blockTailFactor_;
434+}
435+ 
436+void AscendAntiQuantV2Regbase::CalcPerChannelBlockFactor(int64_t size)
437+{
438+ blockFactor_ = Ops::Base::CeilDiv(size, actCoreNum_);
439+ if (blockAxis_ == 0) {
440+ // 切分合轴的情况,切行数
441+ blockTailFactor_ = size - blockFactor_ * (actCoreNum_ - 1);
442+ } else {
443+ // 切分尾轴的情况,以一个cache为基本单位
444+ int64_t shape = xInputShape_.GetDim(blockAxis_);
445+ int64_t dtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
446+ if (dtypeSize != 0) {
447+ blockFactor_ = blockFactor_ * cacheLine_ / dtypeSize;
448+ } else {
449+ blockFactor_ = 0;
450+ }
451+ blockTailFactor_ = shape - blockFactor_ * (actCoreNum_ - 1);
452+ }
453+ blockTailFactor_ = blockTailFactor_ == 0 ? blockFactor_ : blockTailFactor_;
454+}
455+ 
456+void AscendAntiQuantV2Regbase::CalcPerTensorUBFactor(int64_t numPerCache)
457+{
458+ int64_t availableUb = static_cast<int64_t>(ubSize_) - reserveUb_;
459+ int64_t maxBase = CalcMaxBaseLen(availableUb); // 一个UB能算的数
460+ maxBase = Ops::Base::FloorAlign(maxBase, numPerCache); // 用cacheLine对齐
461+ int64_t blockBase = blockFactor_; // block块的宽度
462+ blockBase = Ops::Base::CeilAlign(blockBase, numPerCache);
463+ baseN_ = 1;
464+ baseLen_ = std::min(blockBase, maxBase);
465+}
466+ 
467+void AscendAntiQuantV2Regbase::CalcPerChannelUBFactor(int64_t numPerCache)
468+{
469+ int64_t availableUb = static_cast<int64_t>(ubSize_) - reserveUb_;
470+ int64_t maxBase = CalcMaxBaseLen(availableUb); // 一个UB能算的数
471+ maxBase = Ops::Base::FloorAlign(maxBase, numPerCache); // 用cacheLine对齐
472+ // block cut axis 0, means all dim 1 is continous, else each core handle blockFactor
473+ int64_t blockBase = blockAxis_ == 0 ? xInputShape_.GetDim(1) : blockFactor_; // block的宽度,n方向
474+ blockBase = Ops::Base::CeilAlign(blockBase, numPerCache); // 用cacheLine对齐
475+ // 至少能放下2行时走第一分支
476+ if (blockBase <= maxBase / 2) {
477+ // need calc max n with real base
478+ int64_t maxN = CalcMaxN(availableUb, blockBase); // 一个UB能处理几行
479+ int64_t blockNSize = blockAxis_ == 0 ? blockFactor_ : xInputShape_.GetDim(0);
480+ baseN_ = std::min(maxN, blockNSize); // UB块的行数
481+ baseLen_ = Ops::Base::CeilAlign(blockBase, numPerCache); // UB块的宽度
482+ } else {
483+ baseN_ = 1;
484+ baseLen_ = std::min(blockBase, maxBase);
485+ }
486+}
487+ 
488+void AscendAntiQuantV2Regbase::CalcPerChannelNddmaUBFactor()
489+{
490+ // ub can split to three input: x_dtype_size * n * base, x_dtype_size * base, x_dtype_size * base
491+ // and one output: y_dtype_size * n * base
492+ int64_t availableUb = ubSize_ - reserveUb_;
493+ int64_t maxBase = CalcMaxBaseLen(availableUb); // 一个UB能算的数
494+ int64_t blockBase = blockAxis_ == 0 ? xInputShape_.GetDim(1) : blockFactor_; // block的宽度,n方向
495+ // 至少能放下2行时走第一分支
496+ if (blockBase <= maxBase / 2) {
497+ // need calc max n with real base
498+ int64_t maxN = CalcPerChannelNddmaMaxN(availableUb, blockBase); // 一个UB能处理几行
499+ int64_t blockInnerSize = blockAxis_ == 0 ? blockFactor_ : xInputShape_.GetDim(0);
500+ baseN_ = std::min(maxN, blockInnerSize); // UB块的行数
501+ baseLen_ = blockBase; // UB块的宽度
502+ } else {
503+ baseN_ = 1;
504+ baseLen_ = std::min(blockBase, maxBase);
505+ }
506+}
507+ 
508+void AscendAntiQuantV2Regbase::CalcTiling()
509+{
510+ if (mode_ == static_cast<int64_t>(TPL_PER_TENSOR)) {
511+ // per tensor模式,所有轴合一
512+ int64_t shape = xInputShape_.GetDim(1);
513+ int64_t dtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
514+ if (cacheLine_ == 0 || dtypeSize == 0) {
515+ return;
516+ }
517+ int64_t cacheLineNum = Ops::Base::CeilDiv(shape, cacheLine_ / dtypeSize);
518+ int64_t actCoreNum =
519+ static_cast<int64_t>(GetCoreNum(static_cast<int64_t>(cacheLineNum), static_cast<int64_t>(coreNum_)));
520+ 
521+ blockAxis_ = 1;
522+ actCoreNum_ = actCoreNum;
523+ int64_t size = cacheLineNum;
524+ CalcPerTensorBlockFactor(size);
525+ CalcPerTensorUBFactor(cacheLine_ / dtypeSize);
526+ } else if (mode_ == static_cast<int64_t>(TPL_PER_CHANNEL)) {
527+ // per channel模式,1是尾轴,0是其他轴的合轴
528+ int64_t shape0 = xInputShape_.GetDim(0);
529+ int64_t shape1 = xInputShape_.GetDim(1);
530+ int64_t dtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
531+ if (cacheLine_ == 0 || dtypeSize == 0) {
532+ return;
533+ }
534+ int64_t cacheLineNum =
535+ Ops::Base::CeilDiv(static_cast<int64_t>(shape1), static_cast<int64_t>(cacheLine_ / dtypeSize));
536+ int64_t actCoreNum0 = static_cast<int64_t>(GetCoreNum(shape0, coreNum_));
537+ int64_t actCoreNum1 = static_cast<int64_t>(GetCoreNum(cacheLineNum, coreNum_));
538+ 
539+ blockAxis_ = actCoreNum0 >= actCoreNum1 ? 0 : 1;
540+ actCoreNum_ = actCoreNum0 >= actCoreNum1 ? actCoreNum0 : actCoreNum1;
541+ int64_t size = actCoreNum0 >= actCoreNum1 ? shape0 : cacheLineNum;
542+ CalcPerChannelBlockFactor(size);
543+ if (shape1 < LAST_DIM_NUM && blockAxis_ == 0) {
544+ mode_ = TPL_PER_CHANNEL_NDDMA;
545+ CalcPerChannelNddmaUBFactor();
546+ } else {
547+ CalcPerChannelUBFactor(cacheLine_ / dtypeSize);
548+ }
549+ } else if (mode_ == static_cast<int64_t>(TPL_PER_HEAD)) {
550+ CalcPerHeadTiling();
551+ }
552+}
553+ 
554+void AscendAntiQuantV2Regbase::CalcPerHeadTiling()
555+{
556+ int64_t shape0 = xInputShape_.GetDim(g_FirstShapeDim);
557+ int64_t shape1 = xInputShape_.GetDim(g_SecondShapeDim);
558+ int64_t shape2 = xInputShape_.GetDim(g_ThirdShapeDim);
559+ int64_t dtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
560+ OP_CHECK_IF(dtypeSize == 0, OP_LOGE(context_->GetNodeName(), "dtypeSize should not be zero."), return);
561+ 
562+ if (cacheLine_ == 0 || dtypeSize == 0) {
563+ return;
564+ }
565+ int64_t cacheLineNum = Ops::Base::CeilDiv(shape2, cacheLine_ / dtypeSize);
566+ // split core in S, N, D
567+ // eg. [20, x, x] 40
568+ int64_t actCoreNum0 = static_cast<int64_t>(GetCoreNum(shape0, coreNum_));
569+ int64_t actCoreNum1 = static_cast<int64_t>(GetCoreNumDoubleCut(shape0, shape1, coreNum_));
570+ int64_t actCoreNum2 = static_cast<int64_t>(GetCoreNumDoubleCut(shape0 * shape1, cacheLineNum, coreNum_));
571+ 
572+ blockAxis_ = 0;
573+ actCoreNum_ = actCoreNum0;
574+ if (actCoreNum1 > actCoreNum_) {
575+ blockAxis_ = 1;
576+ actCoreNum_ = actCoreNum1;
577+ }
578+ if (actCoreNum2 > actCoreNum_ && shape2 > g_BlockSize) {
579+ blockAxis_ = static_cast<int64_t>(g_ThirdShapeDim);
580+ actCoreNum_ = actCoreNum2;
581+ }
582+ 
583+ CalcPerHeadBlockFactor();
584+ if (shape2 < LAST_DIM_NUM && (blockAxis_ == 0 || blockAxis_ == 1)) {
585+ mode_ = TPL_PER_HEAD_NDDMA;
586+ CalcPerHeadNddmaUBFactor();
587+ } else {
588+ CalcPerHeadUBFactor(cacheLine_ / dtypeSize);
589+ }
590+}
591+ 
592+void AscendAntiQuantV2Regbase::CalcPerHeadBlockFactor()
593+{
594+ int64_t shape0 = xInputShape_.GetDim(g_FirstShapeDim);
595+ int64_t shape1 = xInputShape_.GetDim(g_SecondShapeDim);
596+ int64_t shape2 = xInputShape_.GetDim(g_ThirdShapeDim);
597+ int64_t dtypeSize = ge::GetSizeByDataType(ge::DT_INT8);
598+ if (blockAxis_ == 0) {
599+ blockFactor_ = Ops::Base::CeilDiv(shape0, actCoreNum_);
600+ blockTailFactor_ = shape0 - blockFactor_ * (actCoreNum_ - 1);
601+ } else if (blockAxis_ == 1) {
602+ if (shape0 == 0) {
603+ return;
604+ }
605+ blockUnion_ = actCoreNum_ / shape0;
606+ blockFactor_ = Ops::Base::CeilDiv(shape1, blockUnion_);
607+ blockTailFactor_ = shape1 - blockFactor_ * (blockUnion_ - 1);
608+ } else {
609+ if (cacheLine_ == 0 || dtypeSize == 0) {
610+ return;
611+ }
612+ int64_t cacheLineNum = Ops::Base::CeilDiv(shape2, cacheLine_ / dtypeSize);
613+ if (shape0 == 0 || shape1 == 0) {
614+ return;
615+ }
616+ blockUnion_ = actCoreNum_ / shape0 / shape1;
617+ blockFactor_ = Ops::Base::CeilDiv(cacheLineNum, blockUnion_) * cacheLine_ / dtypeSize;
618+ blockTailFactor_ = shape2 - blockFactor_ * (blockUnion_ - 1);
619+ }
620+ blockTailFactor_ = blockTailFactor_ == 0 ? blockFactor_ : blockTailFactor_;
621+}
622+ 
623+void AscendAntiQuantV2Regbase::CalcPerHeadNddmaUBFactor()
624+{
625+ int64_t shape1 = xInputShape_.GetDim(g_SecondShapeDim);
626+ int64_t shape2 = xInputShape_.GetDim(g_ThirdShapeDim);
627+ 
628+ int64_t availableUb = static_cast<int64_t>(ubSize_) - reserveUb_;
629+ int64_t maxBase = CalcMaxBaseLen(availableUb);
630+ 
631+ // 圈复杂度重构
632+ if (blockAxis_ == 0) {
633+ if (shape1 * shape2 <= maxBase) {
634+ baseN_ = shape1;
635+ baseLen_ = shape2;
636+ } else if (shape2 <= maxBase) {
637+ if (shape2 == 0) {
638+ return;
639+ }
640+ baseN_ = maxBase / shape2; // must less than shape1
641+ baseLen_ = shape2;
642+ } else {
643+ baseN_ = 1;
644+ baseLen_ = maxBase;
645+ }
646+ } else {
647+ if (shape2 <= maxBase) {
648+ if (shape2 == 0) {
649+ return;
650+ }
651+ baseN_ = std::min(blockFactor_, maxBase / shape2);
652+ baseLen_ = shape2;
653+ } else {
654+ baseN_ = 1;
655+ baseLen_ = maxBase;
656+ }
657+ }
658+}
659+ 
660+void AscendAntiQuantV2Regbase::CalcPerHeadUBFactor(int64_t cacheLineNum)
661+{
662+ int64_t shape1 = xInputShape_.GetDim(g_SecondShapeDim);
663+ int64_t shape2 = xInputShape_.GetDim(g_ThirdShapeDim);
664+ shape2 = Ops::Base::CeilAlign(shape2, cacheLineNum);
665+ 
666+ int64_t availableUb = static_cast<int64_t>(ubSize_) - reserveUb_;
667+ int64_t maxBase = CalcMaxBaseLen(availableUb);
668+ maxBase = Ops::Base::FloorAlign(maxBase, cacheLineNum);
669+ int64_t blockBase = Ops::Base::CeilAlign(blockFactor_, cacheLineNum);
670+ 
671+ // 圈复杂度重构
672+ if (blockAxis_ == 0) {
673+ if (shape1 * shape2 <= maxBase) {
674+ baseN_ = shape1;
675+ baseLen_ = shape2;
676+ } else if (shape2 <= maxBase) {
677+ if (shape2 == 0) {
678+ return;
679+ }
680+ baseN_ = maxBase / shape2; // must less than shape1
681+ baseLen_ = shape2;
682+ } else {
683+ baseN_ = 1;
684+ baseLen_ = maxBase;
685+ }
686+ } else if (blockAxis_ == 1) {
687+ if (shape2 <= maxBase) {
688+ if (shape2 == 0) {
689+ return;
690+ }
691+ baseN_ = std::min(blockFactor_, maxBase / shape2);
692+ baseLen_ = shape2;
693+ } else {
694+ baseN_ = 1;
695+ baseLen_ = maxBase;
696+ }
697+ } else {
698+ baseN_ = 1;
699+ baseLen_ = std::min(blockBase, maxBase);
700+ }
701+}
702+ 
703+uint32_t AscendAntiQuantV2Regbase::GetCoreNumDoubleCut(int64_t shape0, int64_t shape1, int64_t coreNum) const
704+{
705+ if (shape0 == 0) {
706+ return 0;
707+ }
708+ int64_t yCoreNum = coreNum / shape0;
709+ if (yCoreNum == 0) {
710+ return static_cast<uint32_t>(yCoreNum);
711+ }
712+ uint32_t actCoreNum = GetCoreNum(shape1, yCoreNum);
713+ return static_cast<uint32_t>(shape0 * static_cast<int64_t>(actCoreNum));
714+}
715+ 
716+void AscendAntiQuantV2Regbase::CalcTilingKey()
717+{
718+ uint32_t zeroPointType = hasOffset_ ? static_cast<uint32_t>(TPL_HAS_OFFSET) : static_cast<uint32_t>(TPL_NO_OFFSET);
719+ uint32_t sqrtModeKey = static_cast<uint32_t>(sqrtMode_);
720+ tilingKey_ = GET_TPL_TILING_KEY(mode_, zeroPointType, sqrtModeKey);
721+}
722+ 
723+ge::graphStatus AscendAntiQuantV2Regbase::WriteTilingData()
724+{
725+ OP_LOGD(context_->GetNodeName(), "coreNum:%ld, tilingKey:%lu", coreNum_, tilingKey_);
726+ context_->SetBlockDim(coreNum_);
727+ context_->SetTilingKey(tilingKey_);
728+ 
729+ OP_LOGD(context_->GetNodeName(), "hasOffset:%d, sqrtMode:%d, dstType:%d", hasOffset_, sqrtMode_, dstType_);
730+ 
731+ OP_LOGD(
732+ context_->GetNodeName(),
733+ "actCoreNum:%ld, blockAxis:%d, blockFactor:%ld, blockTailFactor:%ld, baseN:%ld, baseLen:%ld",
734+ actCoreNum_, blockAxis_, blockFactor_, blockTailFactor_, baseN_, baseLen_);
735+ 
736+ int64_t shape0 = xInputShape_.GetDim(g_FirstShapeDim);
737+ int64_t shape1 = xInputShape_.GetDim(g_SecondShapeDim);
738+ int64_t shape2 = xInputShape_.GetDim(g_ThirdShapeDim);
739+ 
740+ tilingData.numCore = actCoreNum_;
741+ tilingData.blockAxis = blockAxis_;
742+ tilingData.blockUnion = blockUnion_;
743+ tilingData.dim0 = shape0;
744+ tilingData.dim1 = shape1;
745+ tilingData.dim2 = shape2;
746+ tilingData.blockFactor = blockFactor_;
747+ tilingData.blockTailFactor = blockTailFactor_;
748+ tilingData.baseN = baseN_;
749+ tilingData.baseLen = baseLen_;
750+ tilingData.hasOffset = hasOffset_;
751+ tilingData.sqrtMode = sqrtMode_;
752+ 
753+ uint64_t tilingDataSize = sizeof(tilingData);
754+ errno_t ret = memcpy_s(context_->GetRawTilingData()->GetData(), context_->GetRawTilingData()->GetCapacity(),
755+ reinterpret_cast<void *>(&tilingData), tilingDataSize);
756+ if (ret != EOK) {
757+ OP_LOGD(context_->GetNodeName(), "memcpy_s failde, ret=%d", ret);
758+ return ge::GRAPH_FAILED;
759+ }
760+ context_->GetRawTilingData()->SetDataSize(tilingDataSize);
761+ size_t* currentWorkspace = context_->GetWorkspaceSizes(1);
762+ currentWorkspace[0] = SYNC_WORKSPACE_SIZE;
763+ 
764+ return ge::GRAPH_SUCCESS;
765+}
766+ 
767+static ge::graphStatus TilingForAscendAntiQuantV2(gert::TilingContext* context)
768+{
769+ OP_LOGD("AscendAntiQuantV2Tiling", "Enter TilingForAscendAntiQuantV2Tiling");
770+ 
771+ OP_CHECK_IF(
772+ context == nullptr, OP_LOGE("AscendAntiQuantV2Tiling", "Tiling context is null."),
773+ return ge::GRAPH_FAILED);
774+ 
775+ AscendAntiQuantV2Regbase AscendAntiQuantV2Tiling(context);
776+ return AscendAntiQuantV2Tiling.DoAscendAntiQuantV2Tiling();
777+}
778+ 
779+static ge::graphStatus TilingPrepareForAscendAntiQuantV2(gert::TilingParseContext* context)
780+{
781+ OP_LOGD("AscendAntiQuantV2Tiling", "Enter TilingPrepareForAscendAntiQuantV2Tiling");
782+ 
783+ OP_CHECK_IF(
784+ context == nullptr, OP_LOGE("AscendAntiQuantV2Tiling", "TilingParse context is null."),
785+ return ge::GRAPH_FAILED);
786+ 
787+ auto compileInfo = context->GetCompiledInfo<AscendAntiQuantV2CompileInfo>();
788+ OP_CHECK_NULL_WITH_CONTEXT(context, compileInfo);
789+ auto platformInfo = context->GetPlatformInfo();
790+ OP_CHECK_NULL_WITH_CONTEXT(context, platformInfo);
791+ auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo);
792+ compileInfo->vectorCoreNum = ascendcPlatform.GetCoreNumAiv();
793+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, compileInfo->ubSize);
794+ 
795+ OP_CHECK_IF(
796+ (compileInfo->vectorCoreNum <= 0 || compileInfo->ubSize <= 0),
797+ OP_LOGE(
798+ context->GetNodeName(), "AscendAntiQuantV2 GetHardwareInfo Failed, vectorCoreNum:%d, ubSize:%lu.",
799+ compileInfo->vectorCoreNum, compileInfo->ubSize),
800+ return ge::GRAPH_FAILED);
801+ OP_LOGD(context->GetNodeName(), "GetCoreNum:%d, ubSize:%lu", compileInfo->vectorCoreNum, compileInfo->ubSize);
802+ 
803+ return ge::GRAPH_SUCCESS;
804+}
805+ 
806+IMPL_OP_OPTILING(AscendAntiQuantV2)
807+ .Tiling(TilingForAscendAntiQuantV2)
808+ .TilingParse<AscendAntiQuantV2CompileInfo>(TilingPrepareForAscendAntiQuantV2);
809+ 
810+} // namespace optiling
Aquant/ascend_anti_quant_v2/op_host/ascend_anti_quant_v2_regbase_tiling.h+106-0
@@ -0,0 +1,106 @@
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 ascend_anti_quant_v2_regbase_tiling.h
13+ * \brief
14+ */
15+ 
16+#ifndef OPS_BUILT_IN_OP_TILING_RUNTIME_ASCEND_ANTI_QUANT_V2_REGBASE_TILING_H
17+#define OPS_BUILT_IN_OP_TILING_RUNTIME_ASCEND_ANTI_QUANT_V2_REGBASE_TILING_H
18+ 
19+#include <cstdint>
20+#include <vector>
21+#include "register/tilingdata_base.h"
22+#include "log/log.h"
23+#include "register/op_impl_registry.h"
24+#include "util/math_util.h"
25+#include "tiling/platform/platform_ascendc.h"
26+#include "platform/platform_infos_def.h"
27+#include "op_host/tiling_base.h"
28+#include "op_common/op_host/util/platform_util.h"
29+#include "op_host/tiling_templates_registry.h"
30+#include "../op_kernel/arch35/ascend_anti_quant_v2_tilingdata.h"
31+ 
32+using namespace Ops::NN::Optiling;
33+ 
34+namespace optiling {
35+struct AscendAntiQuantV2CompileInfo {
36+ int32_t vectorCoreNum = 0;
37+ uint64_t ubSize = 0;
38+};
39+ 
40+class AscendAntiQuantV2Regbase {
41+public:
42+ explicit AscendAntiQuantV2Regbase(gert::TilingContext* context) : context_(context){};
43+ ge::graphStatus DoAscendAntiQuantV2Tiling();
44+ 
45+protected:
46+ ge::graphStatus GetCompileInfo();
47+ ge::graphStatus GetOpParam();
48+ ge::graphStatus CheckInputValid(
49+ const gert::Shape& input1, const gert::Shape& input2, const std::string& param) const;
50+ ge::graphStatus CheckOutputValid(const gert::Shape& input, const gert::Shape& output) const;
51+ ge::graphStatus CheckAttrs(const gert::Shape& xShape);
52+ ge::graphStatus WriteTilingData();
53+ void MergeInputShape(const gert::Shape& input);
54+ uint32_t GetCoreNum(int64_t factor, int64_t coreNum) const;
55+ uint32_t GetCoreNumDoubleCut(int64_t shape0, int64_t shape1, int64_t coreNum) const;
56+ void CalcTiling();
57+ void CalcTilingKey();
58+ void CalcPerHeadTiling();
59+ int64_t CalcMaxBaseLen(int64_t ubSize) const;
60+ int64_t CalcMaxN(int64_t ubSize, int64_t base) const;
61+ int64_t CalcPerChannelNddmaMaxN(int64_t ubSize, int64_t base) const;
62+ void CalcPerTensorBlockFactor(int64_t size);
63+ void CalcPerChannelBlockFactor(int64_t size);
64+ void CalcPerTensorUBFactor(int64_t numPerCache);
65+ void CalcPerChannelUBFactor(int64_t numPerCache);
66+ void CalcPerChannelNddmaUBFactor();
67+ void CalcPerHeadBlockFactor();
68+ void CalcPerHeadUBFactor(int64_t cacheLineNum);
69+ void CalcPerHeadNddmaUBFactor();
70+ 
71+ ge::graphStatus CheckShapeEqual(const gert::Shape& shape1, const gert::Shape& shape2) const;
72+ ge::graphStatus CheckInputDtype();
73+ const gert::Shape& EnsureXAndScaleNotScalar(const gert::Shape& inShape);
74+ const gert::Shape& EnsureYNotScalar(const gert::Shape& inShape);
75+ 
76+private:
77+ gert::TilingContext* context_ = nullptr;
78+ AscendAntiQuantV2TilingData tilingData;
79+ 
80+ int64_t coreNum_{0};
81+ uint64_t ubSize_{0};
82+ bool isAscend910B_{false};
83+ int64_t reserveUb_{2048};
84+ int64_t cacheLine_{256};
85+ 
86+ gert::Shape xInputShape_;
87+ ge::DataType xDtype_{ge::DT_UNDEFINED};
88+ ge::DataType yDtype_{ge::DT_UNDEFINED};
89+ ge::DataType scaleDtype_{ge::DT_UNDEFINED};
90+ bool hasOffset_{true};
91+ bool useDoubleCut{false};
92+ int16_t sqrtMode_ = 0;
93+ int32_t dstType_ = 0;
94+ 
95+ int64_t actCoreNum_{0};
96+ int64_t blockUnion_{1};
97+ int32_t blockAxis_{-1};
98+ int64_t blockFactor_{-1};
99+ int64_t blockTailFactor_{-1};
100+ int64_t baseN_{1};
101+ int64_t baseLen_{1};
102+ uint64_t tilingKey_{0};
103+ uint32_t mode_ = 0;
104+};
105+} // namespace optiling
106+#endif
Aquant/ascend_anti_quant_v2/op_host/config/ascend950/ascend_anti_quant_v2_binary.json+1769-0
@@ -0,0 +1,1769 @@
1+{
2+ "op_type": "AscendAntiQuantV2",
3+ "op_list": [
4+ {
5+ "bin_filename": "AscendAntiQuantV2_ffbf03b2f6cdbd5ae89f6191b81f54c2",
6+ "inputs": [
7+ {
8+ "name": "x",
9+ "index": 0,
10+ "dtype": "int4",
11+ "format": "ND",
12+ "paramType": "required",
13+ "shape": [
14+ -2
15+ ],
16+ "format_match_mode": "FormatDefault"
17+ },
18+ {
19+ "name": "scale",
20+ "index": 1,
21+ "dtype": "bfloat16",
22+ "format": "ND",
23+ "paramType": "required",
24+ "shape": [
25+ -2
26+ ],
27+ "format_match_mode": "FormatDefault"
28+ },
29+ {
30+ "name": "offset",
31+ "index": 2,
32+ "dtype": "bfloat16",
33+ "format": "ND",
34+ "paramType": "optional",
35+ "shape": [
36+ -2
37+ ],
38+ "format_match_mode": "FormatDefault"
39+ }
40+ ],
41+ "outputs": [
42+ {
43+ "name": "y",
44+ "index": 0,
45+ "dtype": "bfloat16",
46+ "format": "ND",
47+ "paramType": "required",
48+ "shape": [
49+ -2
50+ ],
51+ "format_match_mode": "FormatDefault"
52+ }
53+ ],
54+ "attrs": [
55+ {
56+ "name": "dst_type",
57+ "dtype": "int",
58+ "value": null
59+ },
60+ {
61+ "name": "sqrt_mode",
62+ "dtype": "bool",
63+ "value": false
64+ }
65+ ]
66+ },
67+ {
68+ "bin_filename": "AscendAntiQuantV2_e0c120dcb633297543605f0ea4d17615",
69+ "inputs": [
70+ {
71+ "name": "x",
72+ "index": 0,
73+ "dtype": "int4",
74+ "format": "ND",
75+ "paramType": "required",
76+ "shape": [
77+ -2
78+ ],
79+ "format_match_mode": "FormatDefault"
80+ },
81+ {
82+ "name": "scale",
83+ "index": 1,
84+ "dtype": "bfloat16",
85+ "format": "ND",
86+ "paramType": "required",
87+ "shape": [
88+ -2
89+ ],
90+ "format_match_mode": "FormatDefault"
91+ },
92+ {
93+ "name": "offset",
94+ "index": 2,
95+ "dtype": "bfloat16",
96+ "format": "ND",
97+ "paramType": "optional",
98+ "shape": [
99+ -2
100+ ],
101+ "format_match_mode": "FormatDefault"
102+ }
103+ ],
104+ "outputs": [
105+ {
106+ "name": "y",
107+ "index": 0,
108+ "dtype": "bfloat16",
109+ "format": "ND",
110+ "paramType": "required",
111+ "shape": [
112+ -2
113+ ],
114+ "format_match_mode": "FormatDefault"
115+ }
116+ ],
117+ "attrs": [
118+ {
119+ "name": "dst_type",
120+ "dtype": "int",
121+ "value": null
122+ },
123+ {
124+ "name": "sqrt_mode",
125+ "dtype": "bool",
126+ "value": true
127+ }
128+ ]
129+ },
130+ {
131+ "bin_filename": "AscendAntiQuantV2_a6f109304ef7c4fca371ecb5a3772011",
132+ "inputs": [
133+ {
134+ "name": "x",
135+ "index": 0,
136+ "dtype": "int4",
137+ "format": "ND",
138+ "paramType": "required",
139+ "shape": [
140+ -2
141+ ],
142+ "format_match_mode": "FormatDefault"
143+ },
144+ {
145+ "name": "scale",
146+ "index": 1,
147+ "dtype": "bfloat16",
148+ "format": "ND",
149+ "paramType": "required",
150+ "shape": [
151+ -2
152+ ],
153+ "format_match_mode": "FormatDefault"
154+ },
155+ {
156+ "name": "offset",
157+ "index": 2,
158+ "dtype": "bfloat16",
159+ "format": "ND",
160+ "paramType": "optional",
161+ "shape": [
162+ -2
163+ ],
164+ "format_match_mode": "FormatDefault"
165+ }
166+ ],
167+ "outputs": [
168+ {
169+ "name": "y",
170+ "index": 0,
171+ "dtype": "float16",
172+ "format": "ND",
173+ "paramType": "required",
174+ "shape": [
175+ -2
176+ ],
177+ "format_match_mode": "FormatDefault"
178+ }
179+ ],
180+ "attrs": [
181+ {
182+ "name": "dst_type",
183+ "dtype": "int",
184+ "value": null
185+ },
186+ {
187+ "name": "sqrt_mode",
188+ "dtype": "bool",
189+ "value": false
190+ }
191+ ]
192+ },
193+ {
194+ "bin_filename": "AscendAntiQuantV2_e14378ddb1b26ab56cbb7da89efe1afb",
195+ "inputs": [
196+ {
197+ "name": "x",
198+ "index": 0,
199+ "dtype": "int4",
200+ "format": "ND",
201+ "paramType": "required",
202+ "shape": [
203+ -2
204+ ],
205+ "format_match_mode": "FormatDefault"
206+ },
207+ {
208+ "name": "scale",
209+ "index": 1,
210+ "dtype": "bfloat16",
211+ "format": "ND",
212+ "paramType": "required",
213+ "shape": [
214+ -2
215+ ],
216+ "format_match_mode": "FormatDefault"
217+ },
218+ {
219+ "name": "offset",
220+ "index": 2,
221+ "dtype": "bfloat16",
222+ "format": "ND",
223+ "paramType": "optional",
224+ "shape": [
225+ -2
226+ ],
227+ "format_match_mode": "FormatDefault"
228+ }
229+ ],
230+ "outputs": [
231+ {
232+ "name": "y",
233+ "index": 0,
234+ "dtype": "float16",
235+ "format": "ND",
236+ "paramType": "required",
237+ "shape": [
238+ -2
239+ ],
240+ "format_match_mode": "FormatDefault"
241+ }
242+ ],
243+ "attrs": [
244+ {
245+ "name": "dst_type",
246+ "dtype": "int",
247+ "value": null
248+ },
249+ {
250+ "name": "sqrt_mode",
251+ "dtype": "bool",
252+ "value": true
253+ }
254+ ]
255+ },
256+ {
257+ "bin_filename": "AscendAntiQuantV2_85bd78a7a62d1d35e6f0fb5cf3ebe859",
258+ "inputs": [
259+ {
260+ "name": "x",
261+ "index": 0,
262+ "dtype": "int4",
263+ "format": "ND",
264+ "paramType": "required",
265+ "shape": [
266+ -2
267+ ],
268+ "format_match_mode": "FormatDefault"
269+ },
270+ {
271+ "name": "scale",
272+ "index": 1,
273+ "dtype": "float32",
274+ "format": "ND",
275+ "paramType": "required",
276+ "shape": [
277+ -2
278+ ],
279+ "format_match_mode": "FormatDefault"
280+ },
281+ {
282+ "name": "offset",
283+ "index": 2,
284+ "dtype": "float32",
285+ "format": "ND",
286+ "paramType": "optional",
287+ "shape": [
288+ -2
289+ ],
290+ "format_match_mode": "FormatDefault"
291+ }
292+ ],
293+ "outputs": [
294+ {
295+ "name": "y",
296+ "index": 0,
297+ "dtype": "bfloat16",
298+ "format": "ND",
299+ "paramType": "required",
300+ "shape": [
301+ -2
302+ ],
303+ "format_match_mode": "FormatDefault"
304+ }
305+ ],
306+ "attrs": [
307+ {
308+ "name": "dst_type",
309+ "dtype": "int",
310+ "value": null
311+ },
312+ {
313+ "name": "sqrt_mode",
314+ "dtype": "bool",
315+ "value": false
316+ }
317+ ]
318+ },
319+ {
320+ "bin_filename": "AscendAntiQuantV2_705d8813a0e4fe0d26c7aa3f0b488bbe",
321+ "inputs": [
322+ {
323+ "name": "x",
324+ "index": 0,
325+ "dtype": "int4",
326+ "format": "ND",
327+ "paramType": "required",
328+ "shape": [
329+ -2
330+ ],
331+ "format_match_mode": "FormatDefault"
332+ },
333+ {
334+ "name": "scale",
335+ "index": 1,
336+ "dtype": "float32",
337+ "format": "ND",
338+ "paramType": "required",
339+ "shape": [
340+ -2
341+ ],
342+ "format_match_mode": "FormatDefault"
343+ },
344+ {
345+ "name": "offset",
346+ "index": 2,
347+ "dtype": "float32",
348+ "format": "ND",
349+ "paramType": "optional",
350+ "shape": [
351+ -2
352+ ],
353+ "format_match_mode": "FormatDefault"
354+ }
355+ ],
356+ "outputs": [
357+ {
358+ "name": "y",
359+ "index": 0,
360+ "dtype": "bfloat16",
361+ "format": "ND",
362+ "paramType": "required",
363+ "shape": [
364+ -2
365+ ],
366+ "format_match_mode": "FormatDefault"
367+ }
368+ ],
369+ "attrs": [
370+ {
371+ "name": "dst_type",
372+ "dtype": "int",
373+ "value": null
374+ },
375+ {
376+ "name": "sqrt_mode",
377+ "dtype": "bool",
378+ "value": true
379+ }
380+ ]
381+ },
382+ {
383+ "bin_filename": "AscendAntiQuantV2_eafcd885a9e8164fccf39b53423c3b56",
384+ "inputs": [
385+ {
386+ "name": "x",
387+ "index": 0,
388+ "dtype": "int4",
389+ "format": "ND",
390+ "paramType": "required",
391+ "shape": [
392+ -2
393+ ],
394+ "format_match_mode": "FormatDefault"
395+ },
396+ {
397+ "name": "scale",
398+ "index": 1,
399+ "dtype": "float32",
400+ "format": "ND",
401+ "paramType": "required",
402+ "shape": [
403+ -2
404+ ],
405+ "format_match_mode": "FormatDefault"
406+ },
407+ {
408+ "name": "offset",
409+ "index": 2,
410+ "dtype": "float32",
411+ "format": "ND",
412+ "paramType": "optional",
413+ "shape": [
414+ -2
415+ ],
416+ "format_match_mode": "FormatDefault"
417+ }
418+ ],
419+ "outputs": [
420+ {
421+ "name": "y",
422+ "index": 0,
423+ "dtype": "float16",
424+ "format": "ND",
425+ "paramType": "required",
426+ "shape": [
427+ -2
428+ ],
429+ "format_match_mode": "FormatDefault"
430+ }
431+ ],
432+ "attrs": [
433+ {
434+ "name": "dst_type",
435+ "dtype": "int",
436+ "value": null
437+ },
438+ {
439+ "name": "sqrt_mode",
440+ "dtype": "bool",
441+ "value": false
442+ }
443+ ]
444+ },
445+ {
446+ "bin_filename": "AscendAntiQuantV2_bc5890e36c219f6d89e9500fb83fbe67",
447+ "inputs": [
448+ {
449+ "name": "x",
450+ "index": 0,
451+ "dtype": "int4",
452+ "format": "ND",
453+ "paramType": "required",
454+ "shape": [
455+ -2
456+ ],
457+ "format_match_mode": "FormatDefault"
458+ },
459+ {
460+ "name": "scale",
461+ "index": 1,
462+ "dtype": "float32",
463+ "format": "ND",
464+ "paramType": "required",
465+ "shape": [
466+ -2
467+ ],
468+ "format_match_mode": "FormatDefault"
469+ },
470+ {
471+ "name": "offset",
472+ "index": 2,
473+ "dtype": "float32",
474+ "format": "ND",
475+ "paramType": "optional",
476+ "shape": [
477+ -2
478+ ],
479+ "format_match_mode": "FormatDefault"
480+ }
481+ ],
482+ "outputs": [
483+ {
484+ "name": "y",
485+ "index": 0,
486+ "dtype": "float16",
487+ "format": "ND",
488+ "paramType": "required",
489+ "shape": [
490+ -2
491+ ],
492+ "format_match_mode": "FormatDefault"
493+ }
494+ ],
495+ "attrs": [
496+ {
497+ "name": "dst_type",
498+ "dtype": "int",
499+ "value": null
500+ },
501+ {
502+ "name": "sqrt_mode",
503+ "dtype": "bool",
504+ "value": true
505+ }
506+ ]
507+ },
508+ {
509+ "bin_filename": "AscendAntiQuantV2_6c286918b80d339a2939bf4648e2012f",
510+ "inputs": [
511+ {
512+ "name": "x",
513+ "index": 0,
514+ "dtype": "int8",
515+ "format": "ND",
516+ "paramType": "required",
517+ "shape": [
518+ -2
519+ ],
520+ "format_match_mode": "FormatDefault"
521+ },
522+ {
523+ "name": "scale",
524+ "index": 1,
525+ "dtype": "bfloat16",
526+ "format": "ND",
527+ "paramType": "required",
528+ "shape": [
529+ -2
530+ ],
531+ "format_match_mode": "FormatDefault"
532+ },
533+ {
534+ "name": "offset",
535+ "index": 2,
536+ "dtype": "bfloat16",
537+ "format": "ND",
538+ "paramType": "optional",
539+ "shape": [
540+ -2
541+ ],
542+ "format_match_mode": "FormatDefault"
543+ }
544+ ],
545+ "outputs": [
546+ {
547+ "name": "y",
548+ "index": 0,
549+ "dtype": "bfloat16",
550+ "format": "ND",
551+ "paramType": "required",
552+ "shape": [
553+ -2
554+ ],
555+ "format_match_mode": "FormatDefault"
556+ }
557+ ],
558+ "attrs": [
559+ {
560+ "name": "dst_type",
561+ "dtype": "int",
562+ "value": null
563+ },
564+ {
565+ "name": "sqrt_mode",
566+ "dtype": "bool",
567+ "value": false
568+ }
569+ ]
570+ },
571+ {
572+ "bin_filename": "AscendAntiQuantV2_bb59d06bddcf2044e44305e84ee88d61",
573+ "inputs": [
574+ {
575+ "name": "x",
576+ "index": 0,
577+ "dtype": "int8",
578+ "format": "ND",
579+ "paramType": "required",
580+ "shape": [
581+ -2
582+ ],
583+ "format_match_mode": "FormatDefault"
584+ },
585+ {
586+ "name": "scale",
587+ "index": 1,
588+ "dtype": "bfloat16",
589+ "format": "ND",
590+ "paramType": "required",
591+ "shape": [
592+ -2
593+ ],
594+ "format_match_mode": "FormatDefault"
595+ },
596+ {
597+ "name": "offset",
598+ "index": 2,
599+ "dtype": "bfloat16",
600+ "format": "ND",
601+ "paramType": "optional",
602+ "shape": [
603+ -2
604+ ],
605+ "format_match_mode": "FormatDefault"
606+ }
607+ ],
608+ "outputs": [
609+ {
610+ "name": "y",
611+ "index": 0,
612+ "dtype": "bfloat16",
613+ "format": "ND",
614+ "paramType": "required",
615+ "shape": [
616+ -2
617+ ],
618+ "format_match_mode": "FormatDefault"
619+ }
620+ ],
621+ "attrs": [
622+ {
623+ "name": "dst_type",
624+ "dtype": "int",
625+ "value": null
626+ },
627+ {
628+ "name": "sqrt_mode",
629+ "dtype": "bool",
630+ "value": true
631+ }
632+ ]
633+ },
634+ {
635+ "bin_filename": "AscendAntiQuantV2_d9de980292c01a395ca23266162ed8d7",
636+ "inputs": [
637+ {
638+ "name": "x",
639+ "index": 0,
640+ "dtype": "int8",
641+ "format": "ND",
642+ "paramType": "required",
643+ "shape": [
644+ -2
645+ ],
646+ "format_match_mode": "FormatDefault"
647+ },
648+ {
649+ "name": "scale",
650+ "index": 1,
651+ "dtype": "bfloat16",
652+ "format": "ND",
653+ "paramType": "required",
654+ "shape": [
655+ -2
656+ ],
657+ "format_match_mode": "FormatDefault"
658+ },
659+ {
660+ "name": "offset",
661+ "index": 2,
662+ "dtype": "bfloat16",
663+ "format": "ND",
664+ "paramType": "optional",
665+ "shape": [
666+ -2
667+ ],
668+ "format_match_mode": "FormatDefault"
669+ }
670+ ],
671+ "outputs": [
672+ {
673+ "name": "y",
674+ "index": 0,
675+ "dtype": "float16",
676+ "format": "ND",
677+ "paramType": "required",
678+ "shape": [
679+ -2
680+ ],
681+ "format_match_mode": "FormatDefault"
682+ }
683+ ],
684+ "attrs": [
685+ {
686+ "name": "dst_type",
687+ "dtype": "int",
688+ "value": null
689+ },
690+ {
691+ "name": "sqrt_mode",
692+ "dtype": "bool",
693+ "value": false
694+ }
695+ ]
696+ },
697+ {
698+ "bin_filename": "AscendAntiQuantV2_ef54143ef2f0bc28156ab4ea700ffb00",
699+ "inputs": [
700+ {
701+ "name": "x",
702+ "index": 0,
703+ "dtype": "int8",
704+ "format": "ND",
705+ "paramType": "required",
706+ "shape": [
707+ -2
708+ ],
709+ "format_match_mode": "FormatDefault"
710+ },
711+ {
712+ "name": "scale",
713+ "index": 1,
714+ "dtype": "bfloat16",
715+ "format": "ND",
716+ "paramType": "required",
717+ "shape": [
718+ -2
719+ ],
720+ "format_match_mode": "FormatDefault"
721+ },
722+ {
723+ "name": "offset",
724+ "index": 2,
725+ "dtype": "bfloat16",
726+ "format": "ND",
727+ "paramType": "optional",
728+ "shape": [
729+ -2
730+ ],
731+ "format_match_mode": "FormatDefault"
732+ }
733+ ],
734+ "outputs": [
735+ {
736+ "name": "y",
737+ "index": 0,
738+ "dtype": "float16",
739+ "format": "ND",
740+ "paramType": "required",
741+ "shape": [
742+ -2
743+ ],
744+ "format_match_mode": "FormatDefault"
745+ }
746+ ],
747+ "attrs": [
748+ {
749+ "name": "dst_type",
750+ "dtype": "int",
751+ "value": null
752+ },
753+ {
754+ "name": "sqrt_mode",
755+ "dtype": "bool",
756+ "value": true
757+ }
758+ ]
759+ },
760+ {
761+ "bin_filename": "AscendAntiQuantV2_bd2d9bd1655309893571009244932570",
762+ "inputs": [
763+ {
764+ "name": "x",
765+ "index": 0,
766+ "dtype": "int8",
767+ "format": "ND",
768+ "paramType": "required",
769+ "shape": [
770+ -2
771+ ],
772+ "format_match_mode": "FormatDefault"
773+ },
774+ {
775+ "name": "scale",
776+ "index": 1,
777+ "dtype": "float32",
778+ "format": "ND",
779+ "paramType": "required",
780+ "shape": [
781+ -2
782+ ],
783+ "format_match_mode": "FormatDefault"
784+ },
785+ {
786+ "name": "offset",
787+ "index": 2,
788+ "dtype": "float32",
789+ "format": "ND",
790+ "paramType": "optional",
791+ "shape": [
792+ -2
793+ ],
794+ "format_match_mode": "FormatDefault"
795+ }
796+ ],
797+ "outputs": [
798+ {
799+ "name": "y",
800+ "index": 0,
801+ "dtype": "bfloat16",
802+ "format": "ND",
803+ "paramType": "required",
804+ "shape": [
805+ -2
806+ ],
807+ "format_match_mode": "FormatDefault"
808+ }
809+ ],
810+ "attrs": [
811+ {
812+ "name": "dst_type",
813+ "dtype": "int",
814+ "value": null
815+ },
816+ {
817+ "name": "sqrt_mode",
818+ "dtype": "bool",
819+ "value": false
820+ }
821+ ]
822+ },
823+ {
824+ "bin_filename": "AscendAntiQuantV2_224c105876bb783e521dc1a5debdd6aa",
825+ "inputs": [
826+ {
827+ "name": "x",
828+ "index": 0,
829+ "dtype": "int8",
830+ "format": "ND",
831+ "paramType": "required",
832+ "shape": [
833+ -2
834+ ],
835+ "format_match_mode": "FormatDefault"
836+ },
837+ {
838+ "name": "scale",
839+ "index": 1,
840+ "dtype": "float32",
841+ "format": "ND",
842+ "paramType": "required",
843+ "shape": [
844+ -2
845+ ],
846+ "format_match_mode": "FormatDefault"
847+ },
848+ {
849+ "name": "offset",
850+ "index": 2,
851+ "dtype": "float32",
852+ "format": "ND",
853+ "paramType": "optional",
854+ "shape": [
855+ -2
856+ ],
857+ "format_match_mode": "FormatDefault"
858+ }
859+ ],
860+ "outputs": [
861+ {
862+ "name": "y",
863+ "index": 0,
864+ "dtype": "bfloat16",
865+ "format": "ND",
866+ "paramType": "required",
867+ "shape": [
868+ -2
869+ ],
870+ "format_match_mode": "FormatDefault"
871+ }
872+ ],
873+ "attrs": [
874+ {
875+ "name": "dst_type",
876+ "dtype": "int",
877+ "value": null
878+ },
879+ {
880+ "name": "sqrt_mode",
881+ "dtype": "bool",
882+ "value": true
883+ }
884+ ]
885+ },
886+ {
887+ "bin_filename": "AscendAntiQuantV2_c84bab62aa86157583f9fa95f401c00f",
888+ "inputs": [
889+ {
890+ "name": "x",
891+ "index": 0,
892+ "dtype": "int8",
893+ "format": "ND",
894+ "paramType": "required",
895+ "shape": [
896+ -2
897+ ],
898+ "format_match_mode": "FormatDefault"
899+ },
900+ {
901+ "name": "scale",
902+ "index": 1,
903+ "dtype": "float32",
904+ "format": "ND",
905+ "paramType": "required",
906+ "shape": [
907+ -2
908+ ],
909+ "format_match_mode": "FormatDefault"
910+ },
911+ {
912+ "name": "offset",
913+ "index": 2,
914+ "dtype": "float32",
915+ "format": "ND",
916+ "paramType": "optional",
917+ "shape": [
918+ -2
919+ ],
920+ "format_match_mode": "FormatDefault"
921+ }
922+ ],
923+ "outputs": [
924+ {
925+ "name": "y",
926+ "index": 0,
927+ "dtype": "float16",
928+ "format": "ND",
929+ "paramType": "required",
930+ "shape": [
931+ -2
932+ ],
933+ "format_match_mode": "FormatDefault"
934+ }
935+ ],
936+ "attrs": [
937+ {
938+ "name": "dst_type",
939+ "dtype": "int",
940+ "value": null
941+ },
942+ {
943+ "name": "sqrt_mode",
944+ "dtype": "bool",
945+ "value": false
946+ }
947+ ]
948+ },
949+ {
950+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6aa3472",
951+ "inputs": [
952+ {
953+ "name": "x",
954+ "index": 0,
955+ "dtype": "int8",
956+ "format": "ND",
957+ "paramType": "required",
958+ "shape": [
959+ -2
960+ ],
961+ "format_match_mode": "FormatDefault"
962+ },
963+ {
964+ "name": "scale",
965+ "index": 1,
966+ "dtype": "float32",
967+ "format": "ND",
968+ "paramType": "required",
969+ "shape": [
970+ -2
971+ ],
972+ "format_match_mode": "FormatDefault"
973+ },
974+ {
975+ "name": "offset",
976+ "index": 2,
977+ "dtype": "float32",
978+ "format": "ND",
979+ "paramType": "optional",
980+ "shape": [
981+ -2
982+ ],
983+ "format_match_mode": "FormatDefault"
984+ }
985+ ],
986+ "outputs": [
987+ {
988+ "name": "y",
989+ "index": 0,
990+ "dtype": "float16",
991+ "format": "ND",
992+ "paramType": "required",
993+ "shape": [
994+ -2
995+ ],
996+ "format_match_mode": "FormatDefault"
997+ }
998+ ],
999+ "attrs": [
1000+ {
1001+ "name": "dst_type",
1002+ "dtype": "int",
1003+ "value": null
1004+ },
1005+ {
1006+ "name": "sqrt_mode",
1007+ "dtype": "bool",
1008+ "value": true
1009+ }
1010+ ]
1011+ },
1012+ {
1013+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6aa3432",
1014+ "inputs": [
1015+ {
1016+ "name": "x",
1017+ "index": 0,
1018+ "dtype": "hifloat8",
1019+ "format": "ND",
1020+ "paramType": "required",
1021+ "shape": [
1022+ -2
1023+ ],
1024+ "format_match_mode": "FormatDefault"
1025+ },
1026+ {
1027+ "name": "scale",
1028+ "index": 1,
1029+ "dtype": "float32",
1030+ "format": "ND",
1031+ "paramType": "required",
1032+ "shape": [
1033+ -2
1034+ ],
1035+ "format_match_mode": "FormatDefault"
1036+ },
1037+ {
1038+ "name": "offset",
1039+ "index": 2,
1040+ "dtype": "float32",
1041+ "format": "ND",
1042+ "paramType": "optional",
1043+ "shape": [
1044+ -2
1045+ ],
1046+ "format_match_mode": "FormatDefault"
1047+ }
1048+ ],
1049+ "outputs": [
1050+ {
1051+ "name": "y",
1052+ "index": 0,
1053+ "dtype": "float16",
1054+ "format": "ND",
1055+ "paramType": "required",
1056+ "shape": [
1057+ -2
1058+ ],
1059+ "format_match_mode": "FormatDefault"
1060+ }
1061+ ],
1062+ "attrs": [
1063+ {
1064+ "name": "dst_type",
1065+ "dtype": "int",
1066+ "value": null
1067+ },
1068+ {
1069+ "name": "sqrt_mode",
1070+ "dtype": "bool",
1071+ "value": false
1072+ }
1073+ ]
1074+ },
1075+ {
1076+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6aa7389",
1077+ "inputs": [
1078+ {
1079+ "name": "x",
1080+ "index": 0,
1081+ "dtype": "hifloat8",
1082+ "format": "ND",
1083+ "paramType": "required",
1084+ "shape": [
1085+ -2
1086+ ],
1087+ "format_match_mode": "FormatDefault"
1088+ },
1089+ {
1090+ "name": "scale",
1091+ "index": 1,
1092+ "dtype": "float32",
1093+ "format": "ND",
1094+ "paramType": "required",
1095+ "shape": [
1096+ -2
1097+ ],
1098+ "format_match_mode": "FormatDefault"
1099+ },
1100+ {
1101+ "name": "offset",
1102+ "index": 2,
1103+ "dtype": "float32",
1104+ "format": "ND",
1105+ "paramType": "optional",
1106+ "shape": [
1107+ -2
1108+ ],
1109+ "format_match_mode": "FormatDefault"
1110+ }
1111+ ],
1112+ "outputs": [
1113+ {
1114+ "name": "y",
1115+ "index": 0,
1116+ "dtype": "float16",
1117+ "format": "ND",
1118+ "paramType": "required",
1119+ "shape": [
1120+ -2
1121+ ],
1122+ "format_match_mode": "FormatDefault"
1123+ }
1124+ ],
1125+ "attrs": [
1126+ {
1127+ "name": "dst_type",
1128+ "dtype": "int",
1129+ "value": null
1130+ },
1131+ {
1132+ "name": "sqrt_mode",
1133+ "dtype": "bool",
1134+ "value": true
1135+ }
1136+ ]
1137+ },
1138+ {
1139+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6aa9921",
1140+ "inputs": [
1141+ {
1142+ "name": "x",
1143+ "index": 0,
1144+ "dtype": "hifloat8",
1145+ "format": "ND",
1146+ "paramType": "required",
1147+ "shape": [
1148+ -2
1149+ ],
1150+ "format_match_mode": "FormatDefault"
1151+ },
1152+ {
1153+ "name": "scale",
1154+ "index": 1,
1155+ "dtype": "float32",
1156+ "format": "ND",
1157+ "paramType": "required",
1158+ "shape": [
1159+ -2
1160+ ],
1161+ "format_match_mode": "FormatDefault"
1162+ },
1163+ {
1164+ "name": "offset",
1165+ "index": 2,
1166+ "dtype": "float32",
1167+ "format": "ND",
1168+ "paramType": "optional",
1169+ "shape": [
1170+ -2
1171+ ],
1172+ "format_match_mode": "FormatDefault"
1173+ }
1174+ ],
1175+ "outputs": [
1176+ {
1177+ "name": "y",
1178+ "index": 0,
1179+ "dtype": "bfloat16",
1180+ "format": "ND",
1181+ "paramType": "required",
1182+ "shape": [
1183+ -2
1184+ ],
1185+ "format_match_mode": "FormatDefault"
1186+ }
1187+ ],
1188+ "attrs": [
1189+ {
1190+ "name": "dst_type",
1191+ "dtype": "int",
1192+ "value": null
1193+ },
1194+ {
1195+ "name": "sqrt_mode",
1196+ "dtype": "bool",
1197+ "value": false
1198+ }
1199+ ]
1200+ },
1201+ {
1202+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6aa8821",
1203+ "inputs": [
1204+ {
1205+ "name": "x",
1206+ "index": 0,
1207+ "dtype": "hifloat8",
1208+ "format": "ND",
1209+ "paramType": "required",
1210+ "shape": [
1211+ -2
1212+ ],
1213+ "format_match_mode": "FormatDefault"
1214+ },
1215+ {
1216+ "name": "scale",
1217+ "index": 1,
1218+ "dtype": "float32",
1219+ "format": "ND",
1220+ "paramType": "required",
1221+ "shape": [
1222+ -2
1223+ ],
1224+ "format_match_mode": "FormatDefault"
1225+ },
1226+ {
1227+ "name": "offset",
1228+ "index": 2,
1229+ "dtype": "float32",
1230+ "format": "ND",
1231+ "paramType": "optional",
1232+ "shape": [
1233+ -2
1234+ ],
1235+ "format_match_mode": "FormatDefault"
1236+ }
1237+ ],
1238+ "outputs": [
1239+ {
1240+ "name": "y",
1241+ "index": 0,
1242+ "dtype": "bfloat16",
1243+ "format": "ND",
1244+ "paramType": "required",
1245+ "shape": [
1246+ -2
1247+ ],
1248+ "format_match_mode": "FormatDefault"
1249+ }
1250+ ],
1251+ "attrs": [
1252+ {
1253+ "name": "dst_type",
1254+ "dtype": "int",
1255+ "value": null
1256+ },
1257+ {
1258+ "name": "sqrt_mode",
1259+ "dtype": "bool",
1260+ "value": true
1261+ }
1262+ ]
1263+ },
1264+ {
1265+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2g8fl03912",
1266+ "inputs": [
1267+ {
1268+ "name": "x",
1269+ "index": 0,
1270+ "dtype": "float8_e5m2",
1271+ "format": "ND",
1272+ "paramType": "required",
1273+ "shape": [
1274+ -2
1275+ ],
1276+ "format_match_mode": "FormatDefault"
1277+ },
1278+ {
1279+ "name": "scale",
1280+ "index": 1,
1281+ "dtype": "float32",
1282+ "format": "ND",
1283+ "paramType": "required",
1284+ "shape": [
1285+ -2
1286+ ],
1287+ "format_match_mode": "FormatDefault"
1288+ },
1289+ {
1290+ "name": "offset",
1291+ "index": 2,
1292+ "dtype": "float32",
1293+ "format": "ND",
1294+ "paramType": "optional",
1295+ "shape": [
1296+ -2
1297+ ],
1298+ "format_match_mode": "FormatDefault"
1299+ }
1300+ ],
1301+ "outputs": [
1302+ {
1303+ "name": "y",
1304+ "index": 0,
1305+ "dtype": "float16",
1306+ "format": "ND",
1307+ "paramType": "required",
1308+ "shape": [
1309+ -2
1310+ ],
1311+ "format_match_mode": "FormatDefault"
1312+ }
1313+ ],
1314+ "attrs": [
1315+ {
1316+ "name": "dst_type",
1317+ "dtype": "int",
1318+ "value": null
1319+ },
1320+ {
1321+ "name": "sqrt_mode",
1322+ "dtype": "bool",
1323+ "value": false
1324+ }
1325+ ]
1326+ },
1327+ {
1328+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6ad9803",
1329+ "inputs": [
1330+ {
1331+ "name": "x",
1332+ "index": 0,
1333+ "dtype": "float8_e5m2",
1334+ "format": "ND",
1335+ "paramType": "required",
1336+ "shape": [
1337+ -2
1338+ ],
1339+ "format_match_mode": "FormatDefault"
1340+ },
1341+ {
1342+ "name": "scale",
1343+ "index": 1,
1344+ "dtype": "float32",
1345+ "format": "ND",
1346+ "paramType": "required",
1347+ "shape": [
1348+ -2
1349+ ],
1350+ "format_match_mode": "FormatDefault"
1351+ },
1352+ {
1353+ "name": "offset",
1354+ "index": 2,
1355+ "dtype": "float32",
1356+ "format": "ND",
1357+ "paramType": "optional",
1358+ "shape": [
1359+ -2
1360+ ],
1361+ "format_match_mode": "FormatDefault"
1362+ }
1363+ ],
1364+ "outputs": [
1365+ {
1366+ "name": "y",
1367+ "index": 0,
1368+ "dtype": "float16",
1369+ "format": "ND",
1370+ "paramType": "required",
1371+ "shape": [
1372+ -2
1373+ ],
1374+ "format_match_mode": "FormatDefault"
1375+ }
1376+ ],
1377+ "attrs": [
1378+ {
1379+ "name": "dst_type",
1380+ "dtype": "int",
1381+ "value": null
1382+ },
1383+ {
1384+ "name": "sqrt_mode",
1385+ "dtype": "bool",
1386+ "value": true
1387+ }
1388+ ]
1389+ },
1390+ {
1391+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6bb5638",
1392+ "inputs": [
1393+ {
1394+ "name": "x",
1395+ "index": 0,
1396+ "dtype": "float8_e5m2",
1397+ "format": "ND",
1398+ "paramType": "required",
1399+ "shape": [
1400+ -2
1401+ ],
1402+ "format_match_mode": "FormatDefault"
1403+ },
1404+ {
1405+ "name": "scale",
1406+ "index": 1,
1407+ "dtype": "float32",
1408+ "format": "ND",
1409+ "paramType": "required",
1410+ "shape": [
1411+ -2
1412+ ],
1413+ "format_match_mode": "FormatDefault"
1414+ },
1415+ {
1416+ "name": "offset",
1417+ "index": 2,
1418+ "dtype": "float32",
1419+ "format": "ND",
1420+ "paramType": "optional",
1421+ "shape": [
1422+ -2
1423+ ],
1424+ "format_match_mode": "FormatDefault"
1425+ }
1426+ ],
1427+ "outputs": [
1428+ {
1429+ "name": "y",
1430+ "index": 0,
1431+ "dtype": "bfloat16",
1432+ "format": "ND",
1433+ "paramType": "required",
1434+ "shape": [
1435+ -2
1436+ ],
1437+ "format_match_mode": "FormatDefault"
1438+ }
1439+ ],
1440+ "attrs": [
1441+ {
1442+ "name": "dst_type",
1443+ "dtype": "int",
1444+ "value": null
1445+ },
1446+ {
1447+ "name": "sqrt_mode",
1448+ "dtype": "bool",
1449+ "value": false
1450+ }
1451+ ]
1452+ },
1453+ {
1454+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2ff9380",
1455+ "inputs": [
1456+ {
1457+ "name": "x",
1458+ "index": 0,
1459+ "dtype": "float8_e5m2",
1460+ "format": "ND",
1461+ "paramType": "required",
1462+ "shape": [
1463+ -2
1464+ ],
1465+ "format_match_mode": "FormatDefault"
1466+ },
1467+ {
1468+ "name": "scale",
1469+ "index": 1,
1470+ "dtype": "float32",
1471+ "format": "ND",
1472+ "paramType": "required",
1473+ "shape": [
1474+ -2
1475+ ],
1476+ "format_match_mode": "FormatDefault"
1477+ },
1478+ {
1479+ "name": "offset",
1480+ "index": 2,
1481+ "dtype": "float32",
1482+ "format": "ND",
1483+ "paramType": "optional",
1484+ "shape": [
1485+ -2
1486+ ],
1487+ "format_match_mode": "FormatDefault"
1488+ }
1489+ ],
1490+ "outputs": [
1491+ {
1492+ "name": "y",
1493+ "index": 0,
1494+ "dtype": "bfloat16",
1495+ "format": "ND",
1496+ "paramType": "required",
1497+ "shape": [
1498+ -2
1499+ ],
1500+ "format_match_mode": "FormatDefault"
1501+ }
1502+ ],
1503+ "attrs": [
1504+ {
1505+ "name": "dst_type",
1506+ "dtype": "int",
1507+ "value": null
1508+ },
1509+ {
1510+ "name": "sqrt_mode",
1511+ "dtype": "bool",
1512+ "value": true
1513+ }
1514+ ]
1515+ },
1516+ {
1517+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2g8fl03290",
1518+ "inputs": [
1519+ {
1520+ "name": "x",
1521+ "index": 0,
1522+ "dtype": "float8_e4m3fn",
1523+ "format": "ND",
1524+ "paramType": "required",
1525+ "shape": [
1526+ -2
1527+ ],
1528+ "format_match_mode": "FormatDefault"
1529+ },
1530+ {
1531+ "name": "scale",
1532+ "index": 1,
1533+ "dtype": "float32",
1534+ "format": "ND",
1535+ "paramType": "required",
1536+ "shape": [
1537+ -2
1538+ ],
1539+ "format_match_mode": "FormatDefault"
1540+ },
1541+ {
1542+ "name": "offset",
1543+ "index": 2,
1544+ "dtype": "float32",
1545+ "format": "ND",
1546+ "paramType": "optional",
1547+ "shape": [
1548+ -2
1549+ ],
1550+ "format_match_mode": "FormatDefault"
1551+ }
1552+ ],
1553+ "outputs": [
1554+ {
1555+ "name": "y",
1556+ "index": 0,
1557+ "dtype": "float16",
1558+ "format": "ND",
1559+ "paramType": "required",
1560+ "shape": [
1561+ -2
1562+ ],
1563+ "format_match_mode": "FormatDefault"
1564+ }
1565+ ],
1566+ "attrs": [
1567+ {
1568+ "name": "dst_type",
1569+ "dtype": "int",
1570+ "value": null
1571+ },
1572+ {
1573+ "name": "sqrt_mode",
1574+ "dtype": "bool",
1575+ "value": false
1576+ }
1577+ ]
1578+ },
1579+ {
1580+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2k3fa9902",
1581+ "inputs": [
1582+ {
1583+ "name": "x",
1584+ "index": 0,
1585+ "dtype": "float8_e4m3fn",
1586+ "format": "ND",
1587+ "paramType": "required",
1588+ "shape": [
1589+ -2
1590+ ],
1591+ "format_match_mode": "FormatDefault"
1592+ },
1593+ {
1594+ "name": "scale",
1595+ "index": 1,
1596+ "dtype": "float32",
1597+ "format": "ND",
1598+ "paramType": "required",
1599+ "shape": [
1600+ -2
1601+ ],
1602+ "format_match_mode": "FormatDefault"
1603+ },
1604+ {
1605+ "name": "offset",
1606+ "index": 2,
1607+ "dtype": "float32",
1608+ "format": "ND",
1609+ "paramType": "optional",
1610+ "shape": [
1611+ -2
1612+ ],
1613+ "format_match_mode": "FormatDefault"
1614+ }
1615+ ],
1616+ "outputs": [
1617+ {
1618+ "name": "y",
1619+ "index": 0,
1620+ "dtype": "float16",
1621+ "format": "ND",
1622+ "paramType": "required",
1623+ "shape": [
1624+ -2
1625+ ],
1626+ "format_match_mode": "FormatDefault"
1627+ }
1628+ ],
1629+ "attrs": [
1630+ {
1631+ "name": "dst_type",
1632+ "dtype": "int",
1633+ "value": null
1634+ },
1635+ {
1636+ "name": "sqrt_mode",
1637+ "dtype": "bool",
1638+ "value": true
1639+ }
1640+ ]
1641+ },
1642+ {
1643+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d2f6bb5823",
1644+ "inputs": [
1645+ {
1646+ "name": "x",
1647+ "index": 0,
1648+ "dtype": "float8_e4m3fn",
1649+ "format": "ND",
1650+ "paramType": "required",
1651+ "shape": [
1652+ -2
1653+ ],
1654+ "format_match_mode": "FormatDefault"
1655+ },
1656+ {
1657+ "name": "scale",
1658+ "index": 1,
1659+ "dtype": "float32",
1660+ "format": "ND",
1661+ "paramType": "required",
1662+ "shape": [
1663+ -2
1664+ ],
1665+ "format_match_mode": "FormatDefault"
1666+ },
1667+ {
1668+ "name": "offset",
1669+ "index": 2,
1670+ "dtype": "float32",
1671+ "format": "ND",
1672+ "paramType": "optional",
1673+ "shape": [
1674+ -2
1675+ ],
1676+ "format_match_mode": "FormatDefault"
1677+ }
1678+ ],
1679+ "outputs": [
1680+ {
1681+ "name": "y",
1682+ "index": 0,
1683+ "dtype": "bfloat16",
1684+ "format": "ND",
1685+ "paramType": "required",
1686+ "shape": [
1687+ -2
1688+ ],
1689+ "format_match_mode": "FormatDefault"
1690+ }
1691+ ],
1692+ "attrs": [
1693+ {
1694+ "name": "dst_type",
1695+ "dtype": "int",
1696+ "value": null
1697+ },
1698+ {
1699+ "name": "sqrt_mode",
1700+ "dtype": "bool",
1701+ "value": false
1702+ }
1703+ ]
1704+ },
1705+ {
1706+ "bin_filename": "AscendAntiQuantV2_650baea70767c4bd7838a0d3fg3472",
1707+ "inputs": [
1708+ {
1709+ "name": "x",
1710+ "index": 0,
1711+ "dtype": "float8_e4m3fn",
1712+ "format": "ND",
1713+ "paramType": "required",
1714+ "shape": [
1715+ -2
1716+ ],
1717+ "format_match_mode": "FormatDefault"
1718+ },
1719+ {
1720+ "name": "scale",
1721+ "index": 1,
1722+ "dtype": "float32",
1723+ "format": "ND",
1724+ "paramType": "required",
1725+ "shape": [
1726+ -2
1727+ ],
1728+ "format_match_mode": "FormatDefault"
1729+ },
1730+ {
1731+ "name": "offset",
1732+ "index": 2,
1733+ "dtype": "float32",
1734+ "format": "ND",
1735+ "paramType": "optional",
1736+ "shape": [
1737+ -2
1738+ ],
1739+ "format_match_mode": "FormatDefault"
1740+ }
1741+ ],
1742+ "outputs": [
1743+ {
1744+ "name": "y",
1745+ "index": 0,
1746+ "dtype": "bfloat16",
1747+ "format": "ND",
1748+ "paramType": "required",
1749+ "shape": [
1750+ -2
1751+ ],
1752+ "format_match_mode": "FormatDefault"
1753+ }
1754+ ],
1755+ "attrs": [
1756+ {
1757+ "name": "dst_type",
1758+ "dtype": "int",
1759+ "value": null
1760+ },
1761+ {
1762+ "name": "sqrt_mode",
1763+ "dtype": "bool",
1764+ "value": true
1765+ }
1766+ ]
1767+ }
1768+ ]
1769+}
Aquant/ascend_anti_quant_v2/op_host/config/ascend950/ascend_anti_quant_v2_simplified_key.ini+13-0
@@ -0,0 +1,13 @@
1+; 该文件主要影响 opc 工具 编译二进制kernel时, --simplified_key_mode 选项中填写的值,格式如下所示:
2+; [某算子]
3+; default=xx
4+; ascendxx=xx
5+; 其中,default为默认mode,ascendxx为可选mode,如果不同芯片有差异化要求时,需要配置;
6+; 1)如果没有配置:非ascendC算子继续按空处理,即opc编译命令中不添加 --simplified_key_mode 选项,AscendC算子按照 simplified_key_mode=0 处理
7+; 2)如果仅有default配置:各个版本按default配置
8+; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理
9+; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。
10+; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式
11+; 6)是否是AscendC算子,由 ops/build-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定
12+[AscendAntiQuantV2]
13+default=0
Mquant/ascend_anti_quant_v2/op_host/op_api/aclnn_ascend_anti_quant.cpp+130-47
@@ -1,5 +1,5 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 * CANN Open Software License Agreement Version 2.0 (the "License").4 * CANN Open Software License Agreement Version 2.0 (the "License").
5 * Please refer to the License for details. You may not use this file except in compliance with the License.5 * Please refer to the License for details. You may not use this file except in compliance with the License.
@@ -29,11 +29,18 @@ static constexpr int64_t EVEN_FACTOR = 2;
29static const std::initializer_list<DataType> X_DTYPE_SUPPORT_LIST_ASCEND910B = {29static const std::initializer_list<DataType> X_DTYPE_SUPPORT_LIST_ASCEND910B = {
30 op::DataType::DT_INT4, op::DataType::DT_INT8, op::DataType::DT_INT32};30 op::DataType::DT_INT4, op::DataType::DT_INT8, op::DataType::DT_INT32};
31 31 
32+static const std::initializer_list<DataType> X_DTYPE_SUPPORT_LIST_ASCEND950 = {
33+ op::DataType::DT_INT4, op::DataType::DT_INT8, op::DataType::DT_HIFLOAT8, op::DataType::DT_FLOAT8_E5M2,
34+ op::DataType::DT_FLOAT8_E4M3FN, op::DataType::DT_INT32};
35+ 
32static const std::initializer_list<DataType> X_DTYPE_SUPPORT_LIST_ASCEND310P = {op::DataType::DT_INT8};36static const std::initializer_list<DataType> X_DTYPE_SUPPORT_LIST_ASCEND310P = {op::DataType::DT_INT8};
33 37 
34static const std::initializer_list<DataType> OUT_DTYPE_SUPPORT_LIST_ASCEND910B = {38static const std::initializer_list<DataType> OUT_DTYPE_SUPPORT_LIST_ASCEND910B = {
35 op::DataType::DT_FLOAT16, op::DataType::DT_BF16};39 op::DataType::DT_FLOAT16, op::DataType::DT_BF16};
36 40 
41+static const std::initializer_list<DataType> OUT_DTYPE_SUPPORT_LIST_ASCEND950 = {
42+ op::DataType::DT_FLOAT16, op::DataType::DT_BF16};
43+ 
37static const std::initializer_list<DataType> OUT_DTYPE_SUPPORT_LIST_ASCEND310P = {op::DataType::DT_FLOAT16};44static const std::initializer_list<DataType> OUT_DTYPE_SUPPORT_LIST_ASCEND310P = {op::DataType::DT_FLOAT16};
38 45 
39static const std::initializer_list<DataType> EMPTY_LIST = {};46static const std::initializer_list<DataType> EMPTY_LIST = {};
@@ -41,21 +48,26 @@ static const std::initializer_list<DataType> EMPTY_LIST = {};
41static const std::initializer_list<DataType> SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND910B = {48static const std::initializer_list<DataType> SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND910B = {
42 op::DataType::DT_FLOAT, op::DataType::DT_BF16};49 op::DataType::DT_FLOAT, op::DataType::DT_BF16};
43 50 
51+static const std::initializer_list<DataType> SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND950 = {
52+ op::DataType::DT_FLOAT, op::DataType::DT_BF16};
53+ 
44static const std::initializer_list<DataType> SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND310P = {op::DataType::DT_FLOAT};54static const std::initializer_list<DataType> SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND310P = {op::DataType::DT_FLOAT};
45 55 
46static const std::initializer_list<DataType>& GetXDtypeSupportList()56static const std::initializer_list<DataType>& GetXDtypeSupportList()
47{57{
48- auto curArch = GetCurrentPlatformInfo().GetCurNpuArch();58+ if (Ops::NN::AclnnUtil::IsRegbase()) {
49- switch (curArch) {59+ return X_DTYPE_SUPPORT_LIST_ASCEND950;
50- case NpuArch::DAV_2201:60+ }
51- case NpuArch::DAV_3510: {61+ NpuArch npuArch = GetCurrentPlatformInfo().GetCurNpuArch();
62+ switch (npuArch) {
63+ case NpuArch::DAV_2201:{
52 return X_DTYPE_SUPPORT_LIST_ASCEND910B;64 return X_DTYPE_SUPPORT_LIST_ASCEND910B;
53 }65 }
54- case NpuArch::DAV_2002:66+ case NpuArch::DAV_2002:{
55 return X_DTYPE_SUPPORT_LIST_ASCEND310P;67 return X_DTYPE_SUPPORT_LIST_ASCEND310P;
68+ }
56 default: {69 default: {
57- SocVersion socVersion = GetCurrentPlatformInfo().GetSocVersion();70+ OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %u is not implemented", static_cast<uint32_t>(npuArch));
58- OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %s is not implemented", op::ToString(socVersion).GetString());
59 return EMPTY_LIST;71 return EMPTY_LIST;
60 }72 }
61 }73 }
@@ -63,17 +75,19 @@ static const std::initializer_list<DataType>& GetXDtypeSupportList()
63 75 
64static const std::initializer_list<DataType>& GetOutDtypeSupportList()76static const std::initializer_list<DataType>& GetOutDtypeSupportList()
65{77{
66- auto curArch = GetCurrentPlatformInfo().GetCurNpuArch();78+ if (Ops::NN::AclnnUtil::IsRegbase()) {
67- switch (curArch) {79+ return OUT_DTYPE_SUPPORT_LIST_ASCEND950;
68- case NpuArch::DAV_2201:80+ }
69- case NpuArch::DAV_3510: {81+ NpuArch npuArch = GetCurrentPlatformInfo().GetCurNpuArch();
82+ switch (npuArch) {
83+ case NpuArch::DAV_2201:{
70 return OUT_DTYPE_SUPPORT_LIST_ASCEND910B;84 return OUT_DTYPE_SUPPORT_LIST_ASCEND910B;
71 }85 }
72- case NpuArch::DAV_2002:86+ case NpuArch::DAV_2002:{
73 return OUT_DTYPE_SUPPORT_LIST_ASCEND310P;87 return OUT_DTYPE_SUPPORT_LIST_ASCEND310P;
88+ }
74 default: {89 default: {
75- SocVersion socVersion = GetCurrentPlatformInfo().GetSocVersion();90+ OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %u is not implemented", static_cast<uint32_t>(npuArch));
76- OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %s is not implemented", op::ToString(socVersion).GetString());
77 return EMPTY_LIST;91 return EMPTY_LIST;
78 }92 }
79 }93 }
@@ -81,17 +95,19 @@ static const std::initializer_list<DataType>& GetOutDtypeSupportList()
81 95 
82static const std::initializer_list<DataType>& GetScaleOffsetDtypeSupportList()96static const std::initializer_list<DataType>& GetScaleOffsetDtypeSupportList()
83{97{
84- auto curArch = GetCurrentPlatformInfo().GetCurNpuArch();98+ if (Ops::NN::AclnnUtil::IsRegbase()) {
85- switch (curArch) {99+ return SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND950;
86- case NpuArch::DAV_2201:100+ }
87- case NpuArch::DAV_3510: {101+ NpuArch npuArch = GetCurrentPlatformInfo().GetCurNpuArch();
102+ switch (npuArch) {
103+ case NpuArch::DAV_2201:{
88 return SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND910B;104 return SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND910B;
89 }105 }
90- case NpuArch::DAV_2002:106+ case NpuArch::DAV_2002:{
91 return SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND310P;107 return SCALE_OFFSET_DTYPE_SUPPORT_LIST_ASCEND310P;
108+ }
92 default: {109 default: {
93- SocVersion socVersion = GetCurrentPlatformInfo().GetSocVersion();110+ OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %u is not implemented", static_cast<uint32_t>(npuArch));
94- OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %s is not implemented", op::ToString(socVersion).GetString());
95 return EMPTY_LIST;111 return EMPTY_LIST;
96 }112 }
97 }113 }
@@ -121,37 +137,75 @@ static bool CheckDtypeValid(
121 return false;137 return false;
122 }138 }
123 139 
140+ if (scale->GetDataType() != op::DataType::DT_FLOAT && (x->GetDataType() == op::DataType::DT_HIFLOAT8 ||
141+ x->GetDataType() == op::DataType::DT_FLOAT8_E5M2 || x->GetDataType() == op::DataType::DT_FLOAT8_E4M3FN)) {
142+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "when x is of type %s, scale must be FLOAT", op::ToString(x->GetDataType()).GetString());
143+ return false;
144+ }
145+ 
124 return true;146 return true;
125}147}
126 148 
127static bool CheckDim(const aclTensor* y, const aclTensor* scale, const aclTensor* offset)149static bool CheckDim(const aclTensor* y, const aclTensor* scale, const aclTensor* offset)
128{150{
129- int64_t scaleDim = scale->GetViewShape().GetDim(0);
130 if (offset != nullptr) {151 if (offset != nullptr) {
131- int64_t offsetDim = offset->GetViewShape().GetDim(0);152+ OP_CHECK_SHAPE_NOT_EQUAL(scale, offset, return false);
132- if (scaleDim != offsetDim) {
133- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "dim of scale must be the same as dim of offset");
134- return false;
135- }
136 }153 }
137- 154+ // x and scale shape
155+ auto yShape = y->GetViewShape();
156+ auto scaleShape = scale->GetViewShape();
157+ int64_t scaleDim = scaleShape.GetDim(0);
138 // per-tensor158 // per-tensor
139 if (scaleDim == 1) {159 if (scaleDim == 1) {
140 return true;160 return true;
141 }161 }
142 162 
143- int64_t dimNum = static_cast<int64_t>(y->GetViewShape().GetDimNum());163+ int64_t dimNum = static_cast<int64_t>(yShape.GetDimNum());
144 if (dimNum == 0) {164 if (dimNum == 0) {
145 dimNum = 1;165 dimNum = 1;
146 }166 }
147 167 
148- int64_t lastDim = y->GetViewShape().GetDim(dimNum - 1);168+ int64_t lastDim = yShape.GetDim(dimNum - 1);
149 if (scaleDim != lastDim) {169 if (scaleDim != lastDim) {
150 OP_LOGE(170 OP_LOGE(
151 ACLNN_ERR_PARAM_INVALID, "the last dim size(%ld) of out(y) must be same as scale and offset(%ld).", lastDim,171 ACLNN_ERR_PARAM_INVALID, "the last dim size(%ld) of out(y) must be same as scale and offset(%ld).", lastDim,
152 scaleDim);172 scaleDim);
153 return false;173 return false;
154 }174 }
175+
176+ return true;
177+}
178+ 
179+static bool CheckXAndScaleDim(const aclTensor* x, const aclTensor* scale)
180+{
181+ if (x->GetDataType() != op::DataType::DT_INT32) {
182+ return true;
183+ }
184+ 
185+ auto scaleShape = scale->GetViewShape();
186+ auto xShape = x->GetViewShape();
187+ size_t scaleDimNum = static_cast<size_t>(scaleShape.GetDimNum());
188+ size_t xDimNum = static_cast<size_t>(xShape.GetDimNum());
189+ 
190+ auto xLastDim = (xDimNum > 0) ? xShape.GetDim(xDimNum - 1) : 0;
191+ auto xSecondLastDim = (xDimNum > 1) ? xShape.GetDim(xDimNum - 2) : 0;
192+ auto scaleLastDim = (scaleDimNum > 0) ? scaleShape.GetDim(scaleDimNum - 1) : 0;
193+ 
194+ if (xDimNum == 1 && scaleLastDim != 1 && scaleLastDim != xLastDim * INT4_NUMS_IN_INT32) {
195+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
196+ "when the dtype of x is int32 and x dim is 1, scale shape must be [1] or 8 times of x shape.");
197+ return false;
198+ } else if (xDimNum > 1) {
199+ if (scaleDimNum == 1 && scaleLastDim != xSecondLastDim && scaleLastDim != 1 && scaleLastDim != xLastDim * INT4_NUMS_IN_INT32) {
200+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
201+ "when the dtype of x is int32 and scale dim is 1, scale last dim must be [1], 8 times of x last dim or x -2 dim.");
202+ return false;
203+ } else if (scaleDimNum > 1 && scaleLastDim != 1 && scaleLastDim != xLastDim * INT4_NUMS_IN_INT32) {
204+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
205+ "when the dtype of x is int32, scale last dim must be [1] or 8 times of x last dim.");
206+ return false;
207+ }
208+ }
155 return true;209 return true;
156}210}
157 211 
@@ -234,29 +288,55 @@ static bool CheckShape(const aclTensor* x, const aclTensor* y, const aclTensor*
234 288 
235 // x的数据维度不能超过8289 // x的数据维度不能超过8
236 OP_CHECK_MAX_DIM(x, MAX_DIM_LEN, return false);290 OP_CHECK_MAX_DIM(x, MAX_DIM_LEN, return false);
237- if (scale->GetViewShape().GetDimNum() != 1) {291+ NpuArch npuArch = GetCurrentPlatformInfo().GetCurNpuArch();
238- OP_LOGE(ACLNN_ERR_PARAM_INVALID, "scale dim num must be 1. scale:%zu", scale->GetViewShape().GetDimNum());292+ if (npuArch != NpuArch::DAV_3510) {
239- return false;293+ if (scale->GetViewShape().GetDimNum() != 1) {
240- }294+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "scale dim num must be 1. scale:%zu", scale->GetViewShape().GetDimNum());
241- if (offset != nullptr) {
242- if (offset->GetViewShape().GetDimNum() != 1) {
243- OP_LOGE(
244- ACLNN_ERR_PARAM_INVALID, "offset dim num must be 1. offset:%zu", offset->GetViewShape().GetDimNum());
245 return false;295 return false;
246 }296 }
247- OP_CHECK_BROADCAST_WITH_SHAPE(offset, y->GetViewShape(), return false);297+ if (offset != nullptr) {
298+ if (offset->GetViewShape().GetDimNum() != 1) {
299+ OP_LOGE(
300+ ACLNN_ERR_PARAM_INVALID, "offset dim num must be 1. offset:%zu", offset->GetViewShape().GetDimNum());
301+ return false;
302+ }
303+ OP_CHECK_BROADCAST_WITH_SHAPE(offset, y->GetViewShape(), return false);
304+ }
305+ 
306+ CHECK_RET(CheckDim(y, scale, offset), false);
307+ 
308+ OP_CHECK_BROADCAST_WITH_SHAPE(scale, y->GetViewShape(), return false);
309+ } else {
S
Ssunday3月23日

问题: 在 DAV_3510 分支中,当 x 不是 INT32 且 offset 为空时,当前逻辑没有对 scale shape 做充分合法性约束(例如非法多维 scale 可能绕过该层校验),与文档约束不一致,存在行为不一致风险。

建议: 在 DAV_3510 分支补充非 INT32 场景的 scale shape 校验(至少覆盖 1D / 最后一维 / 倒数第二维等支持模式),并对非法 shape 返回 ACLNN_ERR_PARAM_INVALID。

likedislike
clwsy
clwsy
3月23日 评论:
310+ if (offset != nullptr) {
311+ OP_CHECK_SHAPE_NOT_EQUAL(scale, offset, return false);
312+ }
313+
314+ size_t dimNum = static_cast<size_t>(x->GetViewShape().GetDimNum());
315+ if (dimNum == 0 && x->GetDataType() != op::DataType::DT_INT32) {
316+ OP_LOGE(ACLNN_ERR_PARAM_INVALID,
317+ "when the dtype of x is not int32, x cannot be a scalar.");
318+ return false;
319+ }
320+ CHECK_RET(CheckXAndScaleDim(x, scale), false);
248 }321 }
249 322 
250- CHECK_RET(CheckDim(y, scale, offset), false);
251- 
252- OP_CHECK_BROADCAST_WITH_SHAPE(scale, y->GetViewShape(), return false);
253- 
254 OP_LOGD("CheckShape end");323 OP_LOGD("CheckShape end");
255 return true;324 return true;
256}325}
257 326 
327+static bool CheckAttrValid(const aclTensor* x, bool sqrtMode)
328+{
329+ if (sqrtMode != false && (x->GetDataType() == op::DataType::DT_HIFLOAT8 || x->GetDataType() == op::DataType::DT_FLOAT8_E5M2
330+ || x->GetDataType() == op::DataType::DT_FLOAT8_E4M3FN)) {
331+ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "when x is of type %s, sqrtMode must be False", op::ToString(x->GetDataType()).GetString());
332+ return false;
333+ }
334+ 
335+ return true;
336+}
337+ 
258static aclnnStatus CheckParams(338static aclnnStatus CheckParams(
259- const aclTensor* x, const aclTensor* scale, const aclTensor* offset, int64_t dstType, const aclTensor* y)339+ const aclTensor* x, const aclTensor* scale, const aclTensor* offset, int64_t dstType, bool sqrtMode, const aclTensor* y)
260{340{
261 // 1. 检查参数是否为空指针341 // 1. 检查参数是否为空指针
262 CHECK_RET(CheckNotNull(x, scale, y), ACLNN_ERR_PARAM_NULLPTR);342 CHECK_RET(CheckNotNull(x, scale, y), ACLNN_ERR_PARAM_NULLPTR);
@@ -264,7 +344,10 @@ static aclnnStatus CheckParams(
264 // 2. 检查输入的数据类型是否在API支持的数据类型范围之内,需要根据api定义校验344 // 2. 检查输入的数据类型是否在API支持的数据类型范围之内,需要根据api定义校验
265 CHECK_RET(CheckDtypeValid(x, scale, offset, y, dstType), ACLNN_ERR_PARAM_INVALID);345 CHECK_RET(CheckDtypeValid(x, scale, offset, y, dstType), ACLNN_ERR_PARAM_INVALID);
266 346 
267- // 3. 检查shape是否满足约束347+ // 3. 检查属性是否合法
348+ CHECK_RET(CheckAttrValid(x, sqrtMode), ACLNN_ERR_PARAM_INVALID);
349+ 
350+ // 4. 检查shape是否满足约束
268 CHECK_RET(CheckShape(x, y, scale, offset), ACLNN_ERR_PARAM_INVALID);351 CHECK_RET(CheckShape(x, y, scale, offset), ACLNN_ERR_PARAM_INVALID);
269 352 
270 return ACLNN_SUCCESS;353 return ACLNN_SUCCESS;
@@ -308,7 +391,7 @@ aclnnStatus aclnnAscendAntiQuantGetWorkspaceSize(
308 CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);391 CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
309 392 
310 // 固定写法,参数检查393 // 固定写法,参数检查
311- auto ret = CheckParams(x, scale, offset, dstType, y);394+ auto ret = CheckParams(x, scale, offset, dstType, sqrtMode, y);
312 CHECK_RET(ret == ACLNN_SUCCESS, ret);395 CHECK_RET(ret == ACLNN_SUCCESS, ret);
313 396 
314 // 空Tensor处理397 // 空Tensor处理
Mquant/ascend_anti_quant_v2/op_host/op_api/aclnn_ascend_anti_quant.h+2-2文件内容审核中,请稍后刷新重试
Mquant/ascend_anti_quant_v2/op_host/op_api/ascend_anti_quant_v2.cpp+3-2
@@ -1,5 +1,5 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 * CANN Open Software License Agreement Version 2.0 (the "License").4 * CANN Open Software License Agreement Version 2.0 (the "License").
5 * Please refer to the License for details. You may not use this file except in compliance with the License.5 * Please refer to the License for details. You may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@ namespace l0op {
26OP_TYPE_REGISTER(AscendAntiQuantV2);26OP_TYPE_REGISTER(AscendAntiQuantV2);
27 27 
28static const std::initializer_list<op::DataType> AICORE_DTYPE_SUPPORT_LIST = {28static const std::initializer_list<op::DataType> AICORE_DTYPE_SUPPORT_LIST = {
29- op::DataType::DT_INT4, op::DataType::DT_INT8};29+ op::DataType::DT_INT4, op::DataType::DT_INT8, op::DataType::DT_HIFLOAT8, op::DataType::DT_FLOAT8_E5M2,
30+ op::DataType::DT_FLOAT8_E4M3FN};
30 31 
31// 根据芯片类型、dtype判断算子是否支持走aicore32// 根据芯片类型、dtype判断算子是否支持走aicore
32static inline bool IsAiCoreSupport(const aclTensor* self)33static inline bool IsAiCoreSupport(const aclTensor* self)
Mquant/ascend_anti_quant_v2/op_host/op_api/ascend_anti_quant_v2.h+1-1文件内容审核中,请稍后刷新重试
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_common.h+143-0
@@ -0,0 +1,143 @@
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 ascend_anti_quant_v2_common.h
13+ * \brief ascendantiquantv2 kernel base
14+ */
15+ 
16+#ifndef QUANTIZE_H
17+#define QUANTIZE_H
18+ 
19+#include "kernel_operator.h"
20+#include "kernel_operator_intf.h"
21+ 
22+namespace AscendAntiQuantV2 {
23+using namespace AscendC;
24+/**
25+ * \brief Type mapping helper
26+ */
27+ 
28+__aicore__ inline constexpr uint32_t GetUbBlockSize()
29+{
30+ return 32U;
31+}
32+ 
33+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
34+class AscendAntiQuantV2Base {
35+public:
36+ __aicore__ inline AscendAntiQuantV2Base(){};
37+ 
38+protected:
39+ __aicore__ inline void GetXInCopyParams(
40+ int64_t dim1, int64_t baseLen, int64_t xN, int64_t xLen, DataCopyExtParams& copyParams);
41+ __aicore__ inline void GetOutCopyParams(
42+ int64_t dim1, int64_t baseLen, int64_t yN, int64_t yLen, DataCopyExtParams& copyParams);
43+ __aicore__ inline int64_t CeilAlign(int64_t i, int64_t align);
44+ 
45+protected:
46+ constexpr static int32_t BLOCK_SIZE = GetUbBlockSize();
47+ constexpr static int64_t INT4_NUMS_IN_INT8_SPACE = 2;
48+ constexpr static uint8_t MULTI_COPY_DIM = 2;
49+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
50+ 
51+protected:
52+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_INT8_TO_HALF = {
53+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::UNKNOWN,
54+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::UNKNOWN};
55+ 
56+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_HALF_TO_FP32 = {
57+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::UNKNOWN,
58+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::UNKNOWN};
59+ 
60+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_BF16_TO_FP32 = {
61+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::UNKNOWN,
62+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::UNKNOWN};
63+ 
64+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_HIFP8_TO_FP32 = {
65+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::UNKNOWN,
66+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::UNKNOWN};
67+ 
68+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_FP8E5M2_TO_FP32 = {
69+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::UNKNOWN,
70+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::UNKNOWN};
71+ 
72+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_FP8E4M3_TO_FP32 = {
73+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::UNKNOWN,
74+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::UNKNOWN};
75+ 
76+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_FP32_TO_HALF = {
77+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::NO_SAT,
78+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::CAST_RINT};
79+ 
80+ constexpr static AscendC::Reg::CastTrait CAST_TRAIT_FP32_TO_BF16 = {
81+ AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::NO_SAT,
82+ AscendC::Reg::MaskMergeMode::ZEROING, RoundMode::CAST_RINT};
83+};
84+ 
85+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
86+__aicore__ inline int64_t AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CeilAlign(int64_t i, int64_t align)
87+{
88+ if (align == 0) {
89+ return i;
90+ }
91+ return (i + align - 1) / align * align;
92+}
93+ 
94+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
95+__aicore__ inline void AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::GetOutCopyParams(
96+ int64_t dim1, int64_t baseLen, int64_t yN, int64_t yLen, DataCopyExtParams& copyParams)
97+{
98+ copyParams.blockCount = yN;
99+ copyParams.blockLen = yLen * sizeof(U);
100+ if (dim1 > yLen) {
101+ copyParams.dstStride = (dim1 - yLen) * sizeof(U);
102+ } else {
103+ copyParams.dstStride = 0;
104+ }
105+ if (baseLen > yLen) {
106+ copyParams.srcStride = (baseLen - yLen) * sizeof(U) / BLOCK_SIZE;
107+ } else {
108+ copyParams.srcStride = 0;
109+ }
110+ copyParams.rsv = 0;
111+}
112+ 
113+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
114+__aicore__ inline void AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::GetXInCopyParams(
115+ int64_t dim1, int64_t baseLen, int64_t xN, int64_t xLen, DataCopyExtParams& copyParams)
116+{
117+ int64_t xLenReal = xLen;
118+ if constexpr (IsSameType<T, int4b_t>::value) {
119+ xLenReal = xLenReal / INT4_NUMS_IN_INT8_SPACE;
120+ copyParams.blockLen = xLenReal * sizeof(xCopyDtype);
121+ } else {
122+ copyParams.blockLen = xLenReal * sizeof(T);
123+ }
124+ copyParams.blockCount = xN;
125+ if (dim1 > xLen) {
126+ if constexpr (IsSameType<T, int4b_t>::value) {
127+ copyParams.srcStride = (dim1 - xLen) * sizeof(xCopyDtype) / INT4_NUMS_IN_INT8_SPACE;
128+ } else {
129+ copyParams.srcStride = (dim1 - xLen) * sizeof(T);
130+ }
131+ } else {
132+ copyParams.srcStride = 0;
133+ }
134+ if (baseLen > xLenReal) {
135+ copyParams.dstStride = (baseLen - xLenReal) * sizeof(xCopyDtype) / BLOCK_SIZE;
136+ } else {
137+ copyParams.dstStride = 0;
138+ }
139+}
140+ 
141+} // namespace AscendAntiQuantV2
142+ 
143+#endif
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_channel_nddma_no_offset_regbase.h+337-0
@@ -0,0 +1,337 @@
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 ascend_anti_quant_v2_per_channel_nddma_no_offset_regbase.h
13+ * \brief ascend_anti_quant_v2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_CHANNEL_NDDMA_NO_OFFSET_REGBASE_H_
17+#define ASCEND_ANTI_QUANT_V2_PER_CHANNEL_NDDMA_NO_OFFSET_REGBASE_H_
18+ 
19+#include "kernel_tiling/kernel_tiling.h"
20+#include "../inc/platform.h"
21+#include "../inc/kernel_utils.h"
22+#include "ascend_anti_quant_v2_common.h"
23+ 
24+namespace AscendAntiQuantV2 {
25+using namespace AscendC;
26+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
27+class AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
28+public:
29+ __aicore__ inline AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase(const AscendAntiQuantV2TilingData* tilingData)
30+ : tilingData_(tilingData){};
31+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
32+ __aicore__ inline void Process();
33+ 
34+private:
35+ __aicore__ inline void CopyXAndCompute(int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal);
36+ __aicore__ inline void CopyInScale(int64_t sLen, int64_t sInOffset);
37+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
38+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
39+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal);
40+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen);
41+ 
42+private:
43+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
44+ constexpr static int32_t bufferNum_ = 2;
45+ TPipe pipe_;
46+ TQue<QuePosition::VECIN, bufferNum_> inQueueX_;
47+ TQue<QuePosition::VECIN, bufferNum_> inQueueScale_;
48+ TQue<QuePosition::VECOUT, bufferNum_> outQueueY_;
49+ GlobalTensor<uint8_t> xGm_;
50+ GlobalTensor<T1> scaleGm_;
51+ GlobalTensor<U> yGm_;
52+ 
53+ const AscendAntiQuantV2TilingData* tilingData_;
54+ int32_t blockIdx_ = 0;
55+ int64_t gmXOffset_ = 0;
56+ int64_t gmSOffset_ = 0;
57+ int64_t blockN_ = 1;
58+ int64_t blockLen_ = 1;
59+};
60+ 
61+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
62+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Init(
63+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
64+{
65+ blockIdx_ = GetBlockIdx();
66+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
67+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
68+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
69+ 
70+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockLen_);
71+ 
72+ // calc n size to alloc queue
73+ pipe_.InitBuffer(
74+ inQueueX_, bufferNum_, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype), this->BLOCK_SIZE));
75+ pipe_.InitBuffer(
76+ inQueueScale_, bufferNum_,
77+ this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(T1), this->BLOCK_SIZE));
78+ 
79+ pipe_.InitBuffer(
80+ outQueueY_, bufferNum_, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(U), this->BLOCK_SIZE));
81+}
82+ 
83+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
84+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Process()
85+{
86+ if (blockIdx_ >= tilingData_->numCore) {
87+ return;
88+ }
89+ if (tilingData_->blockAxis == 0) {
90+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1;
91+ gmSOffset_ = 0;
92+ } else {
93+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor;
94+ gmSOffset_ = blockIdx_ * tilingData_->blockFactor;
95+ }
96+ 
97+ // main loop with column, for scale and offset only need copy once
98+ int64_t lenLoopNum = blockLen_ / tilingData_->baseLen;
99+ int64_t lenLoopTail = blockLen_ % tilingData_->baseLen;
100+ for (int64_t i = 0; i < lenLoopNum; ++i) {
101+ CopyInScale(tilingData_->baseLen, gmSOffset_ + i * tilingData_->baseLen);
102+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
103+ CopyXAndCompute(tilingData_->baseLen, gmXOffset_ + i * tilingData_->baseLen, sLocal);
104+ inQueueScale_.FreeTensor(sLocal);
105+ }
106+ if (lenLoopTail != 0) {
107+ CopyInScale(lenLoopTail, gmSOffset_ + lenLoopNum * tilingData_->baseLen);
108+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
109+ CopyXAndCompute(lenLoopTail, gmXOffset_ + lenLoopNum * tilingData_->baseLen, sLocal);
110+ inQueueScale_.FreeTensor(sLocal);
111+ }
112+}
113+ 
114+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
115+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
116+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen)
117+{
118+ if (tilingData->blockAxis == 0) {
119+ if (blockIdx == tilingData->numCore - 1) {
120+ blockN = tilingData->blockTailFactor;
121+ } else {
122+ blockN = tilingData->blockFactor;
123+ }
124+ blockLen = tilingData->dim1;
125+ } else if (tilingData->blockAxis == 1) {
126+ blockN = tilingData->dim0;
127+ if (blockIdx == tilingData->numCore - 1) {
128+ blockLen = tilingData->blockTailFactor;
129+ } else {
130+ blockLen = tilingData->blockFactor;
131+ }
132+ }
133+}
134+ 
135+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
136+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInScale(
137+ int64_t sLen, int64_t sInOffset)
138+{
139+ LocalTensor<T1> sLocal = inQueueScale_.AllocTensor<T1>();
140+ static constexpr AscendC::MultiCopyConfig copyConfig = {false, 0, 0, false};
141+ MultiCopyLoopInfo<AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> copyLoopInfo;
142+ copyLoopInfo.loopSrcStride[0] = 1;
143+ copyLoopInfo.loopSrcStride[1] = 0;
144+ copyLoopInfo.loopDstStride[0] = 1;
145+ copyLoopInfo.loopDstStride[1] = sLen;
146+ copyLoopInfo.loopSize[0] = sLen;
147+ copyLoopInfo.loopSize[1] = tilingData_->baseN;
148+ 
149+ T1 constValue = 0;
150+ AscendC::MultiCopyParams<T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> copyParams =
151+ {copyLoopInfo, constValue};
152+ AscendC::DataCopy<T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM, copyConfig>(
153+ sLocal, scaleGm_[sInOffset], copyParams);
154+ inQueueScale_.EnQue(sLocal);
155+}
156+ 
157+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
158+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyXAndCompute(
159+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal)
160+{
161+ int64_t nLoopNum = blockN_ / tilingData_->baseN;
162+ int64_t nLoopTail = blockN_ % tilingData_->baseN;
163+ int64_t xOffset = offset;
164+ for (int64_t nIdx = 0; nIdx < nLoopNum; ++nIdx) {
165+ xOffset = offset + nIdx * tilingData_->baseN * tilingData_->dim1;
166+ CopyInX(tilingData_->baseN, dataCount, xOffset);
167+ Compute(tilingData_->baseN, dataCount, sLocal);
168+ CopyOutY(tilingData_->baseN, dataCount, xOffset);
169+ }
170+ if (nLoopTail != 0) {
171+ xOffset = offset + nLoopNum * tilingData_->baseN * tilingData_->dim1;
172+ CopyInX(nLoopTail, dataCount, xOffset);
173+ Compute(nLoopTail, dataCount, sLocal);
174+ CopyOutY(nLoopTail, dataCount, xOffset);
175+ }
176+}
177+ 
178+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
179+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
180+ int64_t xN, int64_t xLen, int64_t xInOffset)
181+{
182+ int64_t xLenReal = xLen;
183+ if constexpr (IsSameType<T, int4b_t>::value) {
184+ xInOffset = xInOffset / this->INT4_NUMS_IN_INT8_SPACE;
185+ xLenReal = xLenReal / this-> INT4_NUMS_IN_INT8_SPACE;
186+ }
187+ 
188+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
189+ DataCopyExtParams copyParams;
190+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
191+ copyParams.blockCount = 1;
192+ copyParams.blockLen = xN * xLenReal * sizeof(xCopyDtype);
193+ copyParams.dstStride = 0;
194+ copyParams.srcStride = 0;
195+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
196+ inQueueX_.EnQue(xLocal);
197+}
198+ 
199+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
200+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Compute(
201+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal)
202+{
203+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
204+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
205+ 
206+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
207+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
208+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
209+ 
210+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
211+ uint16_t HalfVL = VL / 2;
212+ 
213+ // has offset
214+ __VEC_SCOPE__
215+ {
216+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
217+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
218+ AscendC::Reg::RegTensor<half> vregHalfX;
219+ AscendC::Reg::RegTensor<float> vregFloatX;
220+ // scales: fp32, bf16
221+ AscendC::Reg::RegTensor<T1> vregS;
222+ AscendC::Reg::RegTensor<float> vregFloatS;
223+ // y: fp16, bf16
224+ AscendC::Reg::RegTensor<float> vregFloatY;
225+ AscendC::Reg::RegTensor<U> vregY;
226+ 
227+ AscendC::Reg::MaskReg mask;
228+ 
229+ mask = AscendC::Reg::CreateMask<float>();
230+ uint32_t count = dataCount * nRow;
231+ uint16_t vfLoopNum = (count + VL - 1) / VL;
232+ for (uint16_t i = 0; i < vfLoopNum; i++) {
233+ mask = AscendC::Reg::UpdateMask<float>(count);
234+ // ld and cast for x
235+ if constexpr (IsSameType<T, hifloat8_t>::value) {
236+ // hifp8
237+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
238+ vregX, xLocalAddr + i * VL);
239+ AscendC::Reg::Cast<
240+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
241+ vregFloatX, vregX, mask);
242+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
243+ // fp8_e5m2
244+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
245+ vregX, xLocalAddr + i * VL);
246+ AscendC::Reg::Cast<
247+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
248+ vregFloatX, vregX, mask);
249+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
250+ // fp8_e4m3
251+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
252+ vregX, xLocalAddr + i * VL);
253+ AscendC::Reg::Cast<
254+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
255+ vregFloatX, vregX, mask);
256+ } else if constexpr (IsSameType<T, int8_t>::value) {
257+ // int8
258+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
259+ vregX, xLocalAddr + i * VL);
260+ AscendC::Reg::Cast<
261+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
262+ vregHalfX, vregX, mask);
263+ AscendC::Reg::Cast<
264+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
265+ vregFloatX, vregHalfX, mask);
266+ } else if constexpr (IsSameType<T, int4b_t>::value) {
267+ // int4
268+ AscendC::Reg::RegTensor<half> vregTmpX;
269+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
270+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
271+ vregX, xLocalAddr + i * HalfVL);
272+ AscendC::Reg::Cast<
273+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
274+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
275+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
276+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
277+ AscendC::Reg::Cast<
278+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
279+ vregFloatX, vregTmpX, mask);
280+ }
281+ 
282+ // ld and cast for scale
283+ if constexpr (IsSameType<T1, float>::value) {
284+ // fp32
285+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
286+ vregFloatS, scaleLocalAddr + i * VL);
287+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
288+ // bf16
289+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregS, scaleLocalAddr + i * VL);
290+ AscendC::Reg::Cast<
291+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
292+ vregFloatS, vregS, mask);
293+ }
294+ 
295+ // compute
296+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
297+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
298+ }
299+ AscendC::Reg::Mul(vregFloatY, vregFloatX, vregFloatS, mask);
300+ 
301+ // cast and sd for y
302+ if constexpr (IsSameType<U, half>::value) {
303+ // fp16
304+ AscendC::Reg::Cast<
305+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
306+ vregY, vregFloatY, mask);
307+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
308+ outLocalAddr + i * VL, vregY, mask);
309+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
310+ // bf16
311+ AscendC::Reg::Cast<
312+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
313+ vregY, vregFloatY, mask);
314+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
315+ outLocalAddr + i * VL, vregY, mask);
316+ }
317+ }
318+ }
319+ inQueueX_.FreeTensor(xLocal);
320+ outQueueY_.EnQue(outLocal);
321+}
322+ 
323+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
324+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
325+ int64_t yN, int64_t yLen, int64_t yOutOffset)
326+{
327+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
328+ DataCopyExtParams copyParams;
329+ copyParams.blockCount = 1;
330+ copyParams.blockLen = yN * yLen * sizeof(U);
331+ copyParams.dstStride = 0;
332+ copyParams.srcStride = 0;
333+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
334+ outQueueY_.FreeTensor(outLocal);
335+}
336+} // namespace AscendAntiQuantV2
337+#endif
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_channel_nddma_regbase.h+392-0
@@ -0,0 +1,392 @@
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 ascend_anti_quant_v2_per_channel_nddma_regbase.h
13+ * \brief ascend_anti_quant_v2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_CHANNEL_NDDMA_REGBASE_H_
17+#define ASCEND_ANTI_QUANT_V2_PER_CHANNEL_NDDMA_REGBASE_H_
18+ 
19+#include "kernel_tiling/kernel_tiling.h"
20+#include "../inc/platform.h"
21+#include "../inc/kernel_utils.h"
22+#include "ascend_anti_quant_v2_common.h"
23+ 
24+namespace AscendAntiQuantV2 {
25+using namespace AscendC;
26+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
27+class AscendAntiQuantV2PerChannelNddmaRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
28+public:
29+ __aicore__ inline AscendAntiQuantV2PerChannelNddmaRegbase(const AscendAntiQuantV2TilingData* tilingData)
30+ : tilingData_(tilingData){};
31+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
32+ __aicore__ inline void Process();
33+ 
34+private:
35+ __aicore__ inline void CopyXAndCompute(
36+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
37+ __aicore__ inline void CopyInScale(int64_t sLen, int64_t sInOffset);
38+ __aicore__ inline void CopyInOffset(int64_t sLen, int64_t sInOffset);
39+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
40+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
41+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
42+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen);
43+ 
44+private:
45+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
46+ constexpr static int32_t bufferNum_ = 2;
47+ TPipe pipe_;
48+ TQue<QuePosition::VECIN, bufferNum_> inQueueX_;
49+ TQue<QuePosition::VECIN, bufferNum_> inQueueScale_;
50+ TQue<QuePosition::VECIN, bufferNum_> inQueueOffset_;
51+ TQue<QuePosition::VECOUT, bufferNum_> outQueueY_;
52+ GlobalTensor<uint8_t> xGm_;
53+ GlobalTensor<T1> scaleGm_;
54+ GlobalTensor<T2> offsetGm_;
55+ GlobalTensor<U> yGm_;
56+ 
57+ const AscendAntiQuantV2TilingData* tilingData_;
58+ int32_t blockIdx_ = 0;
59+ int64_t gmXOffset_ = 0;
60+ int64_t gmSOffset_ = 0;
61+ int64_t blockN_ = 1;
62+ int64_t blockLen_ = 1;
63+};
64+ 
65+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
66+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::Init(
67+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
68+{
69+ blockIdx_ = GetBlockIdx();
70+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
71+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
72+ offsetGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T2*>(offset));
73+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
74+ 
75+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockLen_);
76+ 
77+ // calc n size to alloc queue
78+ pipe_.InitBuffer(
79+ inQueueX_, bufferNum_, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype), this->BLOCK_SIZE));
80+ pipe_.InitBuffer(
81+ inQueueScale_, bufferNum_,
82+ this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(T1), this->BLOCK_SIZE));
83+ pipe_.InitBuffer(
84+ inQueueOffset_, bufferNum_,
85+ this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(T2), this->BLOCK_SIZE));
86+ 
87+ pipe_.InitBuffer(
88+ outQueueY_, bufferNum_, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(U), this->BLOCK_SIZE));
89+}
90+ 
91+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
92+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::Process()
93+{
94+ if (blockIdx_ >= tilingData_->numCore) {
95+ return;
96+ }
97+ if (tilingData_->blockAxis == 0) {
98+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1;
99+ gmSOffset_ = 0;
100+ } else {
101+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor;
102+ gmSOffset_ = blockIdx_ * tilingData_->blockFactor;
103+ }
104+ 
105+ // main loop with column, for scale and offset only need copy once
106+ int64_t lenLoopNum = blockLen_ / tilingData_->baseLen;
107+ int64_t lenLoopTail = blockLen_ % tilingData_->baseLen;
108+ for (int64_t i = 0; i < lenLoopNum; ++i) {
109+ CopyInScale(tilingData_->baseLen, gmSOffset_ + i * tilingData_->baseLen);
110+ CopyInOffset(tilingData_->baseLen, gmSOffset_ + i * tilingData_->baseLen);
111+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
112+ LocalTensor<T2> oLocal = inQueueOffset_.DeQue<T2>();
113+ CopyXAndCompute(tilingData_->baseLen, gmXOffset_ + i * tilingData_->baseLen, sLocal, oLocal);
114+ inQueueScale_.FreeTensor(sLocal);
115+ inQueueOffset_.FreeTensor(oLocal);
116+ }
117+ if (lenLoopTail != 0) {
118+ CopyInScale(lenLoopTail, gmSOffset_ + lenLoopNum * tilingData_->baseLen);
119+ CopyInOffset(lenLoopTail, gmSOffset_ + lenLoopNum * tilingData_->baseLen);
120+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
121+ LocalTensor<T2> oLocal = inQueueOffset_.DeQue<T2>();
122+ CopyXAndCompute(lenLoopTail, gmXOffset_ + lenLoopNum * tilingData_->baseLen, sLocal, oLocal);
123+ inQueueScale_.FreeTensor(sLocal);
124+ inQueueOffset_.FreeTensor(oLocal);
125+ }
126+}
127+ 
128+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
129+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
130+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen)
131+{
132+ if (tilingData->blockAxis == 0) {
133+ if (blockIdx == tilingData->numCore - 1) {
134+ blockN = tilingData->blockTailFactor;
135+ } else {
136+ blockN = tilingData->blockFactor;
137+ }
138+ blockLen = tilingData->dim1;
139+ } else if (tilingData->blockAxis == 1) {
140+ blockN = tilingData->dim0;
141+ if (blockIdx == tilingData->numCore - 1) {
142+ blockLen = tilingData->blockTailFactor;
143+ } else {
144+ blockLen = tilingData->blockFactor;
145+ }
146+ }
147+}
148+ 
149+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
150+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyInScale(
151+ int64_t sLen, int64_t sInOffset)
152+{
153+ LocalTensor<T1> sLocal = inQueueScale_.AllocTensor<T1>();
154+ static constexpr AscendC::MultiCopyConfig copyConfig = {false, 0, 0, false};
155+ MultiCopyLoopInfo<AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> copyLoopInfo;
156+ copyLoopInfo.loopSrcStride[0] = 1;
157+ copyLoopInfo.loopSrcStride[1] = 0;
158+ copyLoopInfo.loopDstStride[0] = 1;
159+ copyLoopInfo.loopDstStride[1] = sLen;
160+ copyLoopInfo.loopSize[0] = sLen;
161+ copyLoopInfo.loopSize[1] = tilingData_->baseN;
162+ 
163+ T1 constValue = 0;
164+ AscendC::MultiCopyParams<T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> copyParams =
165+ {copyLoopInfo, constValue};
166+ AscendC::DataCopy<T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM, copyConfig>(
167+ sLocal, scaleGm_[sInOffset], copyParams);
168+ inQueueScale_.EnQue(sLocal);
169+}
170+ 
171+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
172+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyInOffset(
173+ int64_t sLen, int64_t sInOffset)
174+{
175+ LocalTensor<T2> oLocal = inQueueOffset_.AllocTensor<T2>();
176+ static constexpr AscendC::MultiCopyConfig copyConfig = {false, 0, 0, false};
177+ MultiCopyLoopInfo<AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> copyLoopInfo;
178+ copyLoopInfo.loopSrcStride[0] = 1;
179+ copyLoopInfo.loopSrcStride[1] = 0;
180+ copyLoopInfo.loopDstStride[0] = 1;
181+ copyLoopInfo.loopDstStride[1] = sLen;
182+ copyLoopInfo.loopSize[0] = sLen;
183+ copyLoopInfo.loopSize[1] = tilingData_->baseN;
184+ 
185+ T2 constValue = 0;
186+ AscendC::MultiCopyParams<T2, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> copyParams =
187+ {copyLoopInfo, constValue};
188+ AscendC::DataCopy<T2, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM, copyConfig>(
189+ oLocal, offsetGm_[sInOffset], copyParams);
190+ inQueueOffset_.EnQue(oLocal);
191+}
192+ 
193+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
194+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyXAndCompute(
195+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
196+{
197+ int64_t nLoopNum = blockN_ / tilingData_->baseN;
198+ int64_t nLoopTail = blockN_ % tilingData_->baseN;
199+ int64_t xOffset = offset;
200+ for (int64_t nIdx = 0; nIdx < nLoopNum; ++nIdx) {
201+ xOffset = offset + nIdx * tilingData_->baseN * tilingData_->dim1;
202+ CopyInX(tilingData_->baseN, dataCount, xOffset);
203+ Compute(tilingData_->baseN, dataCount, sLocal, oLocal);
204+ CopyOutY(tilingData_->baseN, dataCount, xOffset);
205+ }
206+ if (nLoopTail != 0) {
207+ xOffset = offset + nLoopNum * tilingData_->baseN * tilingData_->dim1;
208+ CopyInX(nLoopTail, dataCount, xOffset);
209+ Compute(nLoopTail, dataCount, sLocal, oLocal);
210+ CopyOutY(nLoopTail, dataCount, xOffset);
211+ }
212+}
213+ 
214+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
215+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
216+ int64_t xN, int64_t xLen, int64_t xInOffset)
217+{
218+ int64_t xLenReal = xLen;
219+ if constexpr (IsSameType<T, int4b_t>::value) {
220+ xInOffset = xInOffset / this->INT4_NUMS_IN_INT8_SPACE;
221+ xLenReal = xLenReal / this-> INT4_NUMS_IN_INT8_SPACE;
222+ }
223+ 
224+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
225+ DataCopyExtParams copyParams;
226+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
227+ copyParams.blockCount = 1;
228+ copyParams.blockLen = xN * xLenReal * sizeof(xCopyDtype);
229+ copyParams.dstStride = 0;
230+ copyParams.srcStride = 0;
231+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
232+ inQueueX_.EnQue(xLocal);
233+}
234+ 
235+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
236+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::Compute(
237+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
238+{
239+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
240+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
241+ 
242+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
243+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
244+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
245+ 
246+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
247+ uint16_t HalfVL = VL / 2;
248+ __local_mem__ T2* offsetLocalAddr = (__local_mem__ T2*)oLocal.GetPhyAddr();
249+ 
250+ // has offset
251+ __VEC_SCOPE__
252+ {
253+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
254+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
255+ AscendC::Reg::RegTensor<half> vregHalfX;
256+ AscendC::Reg::RegTensor<float> vregFloatX;
257+ // scales: fp32, bf16
258+ AscendC::Reg::RegTensor<T1> vregS;
259+ AscendC::Reg::RegTensor<float> vregFloatS;
260+ // offset: fp32, bf16
261+ AscendC::Reg::RegTensor<T2> vregO;
262+ AscendC::Reg::RegTensor<float> vregFloatO;
263+ // y: fp16, bf16
264+ AscendC::Reg::RegTensor<float> vregFloatY;
265+ AscendC::Reg::RegTensor<U> vregY;
266+ 
267+ AscendC::Reg::RegTensor<float> vregTmp1;
268+ AscendC::Reg::MaskReg mask;
269+ 
270+ mask = AscendC::Reg::CreateMask<float>();
271+ uint32_t count = dataCount * nRow;
272+ uint16_t vfLoopNum = (count + VL - 1) / VL;
273+ for (uint16_t i = 0; i < vfLoopNum; i++) {
274+ mask = AscendC::Reg::UpdateMask<float>(count);
275+ // ld and cast for x
276+ if constexpr (IsSameType<T, hifloat8_t>::value) {
277+ // hifp8
278+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
279+ vregX, xLocalAddr + i * VL);
280+ AscendC::Reg::Cast<
281+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
282+ vregFloatX, vregX, mask);
283+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
284+ // fp8_e5m2
285+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
286+ vregX, xLocalAddr + i * VL);
287+ AscendC::Reg::Cast<
288+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
289+ vregFloatX, vregX, mask);
290+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
291+ // fp8_e4m3
292+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
293+ vregX, xLocalAddr + i * VL);
294+ AscendC::Reg::Cast<
295+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
296+ vregFloatX, vregX, mask);
297+ } else if constexpr (IsSameType<T, int8_t>::value) {
298+ // int8
299+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
300+ vregX, xLocalAddr + i * VL);
301+ AscendC::Reg::Cast<
302+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
303+ vregHalfX, vregX, mask);
304+ AscendC::Reg::Cast<
305+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
306+ vregFloatX, vregHalfX, mask);
307+ } else if constexpr (IsSameType<T, int4b_t>::value) {
308+ // int4
309+ AscendC::Reg::RegTensor<half> vregTmpX;
310+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
311+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
312+ vregX, xLocalAddr + i * HalfVL);
313+ AscendC::Reg::Cast<
314+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
315+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
316+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
317+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
318+ AscendC::Reg::Cast<
319+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
320+ vregFloatX, vregTmpX, mask);
321+ }
322+ 
323+ // ld and cast for scale
324+ if constexpr (IsSameType<T1, float>::value) {
325+ // fp32
326+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
327+ vregFloatS, scaleLocalAddr + i * VL);
328+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
329+ // bf16
330+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregS, scaleLocalAddr + i * VL);
331+ AscendC::Reg::Cast<
332+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
333+ vregFloatS, vregS, mask);
334+ }
335+ 
336+ // ld and cast for offset
337+ if constexpr (IsSameType<T2, float>::value) {
338+ // fp32
339+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
340+ vregFloatO, offsetLocalAddr + i * VL);
341+ } else if constexpr (IsSameType<T2, bfloat16_t>::value) {
342+ // bf16
343+ AscendC::Reg::DataCopy<T2, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregO, offsetLocalAddr + i * VL);
344+ AscendC::Reg::Cast<
345+ float, T2, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
346+ vregFloatO, vregO, mask);
347+ }
348+ 
349+ // compute
350+ AscendC::Reg::Add<float, AscendC::Reg::MaskMergeMode::ZEROING>(vregTmp1, vregFloatX, vregFloatO, mask);
351+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
352+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
353+ }
354+ AscendC::Reg::Mul(vregFloatY, vregTmp1, vregFloatS, mask);
355+ 
356+ // cast and sd for y
357+ if constexpr (IsSameType<U, half>::value) {
358+ // fp16
359+ AscendC::Reg::Cast<
360+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
361+ vregY, vregFloatY, mask);
362+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
363+ outLocalAddr + i * VL, vregY, mask);
364+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
365+ // bf16
366+ AscendC::Reg::Cast<
367+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
368+ vregY, vregFloatY, mask);
369+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
370+ outLocalAddr + i * VL, vregY, mask);
371+ }
372+ }
373+ }
374+ inQueueX_.FreeTensor(xLocal);
375+ outQueueY_.EnQue(outLocal);
376+}
377+ 
378+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
379+__aicore__ inline void AscendAntiQuantV2PerChannelNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
380+ int64_t yN, int64_t yLen, int64_t yOutOffset)
381+{
382+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
383+ DataCopyExtParams copyParams;
384+ copyParams.blockCount = 1;
385+ copyParams.blockLen = yN * yLen * sizeof(U);
386+ copyParams.dstStride = 0;
387+ copyParams.srcStride = 0;
388+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
389+ outQueueY_.FreeTensor(outLocal);
390+}
391+} // namespace AscendAntiQuantV2
392+#endif
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_channel_no_offset_regbase.h+323-0
@@ -0,0 +1,323 @@
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 ascend_anti_quant_v2_per_channel_no_offset_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_CHANNEL_NO_OFFSET_REGBASE_H_
17+#define ASCEND_ANTI_QUANT_V2_PER_CHANNEL_NO_OFFSET_REGBASE_H_
18+ 
19+ 
20+#include "kernel_tiling/kernel_tiling.h"
21+#include "../inc/platform.h"
22+#include "../inc/kernel_utils.h"
23+#include "ascend_anti_quant_v2_common.h"
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerChannelNoOffsetRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerChannelNoOffsetRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ __aicore__ inline void CopyXAndCompute(int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal);
37+ __aicore__ inline void CopyInScale(int64_t sLen, int64_t sInOffset);
38+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen);
39+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
40+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
41+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal);
42+ 
43+private:
44+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
45+ constexpr static int32_t bufferNum_ = 2;
46+ TPipe pipe_;
47+ TQue<QuePosition::VECIN, bufferNum_> inQueueX_;
48+ TQue<QuePosition::VECIN, bufferNum_> inQueueScale_;
49+ TQue<QuePosition::VECOUT, bufferNum_> outQueueY_;
50+ GlobalTensor<uint8_t> xGm_;
51+ GlobalTensor<T1> scaleGm_;
52+ GlobalTensor<U> yGm_;
53+ 
54+ const AscendAntiQuantV2TilingData* tilingData_;
55+ int32_t blockIdx_ = 0;
56+ int64_t gmXOffset_ = 0;
57+ int64_t gmSOffset_ = 0;
58+ int64_t blockN_ = 1;
59+ int64_t blockLen_ = 1;
60+};
61+ 
62+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
63+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Init(
64+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
65+{
66+ blockIdx_ = GetBlockIdx();
67+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
68+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
69+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
70+ 
71+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockLen_);
72+ 
73+ // calc n size to alloc queue
74+ pipe_.InitBuffer(inQueueX_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype));
75+ pipe_.InitBuffer(inQueueScale_, bufferNum_, tilingData_->baseLen * sizeof(T1));
76+ 
77+ pipe_.InitBuffer(outQueueY_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(U));
78+}
79+ 
80+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
81+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Process()
82+{
83+ if (blockIdx_ >= tilingData_->numCore) {
84+ return;
85+ }
86+ if (tilingData_->blockAxis == 0) {
87+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1;
88+ gmSOffset_ = 0;
89+ } else {
90+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor;
91+ gmSOffset_ = blockIdx_ * tilingData_->blockFactor;
92+ }
93+ 
94+ // main loop with column, for scale and offset only need copy once
95+ int64_t lenLoopNum = blockLen_ / tilingData_->baseLen;
96+ int64_t lenLoopTail = blockLen_ % tilingData_->baseLen;
97+ for (int64_t i = 0; i < lenLoopNum; ++i) {
98+ CopyInScale(tilingData_->baseLen, gmSOffset_ + i * tilingData_->baseLen);
99+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
100+ CopyXAndCompute(tilingData_->baseLen, gmXOffset_ + i * tilingData_->baseLen, sLocal);
101+ inQueueScale_.FreeTensor(sLocal);
102+ }
103+ if (lenLoopTail != 0) {
104+ CopyInScale(lenLoopTail, gmSOffset_ + lenLoopNum * tilingData_->baseLen);
105+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
106+ CopyXAndCompute(lenLoopTail, gmXOffset_ + lenLoopNum * tilingData_->baseLen, sLocal);
107+ inQueueScale_.FreeTensor(sLocal);
108+ }
109+}
110+ 
111+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
112+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
113+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen)
114+{
115+ if (tilingData->blockAxis == 0) {
116+ if (blockIdx == tilingData->numCore - 1) {
117+ blockN = tilingData->blockTailFactor;
118+ } else {
119+ blockN = tilingData->blockFactor;
120+ }
121+ blockLen = tilingData->dim1;
122+ } else if (tilingData->blockAxis == 1) {
123+ blockN = tilingData->dim0;
124+ if (blockIdx == tilingData->numCore - 1) {
125+ blockLen = tilingData->blockTailFactor;
126+ } else {
127+ blockLen = tilingData->blockFactor;
128+ }
129+ }
130+}
131+ 
132+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
133+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInScale(
134+ int64_t sLen, int64_t sInOffset)
135+{
136+ DataCopyExtParams copyParams;
137+ copyParams.blockCount = 1;
138+ copyParams.blockLen = sLen * sizeof(T1);
139+ copyParams.dstStride = 0;
140+ copyParams.srcStride = 0;
141+ copyParams.rsv = 0;
142+ LocalTensor<T1> sLocal = inQueueScale_.AllocTensor<T1>();
143+ DataCopyPad(sLocal, scaleGm_[sInOffset], copyParams, {false, 0, 0, 0});
144+ inQueueScale_.EnQue(sLocal);
145+}
146+ 
147+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
148+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyXAndCompute(
149+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal)
150+{
151+ int64_t nLoopNum = blockN_ / tilingData_->baseN;
152+ int64_t nLoopTail = blockN_ % tilingData_->baseN;
153+ int64_t xOffset = offset;
154+ for (int64_t nIdx = 0; nIdx < nLoopNum; ++nIdx) {
155+ xOffset = offset + nIdx * tilingData_->baseN * tilingData_->dim1;
156+ CopyInX(tilingData_->baseN, dataCount, xOffset);
157+ Compute(tilingData_->baseN, dataCount, sLocal);
158+ CopyOutY(tilingData_->baseN, dataCount, xOffset);
159+ }
160+ if (nLoopTail != 0) {
161+ xOffset = offset + nLoopNum * tilingData_->baseN * tilingData_->dim1;
162+ CopyInX(nLoopTail, dataCount, xOffset);
163+ Compute(nLoopTail, dataCount, sLocal);
164+ CopyOutY(nLoopTail, dataCount, xOffset);
165+ }
166+}
167+ 
168+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
169+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
170+ int64_t xN, int64_t xLen, int64_t xInOffset)
171+{
172+ if constexpr (IsSameType<T, int4b_t>::value) {
173+ xInOffset = xInOffset >> 1;
174+ }
175+
176+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
177+ DataCopyExtParams copyParams;
178+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
179+ this->GetXInCopyParams(tilingData_->dim1, tilingData_->baseLen, xN, xLen, copyParams);
180+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
181+ inQueueX_.EnQue(xLocal);
182+}
183+ 
184+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
185+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Compute(
186+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal)
187+{
188+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
189+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
190+ 
191+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
192+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
193+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
194+ 
195+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
196+ uint16_t HalfVL = VL / 2;
197+ uint16_t vfLoopNum = (dataCount + VL - 1) / VL;
198+ 
199+ uint32_t xLocalOffset = static_cast<uint32_t>(tilingData_->baseLen);
200+ 
201+ // has offset
202+ __VEC_SCOPE__
203+ {
204+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
205+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
206+ AscendC::Reg::RegTensor<half> vregHalfX;
207+ AscendC::Reg::RegTensor<float> vregFloatX;
208+ // scales: fp32, bf16
209+ AscendC::Reg::RegTensor<T1> vregS;
210+ AscendC::Reg::RegTensor<float> vregFloatS;
211+ // y: fp16, bf16
212+ AscendC::Reg::RegTensor<float> vregFloatY;
213+ AscendC::Reg::RegTensor<U> vregY;
214+ 
215+ AscendC::Reg::MaskReg mask;
216+ 
217+ mask = AscendC::Reg::CreateMask<float>();
218+ for (uint16_t j = 0; j < static_cast<uint16_t>(nRow); ++j) {
219+ uint32_t count = dataCount;
220+ for (uint16_t i = 0; i < vfLoopNum; i++) {
221+ mask = AscendC::Reg::UpdateMask<float>(count);
222+ // ld and cast for x
223+ if constexpr (IsSameType<T, hifloat8_t>::value) {
224+ // hifp8
225+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
226+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
227+ AscendC::Reg::Cast<
228+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
229+ vregFloatX, vregX, mask);
230+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
231+ // fp8_e5m2
232+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
233+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
234+ AscendC::Reg::Cast<
235+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
236+ vregFloatX, vregX, mask);
237+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
238+ // fp8_e4m3
239+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
240+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
241+ AscendC::Reg::Cast<
242+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
243+ vregFloatX, vregX, mask);
244+ } else if constexpr (IsSameType<T, int8_t>::value) {
245+ // int8
246+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
247+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
248+ AscendC::Reg::Cast<
249+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
250+ vregHalfX, vregX, mask);
251+ AscendC::Reg::Cast<
252+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
253+ vregFloatX, vregHalfX, mask);
254+ } else if constexpr (IsSameType<T, int4b_t>::value) {
255+ // int4
256+ AscendC::Reg::RegTensor<half> vregTmpX;
257+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
258+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
259+ vregX, xLocalAddr + i * HalfVL + j * xLocalOffset);
260+ AscendC::Reg::Cast<
261+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
262+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
263+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
264+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
265+ AscendC::Reg::Cast<
266+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
267+ vregFloatX, vregTmpX, mask);
268+ }
269+ 
270+ // ld and cast for scale
271+ if constexpr (IsSameType<T1, float>::value) {
272+ // fp32
273+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
274+ vregFloatS, scaleLocalAddr + i * VL);
275+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
276+ // bf16
277+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregS, scaleLocalAddr + i * VL);
278+ AscendC::Reg::Cast<
279+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
280+ vregFloatS, vregS, mask);
281+ }
282+ 
283+ // compute
284+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
285+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
286+ }
287+ AscendC::Reg::Mul(vregFloatY, vregFloatX, vregFloatS, mask);
288+ 
289+ // cast and sd for y
290+ if constexpr (IsSameType<U, half>::value) {
291+ // fp16
292+ AscendC::Reg::Cast<
293+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
294+ vregY, vregFloatY, mask);
295+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
296+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
297+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
298+ // bf16
299+ AscendC::Reg::Cast<
300+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
301+ vregY, vregFloatY, mask);
302+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
303+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
304+ }
305+ }
306+ }
307+ }
308+ inQueueX_.FreeTensor(xLocal);
309+ outQueueY_.EnQue(outLocal);
310+}
311+ 
312+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
313+__aicore__ inline void AscendAntiQuantV2PerChannelNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
314+ int64_t yN, int64_t yLen, int64_t yOutOffset)
315+{
316+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
317+ DataCopyExtParams copyParams;
318+ this->GetOutCopyParams(tilingData_->dim1, tilingData_->baseLen, yN, yLen, copyParams);
319+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
320+ outQueueY_.FreeTensor(outLocal);
321+}
322+} // namespace AscendAntiQuantV2
323+#endif
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_channel_regbase.h+369-0
@@ -0,0 +1,369 @@
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 ascend_anti_quant_v2_per_channel_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_CHANNEL_REGBASE_H_
17+#define ASCEND_ANTI_QUANT_V2_PER_CHANNEL_REGBASE_H_
18+ 
19+ 
20+#include "kernel_tiling/kernel_tiling.h"
21+#include "../inc/platform.h"
22+#include "../inc/kernel_utils.h"
23+#include "ascend_anti_quant_v2_common.h"
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerChannelRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerChannelRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ __aicore__ inline void CopyXAndCompute(
37+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
38+ __aicore__ inline void CopyInScale(int64_t sLen, int64_t sInOffset);
39+ __aicore__ inline void CopyInOffset(int64_t sLen, int64_t sInOffset);
40+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen);
41+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
42+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
43+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
44+ 
45+private:
46+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
47+ constexpr static int32_t bufferNum_ = 2;
48+ TPipe pipe_;
49+ TQue<QuePosition::VECIN, bufferNum_> inQueueX_;
50+ TQue<QuePosition::VECIN, bufferNum_> inQueueScale_;
51+ TQue<QuePosition::VECIN, bufferNum_> inQueueOffset_;
52+ TQue<QuePosition::VECOUT, bufferNum_> outQueueY_;
53+ GlobalTensor<uint8_t> xGm_;
54+ GlobalTensor<T1> scaleGm_;
55+ GlobalTensor<T2> offsetGm_;
56+ GlobalTensor<U> yGm_;
57+ 
58+ const AscendAntiQuantV2TilingData* tilingData_;
59+ int32_t blockIdx_ = 0;
60+ int64_t gmXOffset_ = 0;
61+ int64_t gmSOffset_ = 0;
62+ int64_t blockN_ = 1;
63+ int64_t blockLen_ = 1;
64+};
65+ 
66+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
67+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::Init(
68+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
69+{
70+ blockIdx_ = GetBlockIdx();
71+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
72+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
73+ offsetGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T2*>(offset));
74+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
75+ 
76+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockLen_);
77+ 
78+ // calc n size to alloc queue
79+ pipe_.InitBuffer(inQueueX_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype));
80+ pipe_.InitBuffer(inQueueScale_, bufferNum_, tilingData_->baseLen * sizeof(T1));
81+ pipe_.InitBuffer(inQueueOffset_, bufferNum_, tilingData_->baseLen * sizeof(T2));
82+ 
83+ pipe_.InitBuffer(outQueueY_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(U));
84+}
85+ 
86+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
87+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::Process()
88+{
89+ if (blockIdx_ >= tilingData_->numCore) {
90+ return;
91+ }
92+ if (tilingData_->blockAxis == 0) {
93+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1;
94+ gmSOffset_ = 0;
95+ } else {
96+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor;
97+ gmSOffset_ = blockIdx_ * tilingData_->blockFactor;
98+ }
99+ 
100+ // main loop with column, for scale and offset only need copy once
101+ int64_t lenLoopNum = blockLen_ / tilingData_->baseLen;
102+ int64_t lenLoopTail = blockLen_ % tilingData_->baseLen;
103+ for (int64_t i = 0; i < lenLoopNum; ++i) {
104+ CopyInScale(tilingData_->baseLen, gmSOffset_ + i * tilingData_->baseLen);
105+ CopyInOffset(tilingData_->baseLen, gmSOffset_ + i * tilingData_->baseLen);
106+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
107+ LocalTensor<T2> oLocal = inQueueOffset_.DeQue<T2>();
108+ CopyXAndCompute(tilingData_->baseLen, gmXOffset_ + i * tilingData_->baseLen, sLocal, oLocal);
109+ inQueueScale_.FreeTensor(sLocal);
110+ inQueueOffset_.FreeTensor(oLocal);
111+ }
112+ if (lenLoopTail != 0) {
113+ CopyInScale(lenLoopTail, gmSOffset_ + lenLoopNum * tilingData_->baseLen);
114+ CopyInOffset(lenLoopTail, gmSOffset_ + lenLoopNum * tilingData_->baseLen);
115+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
116+ LocalTensor<T2> oLocal = inQueueOffset_.DeQue<T2>();
117+ CopyXAndCompute(lenLoopTail, gmXOffset_ + lenLoopNum * tilingData_->baseLen, sLocal, oLocal);
118+ inQueueScale_.FreeTensor(sLocal);
119+ inQueueOffset_.FreeTensor(oLocal);
120+ }
121+}
122+ 
123+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
124+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
125+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockLen)
126+{
127+ if (tilingData->blockAxis == 0) {
128+ if (blockIdx == tilingData->numCore - 1) {
129+ blockN = tilingData->blockTailFactor;
130+ } else {
131+ blockN = tilingData->blockFactor;
132+ }
133+ blockLen = tilingData->dim1;
134+ } else if (tilingData->blockAxis == 1) {
135+ blockN = tilingData->dim0;
136+ if (blockIdx == tilingData->numCore - 1) {
137+ blockLen = tilingData->blockTailFactor;
138+ } else {
139+ blockLen = tilingData->blockFactor;
140+ }
141+ }
142+}
143+ 
144+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
145+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::CopyInScale(
146+ int64_t sLen, int64_t sInOffset)
147+{
148+ DataCopyExtParams copyParams;
149+ copyParams.blockCount = 1;
150+ copyParams.blockLen = sLen * sizeof(T1);
151+ copyParams.dstStride = 0;
152+ copyParams.srcStride = 0;
153+ copyParams.rsv = 0;
154+ LocalTensor<T1> sLocal = inQueueScale_.AllocTensor<T1>();
155+ DataCopyPad(sLocal, scaleGm_[sInOffset], copyParams, {false, 0, 0, 0});
156+ inQueueScale_.EnQue(sLocal);
157+}
158+ 
159+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
160+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::CopyInOffset(
161+ int64_t sLen, int64_t sInOffset)
162+{
163+ DataCopyExtParams copyParams;
164+ copyParams.blockCount = 1;
165+ copyParams.blockLen = sLen * sizeof(T2);
166+ copyParams.dstStride = 0;
167+ copyParams.srcStride = 0;
168+ copyParams.rsv = 0;
169+ LocalTensor<T2> oLocal = inQueueOffset_.AllocTensor<T2>();
170+ DataCopyPad(oLocal, offsetGm_[sInOffset], copyParams, {false, 0, 0, 0});
171+ inQueueOffset_.EnQue(oLocal);
172+}
173+ 
174+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
175+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::CopyXAndCompute(
176+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
177+{
178+ int64_t nLoopNum = blockN_ / tilingData_->baseN;
179+ int64_t nLoopTail = blockN_ % tilingData_->baseN;
180+ int64_t xOffset = offset;
181+ for (int64_t nIdx = 0; nIdx < nLoopNum; ++nIdx) {
182+ xOffset = offset + nIdx * tilingData_->baseN * tilingData_->dim1;
183+ CopyInX(tilingData_->baseN, dataCount, xOffset);
184+ Compute(tilingData_->baseN, dataCount, sLocal, oLocal);
185+ CopyOutY(tilingData_->baseN, dataCount, xOffset);
186+ }
187+ if (nLoopTail != 0) {
188+ xOffset = offset + nLoopNum * tilingData_->baseN * tilingData_->dim1;
189+ CopyInX(nLoopTail, dataCount, xOffset);
190+ Compute(nLoopTail, dataCount, sLocal, oLocal);
191+ CopyOutY(nLoopTail, dataCount, xOffset);
192+ }
193+}
194+ 
195+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
196+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
197+ int64_t xN, int64_t xLen, int64_t xInOffset)
198+{
199+ if constexpr (IsSameType<T, int4b_t>::value) {
200+ xInOffset = xInOffset >> 1;
201+ }
202+
203+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
204+ DataCopyExtParams copyParams;
205+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
206+ this->GetXInCopyParams(tilingData_->dim1, tilingData_->baseLen, xN, xLen, copyParams);
207+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
208+ inQueueX_.EnQue(xLocal);
209+}
210+ 
211+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
212+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::Compute(
213+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
214+{
215+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
216+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
217+ 
218+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
219+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
220+ __local_mem__ T2* offsetLocalAddr = (__local_mem__ T2*)oLocal.GetPhyAddr();
221+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
222+ 
223+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
224+ uint16_t HalfVL = VL / 2;
225+ uint16_t vfLoopNum = (dataCount + VL - 1) / VL;
226+ 
227+ uint32_t xLocalOffset = static_cast<uint32_t>(tilingData_->baseLen);
228+ 
229+ // has offset
230+ __VEC_SCOPE__
231+ {
232+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
233+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
234+ AscendC::Reg::RegTensor<half> vregHalfX;
235+ AscendC::Reg::RegTensor<float> vregFloatX;
236+ // scales: fp32, bf16
237+ AscendC::Reg::RegTensor<T1> vregS;
238+ AscendC::Reg::RegTensor<float> vregFloatS;
239+ // offset: fp32, bf16
240+ AscendC::Reg::RegTensor<T2> vregO;
241+ AscendC::Reg::RegTensor<float> vregFloatO;
242+ // y: fp16, bf16
243+ AscendC::Reg::RegTensor<float> vregFloatY;
244+ AscendC::Reg::RegTensor<U> vregY;
245+ 
246+ AscendC::Reg::RegTensor<float> vregTmp1;
247+ AscendC::Reg::MaskReg mask;
248+ 
249+ mask = AscendC::Reg::CreateMask<float>();
250+ for (uint16_t j = 0; j < static_cast<uint16_t>(nRow); ++j) {
251+ uint32_t count = dataCount;
252+ for (uint16_t i = 0; i < vfLoopNum; i++) {
253+ mask = AscendC::Reg::UpdateMask<float>(count);
254+ // ld and cast for x
255+ if constexpr (IsSameType<T, hifloat8_t>::value) {
256+ // hifp8
257+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
258+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
259+ AscendC::Reg::Cast<
260+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
261+ vregFloatX, vregX, mask);
262+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
263+ // fp8_e5m2
264+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
265+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
266+ AscendC::Reg::Cast<
267+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
268+ vregFloatX, vregX, mask);
269+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
270+ // fp8_e4m3
271+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
272+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
273+ AscendC::Reg::Cast<
274+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
275+ vregFloatX, vregX, mask);
276+ } else if constexpr (IsSameType<T, int8_t>::value) {
277+ // int8
278+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
279+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
280+ AscendC::Reg::Cast<
281+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
282+ vregHalfX, vregX, mask);
283+ AscendC::Reg::Cast<
284+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
285+ vregFloatX, vregHalfX, mask);
286+ } else if constexpr (IsSameType<T, int4b_t>::value) {
287+ // int4
288+ AscendC::Reg::RegTensor<half> vregTmpX;
289+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
290+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
291+ vregX, xLocalAddr + i * HalfVL + j * xLocalOffset);
292+ AscendC::Reg::Cast<
293+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
294+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
295+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
296+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
297+ AscendC::Reg::Cast<
298+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
299+ vregFloatX, vregTmpX, mask);
300+ }
301+ 
302+ // ld and cast for scale
303+ if constexpr (IsSameType<T1, float>::value) {
304+ // fp32
305+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
306+ vregFloatS, scaleLocalAddr + i * VL);
307+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
308+ // bf16
309+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregS, scaleLocalAddr + i * VL);
310+ AscendC::Reg::Cast<
311+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
312+ vregFloatS, vregS, mask);
313+ }
314+ 
315+ // ld and cast for offset
316+ if constexpr (IsSameType<T2, float>::value) {
317+ // fp32
318+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
319+ vregFloatO, offsetLocalAddr + i * VL);
320+ } else if constexpr (IsSameType<T2, bfloat16_t>::value) {
321+ // bf16
322+ AscendC::Reg::DataCopy<T2, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregO, offsetLocalAddr + i * VL);
323+ AscendC::Reg::Cast<
324+ float, T2, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
325+ vregFloatO, vregO, mask);
326+ }
327+ 
328+ // compute
329+ AscendC::Reg::Add<float, AscendC::Reg::MaskMergeMode::ZEROING>(vregTmp1, vregFloatX, vregFloatO, mask);
330+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
331+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
332+ }
333+ AscendC::Reg::Mul(vregFloatY, vregTmp1, vregFloatS, mask);
334+ 
335+ // cast and sd for y
336+ if constexpr (IsSameType<U, half>::value) {
337+ // fp16
338+ AscendC::Reg::Cast<
339+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
340+ vregY, vregFloatY, mask);
341+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
342+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
343+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
344+ // bf16
345+ AscendC::Reg::Cast<
346+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
347+ vregY, vregFloatY, mask);
348+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
349+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
350+ }
351+ }
352+ }
353+ }
354+ inQueueX_.FreeTensor(xLocal);
355+ outQueueY_.EnQue(outLocal);
356+}
357+ 
358+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
359+__aicore__ inline void AscendAntiQuantV2PerChannelRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
360+ int64_t yN, int64_t yLen, int64_t yOutOffset)
361+{
362+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
363+ DataCopyExtParams copyParams;
364+ this->GetOutCopyParams(tilingData_->dim1, tilingData_->baseLen, yN, yLen, copyParams);
365+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
366+ outQueueY_.FreeTensor(outLocal);
367+}
368+} // namespace AscendAntiQuantV2
369+#endif
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_head_nddma_no_offset_regbase.h+372-0
@@ -0,0 +1,372 @@
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 ascend_anti_quant_v2_per_head_nddma_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_HEAD_NDDMA_NO_OFFSET_REGBASE_H
17+#define ASCEND_ANTI_QUANT_V2_PER_HEAD_NDDMA_NO_OFFSET_REGBASE_H
18+ 
19+#include "kernel_tiling/kernel_tiling.h"
20+#include "../inc/platform.h"
21+#include "../inc/kernel_utils.h"
22+#include "ascend_anti_quant_v2_common.h"
23+ 
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
37+ TPipe pipe_;
38+ constexpr static int32_t bufferNum = 2;
39+ TQue<QuePosition::VECIN, bufferNum> inQueueX_;
40+ TQue<QuePosition::VECIN, bufferNum> inQueueScale_;
41+ TQue<QuePosition::VECOUT, bufferNum> outQueueY_;
42+ GlobalTensor<uint8_t> xGm_;
43+ GlobalTensor<T1> scaleGm_;
44+ GlobalTensor<U> yGm_;
45+ 
46+ const AscendAntiQuantV2TilingData* tilingData_;
47+ int32_t blockIdx_ = 0;
48+ int64_t gmXOffset_ = 0;
49+ int64_t gmSOffset_ = 0;
50+ int64_t blockN_ = 1;
51+ int64_t blockLen_ = 1;
52+ int64_t blockS_ = 1;
53+ int64_t nLoopLen = 0;
54+ int64_t nLoopNum = 0;
55+ int64_t nLoopTail = 0;
56+ int64_t loopLen = 0;
57+ int64_t lenLoopNum = 0;
58+ int64_t lenLoopTail = 0;
59+ 
60+private:
61+ __aicore__ inline void ProcessInputLoop(int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal);
62+ __aicore__ inline void CopyInParam(
63+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<T1>& inGm, int64_t paramLen, int64_t paramOffset);
64+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen);
65+ __aicore__ inline void ProcessParamOneLoop(int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset);
66+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
67+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
68+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal);
69+};
70+ 
71+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
72+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Init(
73+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
74+{
75+ blockIdx_ = GetBlockIdx();
76+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
77+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
78+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
79+ 
80+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockS_, blockLen_);
81+ 
82+ // calc n size to alloc queue
83+ pipe_.InitBuffer(
84+ inQueueX_, bufferNum, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype), this->BLOCK_SIZE));
85+ pipe_.InitBuffer(
86+ inQueueScale_, bufferNum,
87+ this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(T1), this->BLOCK_SIZE));
88+ 
89+ pipe_.InitBuffer(
90+ outQueueY_, bufferNum, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(U), this->BLOCK_SIZE));
91+}
92+ 
93+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
94+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Process()
95+{
96+ if (blockIdx_ >= tilingData_->numCore || blockN_ == 0) {
97+ return;
98+ }
99+ if (tilingData_->blockAxis == 0) {
100+ // only split axis 0
101+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1 * tilingData_->dim2;
102+ gmSOffset_ = 0;
103+ } else {
104+ // only split axis 1, blockUnion means factor per block on split axis
105+ gmXOffset_ = blockIdx_ / tilingData_->blockUnion * tilingData_->dim1 * tilingData_->dim2 +
106+ blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor * tilingData_->dim2;
107+ gmSOffset_ = blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor;
108+ }
109+ 
110+ nLoopLen = tilingData_->baseN;
111+ nLoopNum = blockN_ / nLoopLen;
112+ nLoopTail = blockN_ % nLoopLen;
113+ 
114+ loopLen = tilingData_->baseLen;
115+ lenLoopNum = blockLen_ / loopLen;
116+ lenLoopTail = blockLen_ % loopLen;
117+ 
118+ for (int64_t i = 0; i < blockS_; ++i) {
119+ // scale allows start from begin on each core
120+ int64_t baseSOffset = gmSOffset_;
121+ int64_t baseXOffset = gmXOffset_;
122+ 
123+ for (int64_t i = 0; i < nLoopNum; ++i) {
124+ ProcessParamOneLoop(nLoopLen, baseSOffset, baseXOffset);
125+ baseXOffset += nLoopLen * tilingData_->dim2;
126+ baseSOffset += tilingData_->baseN;
127+ }
128+ if (nLoopTail != 0) {
129+ ProcessParamOneLoop(nLoopTail, baseSOffset, baseXOffset);
130+ }
131+ gmXOffset_ += tilingData_->dim1 * tilingData_->dim2;
132+ }
133+}
134+ 
135+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
136+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ProcessParamOneLoop(int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset)
137+{
138+ // copy in scale
139+ CopyInParam(inQueueScale_, scaleGm_, nLoopLen, baseSOffset % tilingData_->dim1);
140+ auto scaleLocal = inQueueScale_.DeQue<T1>();
141+ ProcessInputLoop(nLoopLen, baseXOffset, scaleLocal);
142+ 
143+ inQueueScale_.FreeTensor(scaleLocal);
144+}
145+ 
146+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
147+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInParam(
148+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<T1>& inGm, int64_t paramLen,
149+ int64_t paramOffset)
150+{
151+ auto paramLocal = inQueue.AllocTensor<T1>();
152+ static constexpr AscendC::MultiCopyConfig copyConfig = {false, 0, 0, false};
153+ MultiCopyLoopInfo<AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> multiCopyParams;
154+ // src stride info per loop.
155+ multiCopyParams.loopSrcStride[0] = 0;
156+ multiCopyParams.loopSrcStride[1] = 1;
157+ // dst stride info per loop.
158+ multiCopyParams.loopDstStride[0] = 1;
159+ multiCopyParams.loopDstStride[1] = tilingData_->baseLen;
160+ // Loop size per loop.
161+ multiCopyParams.loopSize[0] = tilingData_->baseLen;
162+ multiCopyParams.loopSize[1] = paramLen;
163+ T1 constValue = 0;
164+ AscendC::MultiCopyParams<T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM>
165+ paramsMain = {multiCopyParams, constValue};
166+ AscendC::DataCopy<
167+ T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM, copyConfig>(
168+ paramLocal, inGm[paramOffset], paramsMain);
169+ inQueue.EnQue(paramLocal);
170+}
171+ 
172+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
173+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
174+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen)
175+{
176+ if (tilingData->blockAxis == 0) {
177+ // blockFactor is in [1, S]
178+ if (blockIdx == tilingData->numCore - 1) {
179+ blockS = tilingData->blockTailFactor;
180+ } else {
181+ blockS = tilingData->blockFactor;
182+ }
183+ blockN = tilingData->dim1;
184+ blockLen = tilingData->dim2;
185+ } else {
186+ // blockFactor is in [1, N], blockUnion is in [1, N/blockFactor]
187+ if (blockIdx % tilingData->blockUnion == tilingData->blockUnion - 1) {
188+ blockN = tilingData->blockTailFactor;
189+ } else {
190+ blockN = tilingData->blockFactor;
191+ }
192+ blockLen = tilingData->dim2;
193+ }
194+}
195+ 
196+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
197+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ProcessInputLoop(
198+ int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal)
199+{
200+ for (auto i = 0; i < lenLoopNum; ++i) {
201+ CopyInX(nLoopLen, loopLen, baseXOffset);
202+ Compute(nLoopLen, loopLen, scaleLocal);
203+ CopyOutY(nLoopLen, loopLen, baseXOffset);
204+ baseXOffset += tilingData_->baseLen;
205+ }
206+ if (lenLoopTail != 0) {
207+ CopyInX(nLoopLen, lenLoopTail, baseXOffset);
208+ Compute(nLoopLen, lenLoopTail, scaleLocal);
209+ CopyOutY(nLoopLen, lenLoopTail, baseXOffset);
210+ }
211+}
212+ 
213+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
214+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
215+ int64_t xN, int64_t xLen, int64_t xInOffset)
216+{
217+ int64_t xLenReal = xLen;
218+ if constexpr (IsSameType<T, int4b_t>::value) {
219+ xInOffset = xInOffset >> 1;
220+ xLenReal = xLenReal >> 1;
221+ }
222+ 
223+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
224+ DataCopyExtParams copyParams;
225+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
226+ copyParams.blockCount = 1;
227+ copyParams.blockLen = xN * xLenReal * sizeof(xCopyDtype);
228+ copyParams.dstStride = 0;
229+ copyParams.srcStride = 0;
230+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
231+ inQueueX_.EnQue(xLocal);
232+}
233+ 
234+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
235+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Compute(
236+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal)
237+{
238+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
239+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
240+ 
241+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
242+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
243+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
244+ 
245+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
246+ uint16_t HalfVL = VL / 2;
247+ 
248+ // has offset
249+ __VEC_SCOPE__
250+ {
251+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
252+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
253+ AscendC::Reg::RegTensor<half> vregHalfX;
254+ AscendC::Reg::RegTensor<float> vregFloatX;
255+ // scales: fp32, bf16
256+ AscendC::Reg::RegTensor<T1> vregS;
257+ AscendC::Reg::RegTensor<float> vregFloatS;
258+ // y: fp16, bf16
259+ AscendC::Reg::RegTensor<float> vregFloatY;
260+ AscendC::Reg::RegTensor<U> vregY;
261+ 
262+ AscendC::Reg::MaskReg mask;
263+ 
264+ mask = AscendC::Reg::CreateMask<float>();
265+ uint32_t count = dataCount * nRow;
266+ uint16_t vfLoopNum = (count + VL - 1) / VL;
267+ for (uint16_t i = 0; i < vfLoopNum; i++) {
268+ mask = AscendC::Reg::UpdateMask<float>(count);
269+ // ld and cast for x
270+ if constexpr (IsSameType<T, hifloat8_t>::value) {
271+ // hifp8
272+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
273+ vregX, xLocalAddr + i * VL);
274+ AscendC::Reg::Cast<
275+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
276+ vregFloatX, vregX, mask);
277+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
278+ // fp8_e5m2
279+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
280+ vregX, xLocalAddr + i * VL);
281+ AscendC::Reg::Cast<
282+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
283+ vregFloatX, vregX, mask);
284+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
285+ // fp8_e4m3
286+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
287+ vregX, xLocalAddr + i * VL);
288+ AscendC::Reg::Cast<
289+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
290+ vregFloatX, vregX, mask);
291+ } else if constexpr (IsSameType<T, int8_t>::value) {
292+ // int8
293+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
294+ vregX, xLocalAddr + i * VL);
295+ AscendC::Reg::Cast<
296+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
297+ vregHalfX, vregX, mask);
298+ AscendC::Reg::Cast<
299+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
300+ vregFloatX, vregHalfX, mask);
301+ } else if constexpr (IsSameType<T, int4b_t>::value) {
302+ // int4
303+ AscendC::Reg::RegTensor<half> vregTmpX;
304+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
305+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
306+ vregX, xLocalAddr + i * HalfVL);
307+ AscendC::Reg::Cast<
308+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
309+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
310+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
311+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
312+ AscendC::Reg::Cast<
313+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
314+ vregFloatX, vregTmpX, mask);
315+ }
316+ 
317+ // ld and cast for scale
318+ if constexpr (IsSameType<T1, float>::value) {
319+ // fp32
320+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
321+ vregFloatS, scaleLocalAddr + i * VL);
322+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
323+ // bf16
324+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregS, scaleLocalAddr + i * VL);
325+ AscendC::Reg::Cast<
326+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
327+ vregFloatS, vregS, mask);
328+ }
329+ 
330+ // compute
331+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
332+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
333+ }
334+ AscendC::Reg::Mul(vregFloatY, vregFloatX, vregFloatS, mask);
335+ 
336+ // cast and sd for y
337+ if constexpr (IsSameType<U, half>::value) {
338+ // fp16
339+ AscendC::Reg::Cast<
340+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
341+ vregY, vregFloatY, mask);
342+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
343+ outLocalAddr + i * VL, vregY, mask);
344+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
345+ // bf16
346+ AscendC::Reg::Cast<
347+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
348+ vregY, vregFloatY, mask);
349+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
350+ outLocalAddr + i * VL, vregY, mask);
351+ }
352+ }
353+ }
354+ inQueueX_.FreeTensor(xLocal);
355+ outQueueY_.EnQue(outLocal);
356+}
357+ 
358+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
359+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
360+ int64_t yN, int64_t yLen, int64_t yOutOffset)
361+{
362+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
363+ DataCopyExtParams copyParams;
364+ copyParams.blockCount = 1;
365+ copyParams.blockLen = yN * yLen * sizeof(U);
366+ copyParams.dstStride = 0;
367+ copyParams.srcStride = 0;
368+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
369+ outQueueY_.FreeTensor(outLocal);
370+}
371+} // namespace AscendAntiQuantV2
372+#endif //ASCEND_ANTI_QUANT_V2_PER_HEAD_NDDMA_NO_OFFSET_REGBASE_H
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_head_nddma_regbase.h+403-0
@@ -0,0 +1,403 @@
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 ascend_anti_quant_v2_per_head_nddma_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_HEAD_NDDMA_REGBASE_H
17+#define ASCEND_ANTI_QUANT_V2_PER_HEAD_NDDMA_REGBASE_H
18+ 
19+#include "kernel_tiling/kernel_tiling.h"
20+#include "../inc/platform.h"
21+#include "../inc/kernel_utils.h"
22+#include "ascend_anti_quant_v2_common.h"
23+ 
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerHeadNddmaRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerHeadNddmaRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
37+ TPipe pipe_;
38+ constexpr static int32_t bufferNum = 2;
39+ TQue<QuePosition::VECIN, bufferNum> inQueueX_;
40+ TQue<QuePosition::VECIN, bufferNum> inQueueScale_;
41+ TQue<QuePosition::VECIN, bufferNum> inQueueOffset_;
42+ TQue<QuePosition::VECOUT, bufferNum> outQueueY_;
43+ GlobalTensor<uint8_t> xGm_;
44+ GlobalTensor<T1> scaleGm_;
45+ GlobalTensor<T2> offsetGm_;
46+ GlobalTensor<U> yGm_;
47+ 
48+ const AscendAntiQuantV2TilingData* tilingData_;
49+ int32_t blockIdx_ = 0;
50+ int64_t gmXOffset_ = 0;
51+ int64_t gmSOffset_ = 0;
52+ int64_t blockN_ = 1;
53+ int64_t blockLen_ = 1;
54+ int64_t blockS_ = 1;
55+ int64_t nLoopLen = 0;
56+ int64_t nLoopNum = 0;
57+ int64_t nLoopTail = 0;
58+ int64_t loopLen = 0;
59+ int64_t lenLoopNum = 0;
60+ int64_t lenLoopTail = 0;
61+ 
62+private:
63+ __aicore__ inline void ProcessInputLoop(
64+ int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal, LocalTensor<T2>& offsetLocal);
65+ template <typename dtypeCopyIn>
66+ __aicore__ inline void CopyInParam(
67+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<dtypeCopyIn>& inGm, int64_t paramLen, int64_t paramOffset);
68+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen);
69+ __aicore__ inline void ProcessParamOneLoop(int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset);
70+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
71+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
72+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
73+};
74+ 
75+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
76+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::Init(
77+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
78+{
79+ blockIdx_ = GetBlockIdx();
80+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
81+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
82+ offsetGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T2*>(offset));
83+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
84+ 
85+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockS_, blockLen_);
86+ 
87+ // calc n size to alloc queue
88+ pipe_.InitBuffer(
89+ inQueueX_, bufferNum, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype), this->BLOCK_SIZE));
90+ pipe_.InitBuffer(
91+ inQueueScale_, bufferNum,
92+ this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(T1), this->BLOCK_SIZE));
93+ pipe_.InitBuffer(
94+ inQueueOffset_, bufferNum,
95+ this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(T2), this->BLOCK_SIZE));
96+ 
97+ pipe_.InitBuffer(
98+ outQueueY_, bufferNum, this->CeilAlign(tilingData_->baseN * tilingData_->baseLen * sizeof(U), this->BLOCK_SIZE));
99+}
100+ 
101+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
102+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::Process()
103+{
104+ if (blockIdx_ >= tilingData_->numCore || blockN_ == 0) {
105+ return;
106+ }
107+ if (tilingData_->blockAxis == 0) {
108+ // only split axis 0
109+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1 * tilingData_->dim2;
110+ gmSOffset_ = 0;
111+ } else {
112+ // only split axis 1, blockUnion means factor per block on split axis
113+ gmXOffset_ = blockIdx_ / tilingData_->blockUnion * tilingData_->dim1 * tilingData_->dim2 +
114+ blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor * tilingData_->dim2;
115+ gmSOffset_ = blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor;
116+ }
117+ 
118+ nLoopLen = tilingData_->baseN;
119+ nLoopNum = blockN_ / nLoopLen;
120+ nLoopTail = blockN_ % nLoopLen;
121+ 
122+ loopLen = tilingData_->baseLen;
123+ lenLoopNum = blockLen_ / loopLen;
124+ lenLoopTail = blockLen_ % loopLen;
125+ 
126+ for (int64_t i = 0; i < blockS_; ++i) {
127+ // scale allows start from begin on each core
128+ int64_t baseSOffset = gmSOffset_;
129+ int64_t baseXOffset = gmXOffset_;
130+ 
131+ for (int64_t i = 0; i < nLoopNum; ++i) {
132+ ProcessParamOneLoop(nLoopLen, baseSOffset, baseXOffset);
133+ baseXOffset += nLoopLen * tilingData_->dim2;
134+ baseSOffset += tilingData_->baseN;
135+ }
136+ if (nLoopTail != 0) {
137+ ProcessParamOneLoop(nLoopTail, baseSOffset, baseXOffset);
138+ }
139+ gmXOffset_ += tilingData_->dim1 * tilingData_->dim2;
140+ }
141+}
142+ 
143+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
144+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::ProcessParamOneLoop(int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset)
145+{
146+ // copy in scale and offset
147+ CopyInParam<T1>(inQueueScale_, scaleGm_, nLoopLen, baseSOffset % tilingData_->dim1);
148+ auto scaleLocal = inQueueScale_.DeQue<T1>();
149+ CopyInParam<T2>(inQueueOffset_, offsetGm_, nLoopLen, baseSOffset % tilingData_->dim1);
150+ auto offsetLocal = inQueueOffset_.DeQue<T2>();
151+ ProcessInputLoop(nLoopLen, baseXOffset, scaleLocal, offsetLocal);
152+ inQueueOffset_.FreeTensor(offsetLocal);
153+ 
154+ inQueueScale_.FreeTensor(scaleLocal);
155+}
156+ 
157+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
158+template <typename dtypeCopyIn>
159+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyInParam(
160+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<dtypeCopyIn>& inGm, int64_t paramLen,
161+ int64_t paramOffset)
162+{
163+ auto paramLocal = inQueue.AllocTensor<dtypeCopyIn>();
164+ static constexpr AscendC::MultiCopyConfig copyConfig = {false, 0, 0, false};
165+ MultiCopyLoopInfo<AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM> multiCopyParams;
166+ // src stride info per loop.
167+ multiCopyParams.loopSrcStride[0] = 0;
168+ multiCopyParams.loopSrcStride[1] = 1;
169+ // dst stride info per loop.
170+ multiCopyParams.loopDstStride[0] = 1;
171+ multiCopyParams.loopDstStride[1] = tilingData_->baseLen;
172+ // Loop size per loop.
173+ multiCopyParams.loopSize[0] = tilingData_->baseLen;
174+ multiCopyParams.loopSize[1] = paramLen;
175+ dtypeCopyIn constValue = 0;
176+ AscendC::MultiCopyParams<dtypeCopyIn, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM>
177+ paramsMain = {multiCopyParams, constValue};
178+ AscendC::DataCopy<
179+ dtypeCopyIn, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::MULTI_COPY_DIM, copyConfig>(
180+ paramLocal, inGm[paramOffset], paramsMain);
181+ inQueue.EnQue(paramLocal);
182+}
183+ 
184+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
185+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
186+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen)
187+{
188+ if (tilingData->blockAxis == 0) {
189+ // blockFactor is in [1, S]
190+ if (blockIdx == tilingData->numCore - 1) {
191+ blockS = tilingData->blockTailFactor;
192+ } else {
193+ blockS = tilingData->blockFactor;
194+ }
195+ blockN = tilingData->dim1;
196+ blockLen = tilingData->dim2;
197+ } else {
198+ // blockFactor is in [1, N], blockUnion is in [1, N/blockFactor]
199+ if (blockIdx % tilingData->blockUnion == tilingData->blockUnion - 1) {
200+ blockN = tilingData->blockTailFactor;
201+ } else {
202+ blockN = tilingData->blockFactor;
203+ }
204+ blockLen = tilingData->dim2;
205+ }
206+}
207+ 
208+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
209+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::ProcessInputLoop(
210+ int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal, LocalTensor<T2>& offsetLocal)
211+{
212+ for (auto i = 0; i < lenLoopNum; ++i) {
213+ CopyInX(nLoopLen, loopLen, baseXOffset);
214+ Compute(nLoopLen, loopLen, scaleLocal, offsetLocal);
215+ CopyOutY(nLoopLen, loopLen, baseXOffset);
216+ baseXOffset += tilingData_->baseLen;
217+ }
218+ if (lenLoopTail != 0) {
219+ CopyInX(nLoopLen, lenLoopTail, baseXOffset);
220+ Compute(nLoopLen, lenLoopTail, scaleLocal, offsetLocal);
221+ CopyOutY(nLoopLen, lenLoopTail, baseXOffset);
222+ }
223+}
224+ 
225+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
226+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
227+ int64_t xN, int64_t xLen, int64_t xInOffset)
228+{
229+ int64_t xLenReal = xLen;
230+ if constexpr (IsSameType<T, int4b_t>::value) {
231+ xInOffset = xInOffset >> 1;
232+ xLenReal = xLenReal >> 1;
233+ }
234+ 
235+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
236+ DataCopyExtParams copyParams;
237+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
238+ copyParams.blockCount = 1;
239+ copyParams.blockLen = xN * xLenReal * sizeof(xCopyDtype);
240+ copyParams.dstStride = 0;
241+ copyParams.srcStride = 0;
242+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
243+ inQueueX_.EnQue(xLocal);
244+}
245+ 
246+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
247+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::Compute(
248+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
249+{
250+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
251+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
252+ 
253+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
254+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
255+ __local_mem__ T2* offsetLocalAddr = (__local_mem__ T2*)oLocal.GetPhyAddr();
256+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
257+ 
258+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
259+ uint16_t HalfVL = VL / 2;
260+ 
261+ // has offset
262+ __VEC_SCOPE__
263+ {
264+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
265+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
266+ AscendC::Reg::RegTensor<half> vregHalfX;
267+ AscendC::Reg::RegTensor<float> vregFloatX;
268+ // scales: fp32, bf16
269+ AscendC::Reg::RegTensor<T1> vregS;
270+ AscendC::Reg::RegTensor<float> vregFloatS;
271+ // offset: fp32, bf16
272+ AscendC::Reg::RegTensor<T2> vregO;
273+ AscendC::Reg::RegTensor<float> vregFloatO;
274+ // y: fp16, bf16
275+ AscendC::Reg::RegTensor<float> vregFloatY;
276+ AscendC::Reg::RegTensor<U> vregY;
277+ 
278+ AscendC::Reg::RegTensor<float> vregTmp1;
279+ AscendC::Reg::MaskReg mask;
280+ 
281+ mask = AscendC::Reg::CreateMask<float>();
282+ uint32_t count = dataCount * nRow;
283+ uint16_t vfLoopNum = (count + VL - 1) / VL;
284+ for (uint16_t i = 0; i < vfLoopNum; i++) {
285+ mask = AscendC::Reg::UpdateMask<float>(count);
286+ // ld and cast for x
287+ if constexpr (IsSameType<T, hifloat8_t>::value) {
288+ // hifp8
289+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
290+ vregX, xLocalAddr + i * VL);
291+ AscendC::Reg::Cast<
292+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
293+ vregFloatX, vregX, mask);
294+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
295+ // fp8_e5m2
296+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
297+ vregX, xLocalAddr + i * VL);
298+ AscendC::Reg::Cast<
299+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
300+ vregFloatX, vregX, mask);
301+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
302+ // fp8_e4m3
303+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
304+ vregX, xLocalAddr + i * VL);
305+ AscendC::Reg::Cast<
306+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
307+ vregFloatX, vregX, mask);
308+ } else if constexpr (IsSameType<T, int8_t>::value) {
309+ // int8
310+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
311+ vregX, xLocalAddr + i * VL);
312+ AscendC::Reg::Cast<
313+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
314+ vregHalfX, vregX, mask);
315+ AscendC::Reg::Cast<
316+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
317+ vregFloatX, vregHalfX, mask);
318+ } else if constexpr (IsSameType<T, int4b_t>::value) {
319+ // int4
320+ AscendC::Reg::RegTensor<half> vregTmpX;
321+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
322+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
323+ vregX, xLocalAddr + i * HalfVL);
324+ AscendC::Reg::Cast<
325+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
326+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
327+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
328+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
329+ AscendC::Reg::Cast<
330+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
331+ vregFloatX, vregTmpX, mask);
332+ }
333+ 
334+ // ld and cast for scale
335+ if constexpr (IsSameType<T1, float>::value) {
336+ // fp32
337+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
338+ vregFloatS, scaleLocalAddr + i * VL);
339+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
340+ // bf16
341+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregS, scaleLocalAddr + i * VL);
342+ AscendC::Reg::Cast<
343+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
344+ vregFloatS, vregS, mask);
345+ }
346+ 
347+ // ld and cast for offset
348+ if constexpr (IsSameType<T2, float>::value) {
349+ // fp32
350+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_NORM>(
351+ vregFloatO, offsetLocalAddr + i * VL);
352+ } else if constexpr (IsSameType<T2, bfloat16_t>::value) {
353+ // bf16
354+ AscendC::Reg::DataCopy<T2, AscendC::Reg::LoadDist::DIST_UNPACK_B16>(vregO, offsetLocalAddr + i * VL);
355+ AscendC::Reg::Cast<
356+ float, T2, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
357+ vregFloatO, vregO, mask);
358+ }
359+ 
360+ // compute
361+ AscendC::Reg::Add<float, AscendC::Reg::MaskMergeMode::ZEROING>(vregTmp1, vregFloatX, vregFloatO, mask);
362+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
363+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
364+ }
365+ AscendC::Reg::Mul(vregFloatY, vregTmp1, vregFloatS, mask);
366+ 
367+ // cast and sd for y
368+ if constexpr (IsSameType<U, half>::value) {
369+ // fp16
370+ AscendC::Reg::Cast<
371+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
372+ vregY, vregFloatY, mask);
373+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
374+ outLocalAddr + i * VL, vregY, mask);
375+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
376+ // bf16
377+ AscendC::Reg::Cast<
378+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
379+ vregY, vregFloatY, mask);
380+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
381+ outLocalAddr + i * VL, vregY, mask);
382+ }
383+ }
384+ }
385+ inQueueX_.FreeTensor(xLocal);
386+ outQueueY_.EnQue(outLocal);
387+}
388+ 
389+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
390+__aicore__ inline void AscendAntiQuantV2PerHeadNddmaRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
391+ int64_t yN, int64_t yLen, int64_t yOutOffset)
392+{
393+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
394+ DataCopyExtParams copyParams;
395+ copyParams.blockCount = 1;
396+ copyParams.blockLen = yN * yLen * sizeof(U);
397+ copyParams.dstStride = 0;
398+ copyParams.srcStride = 0;
399+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
400+ outQueueY_.FreeTensor(outLocal);
401+}
402+} // namespace AscendAntiQuantV2
403+#endif //ASCEND_ANTI_QUANT_V2_PER_HEAD_NDDMA_REGBASE_H
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_head_no_offset_regbase.h+418-0
@@ -0,0 +1,418 @@
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 ascend_anti_quant_v2_per_head_no_offset_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_HEAD_NO_OFFSET_REGBASE_H
17+#define ASCEND_ANTI_QUANT_V2_PER_HEAD_NO_OFFSET_REGBASE_H
18+ 
19+#include "kernel_tiling/kernel_tiling.h"
20+#include "../inc/platform.h"
21+#include "../inc/kernel_utils.h"
22+#include "ascend_anti_quant_v2_common.h"
23+ 
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerHeadNoOffsetRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerHeadNoOffsetRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
37+ TPipe pipe_;
38+ constexpr static int32_t bufferNum = 2;
39+ TQue<QuePosition::VECIN, bufferNum> inQueueX_;
40+ TQue<QuePosition::VECIN, bufferNum> inQueueScale_;
41+ TQue<QuePosition::VECOUT, bufferNum> outQueueY_;
42+ GlobalTensor<uint8_t> xGm_;
43+ GlobalTensor<T1> scaleGm_;
44+ GlobalTensor<U> yGm_;
45+ 
46+ const AscendAntiQuantV2TilingData* tilingData_;
47+ int32_t blockIdx_ = 0;
48+ int64_t gmXOffset_ = 0;
49+ int64_t gmSOffset_ = 0;
50+ int64_t blockN_ = 1;
51+ int64_t blockLen_ = 1;
52+ int64_t blockS_ = 1;
53+ int64_t nLoopLen = 0;
54+ int64_t nLoopNum = 0;
55+ int64_t nLoopTail = 0;
56+ int64_t loopLen = 0;
57+ int64_t lenLoopNum = 0;
58+ int64_t lenLoopTail = 0;
59+ 
60+private:
61+ __aicore__ inline void ProcessInputLoop(int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal);
62+ __aicore__ inline void CopyInParam(
63+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<T1>& inGm, int64_t paramLen, int64_t paramOffset);
64+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen);
65+ __aicore__ inline void ProcessParamOneLoop(int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset);
66+ __aicore__ inline void GetXInCopyParams(const AscendAntiQuantV2TilingData* tilingData, int64_t xN, int64_t xLen, int64_t lastDimLen,
67+ DataCopyExtParams& copyParams);
68+ __aicore__ inline void GetOutCopyParams(const AscendAntiQuantV2TilingData* tilingData, int64_t yN, int64_t yLen, int64_t lastDimLen,
69+ DataCopyExtParams& copyParams);
70+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
71+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
72+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal);
73+};
74+ 
75+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
76+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Init(
77+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
78+{
79+ blockIdx_ = GetBlockIdx();
80+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
81+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
82+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
83+ 
84+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockS_, blockLen_);
85+ 
86+ // calc n size to alloc queue
87+ pipe_.InitBuffer(inQueueX_, bufferNum, tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype));
88+ pipe_.InitBuffer(inQueueScale_, bufferNum, tilingData_->baseN * sizeof(T1));
89+ 
90+ pipe_.InitBuffer(outQueueY_, bufferNum, tilingData_->baseN * tilingData_->baseLen * sizeof(U));
91+}
92+ 
93+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
94+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Process()
95+{
96+ if (blockIdx_ >= tilingData_->numCore || blockN_ == 0) {
97+ return;
98+ }
99+ if (tilingData_->blockAxis == 0) {
100+ // only split axis 0
101+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1 * tilingData_->dim2;
102+ gmSOffset_ = 0;
103+ } else if (tilingData_->blockAxis == 1) {
104+ // only split axis 1, blockUnion means factor per block on split axis
105+ gmXOffset_ = blockIdx_ / tilingData_->blockUnion * tilingData_->dim1 * tilingData_->dim2 +
106+ blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor * tilingData_->dim2;
107+ gmSOffset_ = blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor;
108+ } else {
109+ gmXOffset_ =
110+ (blockIdx_ / tilingData_->blockUnion * tilingData_->dim2 +
111+ blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor);
112+ gmSOffset_ = blockIdx_ / tilingData_->blockUnion;
113+ }
114+ 
115+ nLoopLen = tilingData_->baseN;
116+ nLoopNum = blockN_ / nLoopLen;
117+ nLoopTail = blockN_ % nLoopLen;
118+ 
119+ loopLen = tilingData_->baseLen;
120+ lenLoopNum = blockLen_ / loopLen;
121+ lenLoopTail = blockLen_ % loopLen;
122+ 
123+ for (int64_t i = 0; i < blockS_; ++i) {
124+ // scale allows start from begin on each core
125+ int64_t baseSOffset = gmSOffset_;
126+ int64_t baseXOffset = gmXOffset_;
127+ 
128+ for (int64_t i = 0; i < nLoopNum; ++i) {
129+ ProcessParamOneLoop(nLoopLen, baseSOffset, baseXOffset);
130+ baseXOffset += nLoopLen * tilingData_->dim2;
131+ baseSOffset += tilingData_->baseN;
132+ }
133+ if (nLoopTail != 0) {
134+ ProcessParamOneLoop(nLoopTail, baseSOffset, baseXOffset);
135+ }
136+ gmXOffset_ += tilingData_->dim1 * tilingData_->dim2;
137+ }
138+}
139+ 
140+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
141+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ProcessParamOneLoop(
142+ int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset)
143+{
144+ // copy in scale
145+ CopyInParam(inQueueScale_, scaleGm_, nLoopLen, baseSOffset % tilingData_->dim1);
146+ auto scaleLocal = inQueueScale_.DeQue<T1>();
147+ ProcessInputLoop(nLoopLen, baseXOffset, scaleLocal);
148+ 
149+ inQueueScale_.FreeTensor(scaleLocal);
150+}
151+ 
152+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
153+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInParam(
154+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<T1>& inGm, int64_t paramLen, int64_t paramOffset)
155+{
156+ auto paramLocal = inQueue.AllocTensor<T1>();
157+ DataCopyExtParams copyParams;
158+ copyParams.blockCount = 1;
159+ copyParams.blockLen = paramLen * sizeof(T1);
160+ copyParams.dstStride = 0;
161+ copyParams.srcStride = 0;
162+ copyParams.rsv = 0;
163+ DataCopyPad(paramLocal, inGm[paramOffset], copyParams, {false, 0, 0, 0});
164+ inQueue.EnQue(paramLocal);
165+}
166+ 
167+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
168+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
169+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen)
170+{
171+ if (tilingData->blockAxis == 0) {
172+ // blockFactor is in [1, S]
173+ if (blockIdx == tilingData->numCore - 1) {
174+ blockS = tilingData->blockTailFactor;
175+ } else {
176+ blockS = tilingData->blockFactor;
177+ }
178+ blockN = tilingData->dim1;
179+ blockLen = tilingData->dim2;
180+ } else if (tilingData->blockAxis == 1) {
181+ // blockFactor is in [1, N], blockUnion is in [1, N/blockFactor]
182+ if (blockIdx % tilingData->blockUnion == tilingData->blockUnion - 1) {
183+ blockN = tilingData->blockTailFactor;
184+ } else {
185+ blockN = tilingData->blockFactor;
186+ }
187+ blockLen = tilingData->dim2;
188+ } else {
189+ // blockFactor is in [1, D]
190+ blockN = 1;
191+ if (blockIdx % tilingData->blockUnion == tilingData->blockUnion - 1) {
192+ blockLen = tilingData->blockTailFactor;
193+ } else {
194+ blockLen = tilingData->blockFactor;
195+ }
196+ }
197+}
198+ 
199+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
200+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::ProcessInputLoop(
201+ int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal)
202+{
203+ for (auto i = 0; i < lenLoopNum; ++i) {
204+ CopyInX(nLoopLen, loopLen, baseXOffset);
205+ Compute(nLoopLen, loopLen, scaleLocal);
206+ CopyOutY(nLoopLen, loopLen, baseXOffset);
207+ baseXOffset += tilingData_->baseLen;
208+ }
209+ if (lenLoopTail != 0) {
210+ CopyInX(nLoopLen, lenLoopTail, baseXOffset);
211+ Compute(nLoopLen, lenLoopTail, scaleLocal);
212+ CopyOutY(nLoopLen, lenLoopTail, baseXOffset);
213+ }
214+}
215+ 
216+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
217+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::GetXInCopyParams(
218+ const AscendAntiQuantV2TilingData* tilingData, int64_t xN, int64_t xLen, int64_t lastDimLen,
219+ DataCopyExtParams& copyParams)
220+{
221+ int64_t xLenReal = xLen;
222+ if constexpr (IsSameType<T, int4b_t>::value) {
223+ xLenReal = xLenReal / this->INT4_NUMS_IN_INT8_SPACE;
224+ }
225+ 
226+ copyParams.blockCount = xN;
227+ copyParams.blockLen = xLenReal * sizeof(xCopyDtype);
228+ if (lastDimLen > xLen) {
229+ if constexpr (IsSameType<T, int4b_t>::value) {
230+ copyParams.srcStride = (lastDimLen - xLen) * sizeof(xCopyDtype) / this->INT4_NUMS_IN_INT8_SPACE;
231+ } else {
232+ copyParams.srcStride = (lastDimLen - xLen) * sizeof(xCopyDtype);
233+ }
234+ } else {
235+ copyParams.srcStride = 0;
236+ }
237+ if (tilingData->baseLen > xLenReal) {
238+ copyParams.dstStride = (tilingData->baseLen - xLenReal) * sizeof(xCopyDtype) / this->BLOCK_SIZE;
239+ } else {
240+ copyParams.dstStride = 0;
241+ }
242+}
243+ 
244+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
245+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
246+ int64_t xN, int64_t xLen, int64_t xInOffset)
247+{
248+ if constexpr (IsSameType<T, int4b_t>::value) {
249+ xInOffset = xInOffset >> 1;
250+ }
251+ 
252+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
253+ DataCopyExtParams copyParams;
254+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
255+ GetXInCopyParams(tilingData_, xN, xLen, tilingData_->dim2, copyParams);
256+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
257+ inQueueX_.EnQue(xLocal);
258+}
259+ 
260+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
261+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Compute(
262+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal)
263+{
264+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
265+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
266+ 
267+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
268+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
269+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
270+ 
271+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
272+ uint16_t HalfVL = VL / 2;
273+ uint16_t vfLoopNum = (dataCount + VL - 1) / VL;
274+ 
275+ uint32_t xLocalOffset = static_cast<uint32_t>(tilingData_->baseLen);
276+ 
277+ // has offset
278+ __VEC_SCOPE__
279+ {
280+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
281+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
282+ AscendC::Reg::RegTensor<half> vregHalfX;
283+ AscendC::Reg::RegTensor<float> vregFloatX;
284+ // scales: fp32, bf16
285+ AscendC::Reg::RegTensor<T1> vregS;
286+ AscendC::Reg::RegTensor<float> vregFloatS;
287+ // y: fp16, bf16
288+ AscendC::Reg::RegTensor<float> vregFloatY;
289+ AscendC::Reg::RegTensor<U> vregY;
290+ 
291+ AscendC::Reg::MaskReg mask;
292+ 
293+ mask = AscendC::Reg::CreateMask<float>();
294+ for (uint16_t j = 0; j < static_cast<uint16_t>(nRow); ++j) {
295+ uint32_t count = dataCount;
296+ for (uint16_t i = 0; i < vfLoopNum; i++) {
297+ mask = AscendC::Reg::UpdateMask<float>(count);
298+ // ld and cast for x
299+ if constexpr (IsSameType<T, hifloat8_t>::value) {
300+ // hifp8
301+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
302+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
303+ AscendC::Reg::Cast<
304+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
305+ vregFloatX, vregX, mask);
306+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
307+ // fp8_e5m2
308+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
309+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
310+ AscendC::Reg::Cast<
311+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
312+ vregFloatX, vregX, mask);
313+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
314+ // fp8_e4m3
315+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
316+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
317+ AscendC::Reg::Cast<
318+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
319+ vregFloatX, vregX, mask);
320+ } else if constexpr (IsSameType<T, int8_t>::value) {
321+ // int8
322+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
323+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
324+ AscendC::Reg::Cast<
325+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
326+ vregHalfX, vregX, mask);
327+ AscendC::Reg::Cast<
328+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
329+ vregFloatX, vregHalfX, mask);
330+ } else if constexpr (IsSameType<T, int4b_t>::value) {
331+ // int4
332+ AscendC::Reg::RegTensor<half> vregTmpX;
333+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
334+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
335+ vregX, xLocalAddr + i * HalfVL + j * xLocalOffset);
336+ AscendC::Reg::Cast<
337+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
338+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
339+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
340+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
341+ AscendC::Reg::Cast<
342+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
343+ vregFloatX, vregTmpX, mask);
344+ }
345+ 
346+ // ld and cast for scale
347+ if constexpr (IsSameType<T1, float>::value) {
348+ // fp32
349+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_BRC_B32>(
350+ vregFloatS, scaleLocalAddr + j);
351+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
352+ // bf16
353+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_BRC_B16>(vregS, scaleLocalAddr + j);
354+ AscendC::Reg::Cast<
355+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
356+ vregFloatS, vregS, mask);
357+ }
358+ 
359+ // compute
360+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
361+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
362+ }
363+ AscendC::Reg::Mul(vregFloatY, vregFloatX, vregFloatS, mask);
364+ 
365+ // cast and sd for y
366+ if constexpr (IsSameType<U, half>::value) {
367+ // fp16
368+ AscendC::Reg::Cast<
369+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
370+ vregY, vregFloatY, mask);
371+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
372+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
373+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
374+ // bf16
375+ AscendC::Reg::Cast<
376+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
377+ vregY, vregFloatY, mask);
378+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
379+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
380+ }
381+ }
382+ }
383+ }
384+ inQueueX_.FreeTensor(xLocal);
385+ outQueueY_.EnQue(outLocal);
386+}
387+ 
388+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
389+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::GetOutCopyParams(
390+ const AscendAntiQuantV2TilingData* tilingData, int64_t yN, int64_t yLen, int64_t lastDimLen,
391+ DataCopyExtParams& copyParams)
392+{
393+ copyParams.blockCount = yN;
394+ copyParams.blockLen = yLen * sizeof(U);
395+ if (tilingData->baseLen > yLen) {
396+ copyParams.srcStride = (tilingData->baseLen - yLen) * sizeof(U) / this->BLOCK_SIZE;
397+ } else {
398+ copyParams.srcStride = 0;
399+ }
400+ if (lastDimLen > yLen) {
401+ copyParams.dstStride = (lastDimLen - yLen) * sizeof(U);
402+ } else {
403+ copyParams.dstStride = 0;
404+ }
405+}
406+ 
407+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
408+__aicore__ inline void AscendAntiQuantV2PerHeadNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
409+ int64_t yN, int64_t yLen, int64_t yOutOffset)
410+{
411+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
412+ DataCopyExtParams copyParams;
413+ GetOutCopyParams(tilingData_, yN, yLen, tilingData_->dim2, copyParams);
414+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
415+ outQueueY_.FreeTensor(outLocal);
416+}
417+} // namespace AscendAntiQuantV2
418+#endif //ASCEND_ANTI_QUANT_V2_PER_HEAD_NO_OFFSET_REGBASE_H
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_head_regbase.h+447-0
@@ -0,0 +1,447 @@
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 ascend_anti_quant_v2_per_head_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_HEAD_REGBASE_H
17+#define ASCEND_ANTI_QUANT_V2_PER_HEAD_REGBASE_H
18+ 
19+#include "kernel_tiling/kernel_tiling.h"
20+#include "../inc/platform.h"
21+#include "../inc/kernel_utils.h"
22+#include "ascend_anti_quant_v2_common.h"
23+ 
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerHeadRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerHeadRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
37+ TPipe pipe_;
38+ constexpr static int32_t bufferNum = 2;
39+ TQue<QuePosition::VECIN, bufferNum> inQueueX_;
40+ TQue<QuePosition::VECIN, bufferNum> inQueueScale_;
41+ TQue<QuePosition::VECIN, bufferNum> inQueueOffset_;
42+ TQue<QuePosition::VECOUT, bufferNum> outQueueY_;
43+ GlobalTensor<uint8_t> xGm_;
44+ GlobalTensor<T1> scaleGm_;
45+ GlobalTensor<T2> offsetGm_;
46+ GlobalTensor<U> yGm_;
47+ 
48+ const AscendAntiQuantV2TilingData* tilingData_;
49+ int32_t blockIdx_ = 0;
50+ int64_t gmXOffset_ = 0;
51+ int64_t gmSOffset_ = 0;
52+ int64_t blockN_ = 1;
53+ int64_t blockLen_ = 1;
54+ int64_t blockS_ = 1;
55+ int64_t nLoopLen = 0;
56+ int64_t nLoopNum = 0;
57+ int64_t nLoopTail = 0;
58+ int64_t loopLen = 0;
59+ int64_t lenLoopNum = 0;
60+ int64_t lenLoopTail = 0;
61+ 
62+private:
63+ __aicore__ inline void ProcessInputLoop(
64+ int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal, LocalTensor<T2>& offsetLocal);
65+ template <typename dtypeCopyIn>
66+ __aicore__ inline void CopyInParam(
67+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<dtypeCopyIn>& inGm, int64_t paramLen, int64_t paramOffset);
68+ __aicore__ inline void ParseCoreBlocks(const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen);
69+ __aicore__ inline void ProcessParamOneLoop(int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset);
70+ __aicore__ inline void GetXInCopyParams(const AscendAntiQuantV2TilingData* tilingData, int64_t xN, int64_t xLen, int64_t lastDimLen,
71+ DataCopyExtParams& copyParams);
72+ __aicore__ inline void GetOutCopyParams(const AscendAntiQuantV2TilingData* tilingData, int64_t yN, int64_t yLen, int64_t lastDimLen,
73+ DataCopyExtParams& copyParams);
74+ __aicore__ inline void CopyInX(int64_t xN, int64_t xLen, int64_t xInOffset);
75+ __aicore__ inline void CopyOutY(int64_t yN, int64_t yLen, int64_t yOutOffset);
76+ __aicore__ inline void Compute(int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
77+};
78+ 
79+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
80+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::Init(
81+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
82+{
83+ blockIdx_ = GetBlockIdx();
84+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
85+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
86+ offsetGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T2*>(offset));
87+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
88+ 
89+ ParseCoreBlocks(tilingData_, blockIdx_, blockN_, blockS_, blockLen_);
90+ 
91+ // calc n size to alloc queue
92+ pipe_.InitBuffer(inQueueX_, bufferNum, tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype));
93+ pipe_.InitBuffer(inQueueScale_, bufferNum, tilingData_->baseN * sizeof(T1));
94+ pipe_.InitBuffer(inQueueOffset_, bufferNum, tilingData_->baseN * sizeof(T2));
95+ 
96+ pipe_.InitBuffer(outQueueY_, bufferNum, tilingData_->baseN * tilingData_->baseLen * sizeof(U));
97+}
98+ 
99+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
100+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::Process()
101+{
102+ if (blockIdx_ >= tilingData_->numCore || blockN_ == 0) {
103+ return;
104+ }
105+ if (tilingData_->blockAxis == 0) {
106+ // only split axis 0
107+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor * tilingData_->dim1 * tilingData_->dim2;
108+ gmSOffset_ = 0;
109+ } else if (tilingData_->blockAxis == 1) {
110+ // only split axis 1, blockUnion means factor per block on split axis
111+ gmXOffset_ = blockIdx_ / tilingData_->blockUnion * tilingData_->dim1 * tilingData_->dim2 +
112+ blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor * tilingData_->dim2;
113+ gmSOffset_ = blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor;
114+ } else {
115+ gmXOffset_ =
116+ (blockIdx_ / tilingData_->blockUnion * tilingData_->dim2 +
117+ blockIdx_ % tilingData_->blockUnion * tilingData_->blockFactor);
118+ gmSOffset_ = blockIdx_ / tilingData_->blockUnion;
119+ }
120+ 
121+ nLoopLen = tilingData_->baseN;
122+ nLoopNum = blockN_ / nLoopLen;
123+ nLoopTail = blockN_ % nLoopLen;
124+ 
125+ loopLen = tilingData_->baseLen;
126+ lenLoopNum = blockLen_ / loopLen;
127+ lenLoopTail = blockLen_ % loopLen;
128+ 
129+ for (int64_t i = 0; i < blockS_; ++i) {
130+ // scale allows start from begin on each core
131+ int64_t baseSOffset = gmSOffset_;
132+ int64_t baseXOffset = gmXOffset_;
133+ 
134+ for (int64_t i = 0; i < nLoopNum; ++i) {
135+ ProcessParamOneLoop(nLoopLen, baseSOffset, baseXOffset);
136+ baseXOffset += nLoopLen * tilingData_->dim2;
137+ baseSOffset += tilingData_->baseN;
138+ }
139+ if (nLoopTail != 0) {
140+ ProcessParamOneLoop(nLoopTail, baseSOffset, baseXOffset);
141+ }
142+ gmXOffset_ += tilingData_->dim1 * tilingData_->dim2;
143+ }
144+}
145+ 
146+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
147+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::ProcessParamOneLoop(int64_t nLoopLen, int64_t baseSOffset, int64_t baseXOffset)
148+{
149+ // copy in scale and offset
150+ CopyInParam<T1>(inQueueScale_, scaleGm_, nLoopLen, baseSOffset % tilingData_->dim1);
151+ auto scaleLocal = inQueueScale_.DeQue<T1>();
152+ CopyInParam<T2>(inQueueOffset_, offsetGm_, nLoopLen, baseSOffset % tilingData_->dim1);
153+ auto offsetLocal = inQueueOffset_.DeQue<T2>();
154+ ProcessInputLoop(nLoopLen, baseXOffset, scaleLocal, offsetLocal);
155+ inQueueOffset_.FreeTensor(offsetLocal);
156+ 
157+ inQueueScale_.FreeTensor(scaleLocal);
158+}
159+ 
160+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
161+template <typename dtypeCopyIn>
162+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::CopyInParam(
163+ TQue<QuePosition::VECIN, bufferNum>& inQueue, GlobalTensor<dtypeCopyIn>& inGm, int64_t paramLen,
164+ int64_t paramOffset)
165+{
166+ auto paramLocal = inQueue.AllocTensor<dtypeCopyIn>();
167+ DataCopyExtParams copyParams;
168+ copyParams.blockCount = 1;
169+ copyParams.blockLen = paramLen * sizeof(dtypeCopyIn);
170+ copyParams.dstStride = 0;
171+ copyParams.srcStride = 0;
172+ copyParams.rsv = 0;
173+ DataCopyPad(paramLocal, inGm[paramOffset], copyParams, {false, 0, 0, 0});
174+ inQueue.EnQue(paramLocal);
175+}
176+ 
177+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
178+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::ParseCoreBlocks(
179+ const AscendAntiQuantV2TilingData* tilingData, int32_t blockIdx, int64_t& blockN, int64_t& blockS, int64_t& blockLen)
180+{
181+ if (tilingData->blockAxis == 0) {
182+ // blockFactor is in [1, S]
183+ if (blockIdx == tilingData->numCore - 1) {
184+ blockS = tilingData->blockTailFactor;
185+ } else {
186+ blockS = tilingData->blockFactor;
187+ }
188+ blockN = tilingData->dim1;
189+ blockLen = tilingData->dim2;
190+ } else if (tilingData->blockAxis == 1) {
191+ // blockFactor is in [1, N], blockUnion is in [1, N/blockFactor]
192+ if (blockIdx % tilingData->blockUnion == tilingData->blockUnion - 1) {
193+ blockN = tilingData->blockTailFactor;
194+ } else {
195+ blockN = tilingData->blockFactor;
196+ }
197+ blockLen = tilingData->dim2;
198+ } else {
199+ // blockFactor is in [1, D]
200+ blockN = 1;
201+ if (blockIdx % tilingData->blockUnion == tilingData->blockUnion - 1) {
202+ blockLen = tilingData->blockTailFactor;
203+ } else {
204+ blockLen = tilingData->blockFactor;
205+ }
206+ }
207+}
208+ 
209+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
210+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::ProcessInputLoop(
211+ int64_t nLoopLen, int64_t baseXOffset, LocalTensor<T1>& scaleLocal, LocalTensor<T2>& offsetLocal)
212+{
213+ for (auto i = 0; i < lenLoopNum; ++i) {
214+ CopyInX(nLoopLen, loopLen, baseXOffset);
215+ Compute(nLoopLen, loopLen, scaleLocal, offsetLocal);
216+ CopyOutY(nLoopLen, loopLen, baseXOffset);
217+ baseXOffset += tilingData_->baseLen;
218+ }
219+ if (lenLoopTail != 0) {
220+ CopyInX(nLoopLen, lenLoopTail, baseXOffset);
221+ Compute(nLoopLen, lenLoopTail, scaleLocal, offsetLocal);
222+ CopyOutY(nLoopLen, lenLoopTail, baseXOffset);
223+ }
224+}
225+ 
226+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
227+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::GetXInCopyParams(
228+ const AscendAntiQuantV2TilingData* tilingData, int64_t xN, int64_t xLen, int64_t lastDimLen,
229+ DataCopyExtParams& copyParams)
230+{
231+ int64_t xLenReal = xLen;
232+ if constexpr (IsSameType<T, int4b_t>::value) {
233+ xLenReal = xLenReal / this->INT4_NUMS_IN_INT8_SPACE;
234+ }
235+ 
236+ copyParams.blockCount = xN;
237+ copyParams.blockLen = xLenReal * sizeof(xCopyDtype);
238+ if (lastDimLen > xLen) {
239+ if constexpr (IsSameType<T, int4b_t>::value) {
240+ copyParams.srcStride = (lastDimLen - xLen) * sizeof(xCopyDtype) / this->INT4_NUMS_IN_INT8_SPACE;
241+ } else {
242+ copyParams.srcStride = (lastDimLen - xLen) * sizeof(xCopyDtype);
243+ }
244+ } else {
245+ copyParams.srcStride = 0;
246+ }
247+ if (tilingData->baseLen > xLenReal) {
248+ copyParams.dstStride = (tilingData->baseLen - xLenReal) * sizeof(xCopyDtype) / this->BLOCK_SIZE;
249+ } else {
250+ copyParams.dstStride = 0;
251+ }
252+}
253+ 
254+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
255+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
256+ int64_t xN, int64_t xLen, int64_t xInOffset)
257+{
258+ if constexpr (IsSameType<T, int4b_t>::value) {
259+ xInOffset = xInOffset >> 1;
260+ }
261+ 
262+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
263+ DataCopyExtParams copyParams;
264+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
265+ GetXInCopyParams(tilingData_, xN, xLen, tilingData_->dim2, copyParams);
266+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
267+ inQueueX_.EnQue(xLocal);
268+}
269+ 
270+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
271+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::Compute(
272+ int64_t nRow, int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
273+{
274+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
275+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
276+ 
277+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
278+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
279+ __local_mem__ T2* offsetLocalAddr = (__local_mem__ T2*)oLocal.GetPhyAddr();
280+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
281+ 
282+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
283+ uint16_t HalfVL = VL / 2;
284+ uint16_t vfLoopNum = (dataCount + VL - 1) / VL;
285+ 
286+ uint32_t xLocalOffset = static_cast<uint32_t>(tilingData_->baseLen);
287+ 
288+ // has offset
289+ __VEC_SCOPE__
290+ {
291+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
292+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
293+ AscendC::Reg::RegTensor<half> vregHalfX;
294+ AscendC::Reg::RegTensor<float> vregFloatX;
295+ // scales: fp32, bf16
296+ AscendC::Reg::RegTensor<T1> vregS;
297+ AscendC::Reg::RegTensor<float> vregFloatS;
298+ // offset: fp32, bf16
299+ AscendC::Reg::RegTensor<T2> vregO;
300+ AscendC::Reg::RegTensor<float> vregFloatO;
301+ // y: fp16, bf16
302+ AscendC::Reg::RegTensor<float> vregFloatY;
303+ AscendC::Reg::RegTensor<U> vregY;
304+ 
305+ AscendC::Reg::RegTensor<float> vregTmp1;
306+ AscendC::Reg::MaskReg mask;
307+ 
308+ mask = AscendC::Reg::CreateMask<float>();
309+ for (uint16_t j = 0; j < static_cast<uint16_t>(nRow); ++j) {
310+ uint32_t count = dataCount;
311+ for (uint16_t i = 0; i < vfLoopNum; i++) {
312+ mask = AscendC::Reg::UpdateMask<float>(count);
313+ // ld and cast for x
314+ if constexpr (IsSameType<T, hifloat8_t>::value) {
315+ // hifp8
316+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
317+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
318+ AscendC::Reg::Cast<
319+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
320+ vregFloatX, vregX, mask);
321+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
322+ // fp8_e5m2
323+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
324+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
325+ AscendC::Reg::Cast<
326+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
327+ vregFloatX, vregX, mask);
328+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
329+ // fp8_e4m3
330+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
331+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
332+ AscendC::Reg::Cast<
333+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
334+ vregFloatX, vregX, mask);
335+ } else if constexpr (IsSameType<T, int8_t>::value) {
336+ // int8
337+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
338+ vregX, xLocalAddr + i * VL + j * xLocalOffset);
339+ AscendC::Reg::Cast<
340+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
341+ vregHalfX, vregX, mask);
342+ AscendC::Reg::Cast<
343+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
344+ vregFloatX, vregHalfX, mask);
345+ } else if constexpr (IsSameType<T, int4b_t>::value) {
346+ // int4
347+ AscendC::Reg::RegTensor<half> vregTmpX;
348+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
349+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
350+ vregX, xLocalAddr + i * HalfVL + j * xLocalOffset);
351+ AscendC::Reg::Cast<
352+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
353+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
354+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
355+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
356+ AscendC::Reg::Cast<
357+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
358+ vregFloatX, vregTmpX, mask);
359+ }
360+ 
361+ // ld and cast for scale
362+ if constexpr (IsSameType<T1, float>::value) {
363+ // fp32
364+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_BRC_B32>(
365+ vregFloatS, scaleLocalAddr + j);
366+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
367+ // bf16
368+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_BRC_B16>(vregS, scaleLocalAddr + j);
369+ AscendC::Reg::Cast<
370+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
371+ vregFloatS, vregS, mask);
372+ }
373+ 
374+ // ld and cast for offset
375+ if constexpr (IsSameType<T2, float>::value) {
376+ // fp32
377+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_BRC_B32>(
378+ vregFloatO, offsetLocalAddr + j);
379+ } else if constexpr (IsSameType<T2, bfloat16_t>::value) {
380+ // bf16
381+ AscendC::Reg::DataCopy<T2, AscendC::Reg::LoadDist::DIST_BRC_B16>(vregO, offsetLocalAddr + j);
382+ AscendC::Reg::Cast<
383+ float, T2, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
384+ vregFloatO, vregO, mask);
385+ }
386+ 
387+ // compute
388+ AscendC::Reg::Add<float, AscendC::Reg::MaskMergeMode::ZEROING>(vregTmp1, vregFloatX, vregFloatO, mask);
389+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
390+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
391+ }
392+ AscendC::Reg::Mul(vregFloatY, vregTmp1, vregFloatS, mask);
393+ 
394+ // cast and sd for y
395+ if constexpr (IsSameType<U, half>::value) {
396+ // fp16
397+ AscendC::Reg::Cast<
398+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
399+ vregY, vregFloatY, mask);
400+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
401+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
402+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
403+ // bf16
404+ AscendC::Reg::Cast<
405+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
406+ vregY, vregFloatY, mask);
407+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
408+ outLocalAddr + i * VL + j * xLocalOffset, vregY, mask);
409+ }
410+ }
411+ }
412+ }
413+ inQueueX_.FreeTensor(xLocal);
414+ outQueueY_.EnQue(outLocal);
415+}
416+ 
417+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
418+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::GetOutCopyParams(
419+ const AscendAntiQuantV2TilingData* tilingData, int64_t yN, int64_t yLen, int64_t lastDimLen,
420+ DataCopyExtParams& copyParams)
421+{
422+ copyParams.blockCount = yN;
423+ copyParams.blockLen = yLen * sizeof(U);
424+ if (tilingData->baseLen > yLen) {
425+ copyParams.srcStride = (tilingData->baseLen - yLen) * sizeof(U) / this->BLOCK_SIZE;
426+ } else {
427+ copyParams.srcStride = 0;
428+ }
429+ if (lastDimLen > yLen) {
430+ copyParams.dstStride = (lastDimLen - yLen) * sizeof(U);
431+ } else {
432+ copyParams.dstStride = 0;
433+ }
434+}
435+ 
436+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
437+__aicore__ inline void AscendAntiQuantV2PerHeadRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
438+ int64_t yN, int64_t yLen, int64_t yOutOffset)
439+{
440+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
441+ DataCopyExtParams copyParams;
442+ GetOutCopyParams(tilingData_, yN, yLen, tilingData_->dim2, copyParams);
443+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
444+ outQueueY_.FreeTensor(outLocal);
445+}
446+} // namespace AscendAntiQuantV2
447+#endif //ASCEND_ANTI_QUANT_V2_PER_HEAD_REGBASE_H
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_tensor_no_offset_regbase.h+280-0
@@ -0,0 +1,280 @@
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 ascend_anti_quant_v2_per_tensor_no_offset_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_TENSOR_NO_OFFSET_REGBASE_H_
17+#define ASCEND_ANTI_QUANT_V2_PER_TENSOR_NO_OFFSET_REGBASE_H_
18+ 
19+ 
20+#include "kernel_tiling/kernel_tiling.h"
21+#include "../inc/platform.h"
22+#include "../inc/kernel_utils.h"
23+#include "ascend_anti_quant_v2_common.h"
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerTensorNoOffsetRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerTensorNoOffsetRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ __aicore__ inline void CopyXAndCompute(int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal);
37+ __aicore__ inline void CopyInScale();
38+ __aicore__ inline void CopyInX(int64_t xLen, int64_t xInOffset);
39+ __aicore__ inline void CopyOutY(int64_t yLen, int64_t yOutOffset);
40+ __aicore__ inline void Compute(int64_t dataCount, LocalTensor<T1>& sLocal);
41+ 
42+private:
43+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
44+ constexpr static int32_t bufferNum_ = 2;
45+ TPipe pipe_;
46+ TQue<QuePosition::VECIN, bufferNum_> inQueueX_;
47+ TQue<QuePosition::VECIN, bufferNum_> inQueueScale_;
48+ TQue<QuePosition::VECOUT, bufferNum_> outQueueY_;
49+ GlobalTensor<uint8_t> xGm_;
50+ GlobalTensor<T1> scaleGm_;
51+ GlobalTensor<U> yGm_;
52+ 
53+ const AscendAntiQuantV2TilingData* tilingData_;
54+ int32_t blockIdx_ = 0;
55+ int64_t gmXOffset_ = 0;
56+ int64_t blockN_ = 1;
57+ int64_t blockLen_ = 1;
58+};
59+ 
60+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
61+__aicore__ inline void AscendAntiQuantV2PerTensorNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Init(
62+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
63+{
64+ blockIdx_ = GetBlockIdx();
65+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
66+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
67+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
68+ 
69+ blockN_ = tilingData_->dim0;
70+ if (blockIdx_ == tilingData_->numCore - 1) {
71+ blockLen_ = tilingData_->blockTailFactor;
72+ } else {
73+ blockLen_ = tilingData_->blockFactor;
74+ }
75+ 
76+ // calc n size to alloc queue
77+ pipe_.InitBuffer(inQueueX_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype));
78+ pipe_.InitBuffer(inQueueScale_, bufferNum_, this->BLOCK_SIZE);
79+ 
80+ pipe_.InitBuffer(outQueueY_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(U));
81+}
82+ 
83+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
84+__aicore__ inline void AscendAntiQuantV2PerTensorNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Process()
85+{
86+ if (blockIdx_ >= tilingData_->numCore) {
87+ return;
88+ }
89+ 
90+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor;
91+
92+ // main loop with column, for scale and offset only need copy once
93+ int64_t lenLoopNum = blockLen_ / tilingData_->baseLen;
94+ int64_t lenLoopTail = blockLen_ % tilingData_->baseLen;
95+ CopyInScale();
96+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
97+ for (int64_t i = 0; i < lenLoopNum; ++i) {
98+ CopyXAndCompute(tilingData_->baseLen, gmXOffset_ + i * tilingData_->baseLen, sLocal);
99+ }
100+ if (lenLoopTail != 0) {
101+ CopyXAndCompute(lenLoopTail, gmXOffset_ + lenLoopNum * tilingData_->baseLen, sLocal);
102+ }
103+ inQueueScale_.FreeTensor(sLocal);
104+}
105+ 
106+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
107+__aicore__ inline void AscendAntiQuantV2PerTensorNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInScale()
108+{
109+ DataCopyExtParams copyParams;
110+ copyParams.blockCount = 1;
111+ copyParams.blockLen = sizeof(T1);
112+ copyParams.dstStride = 0;
113+ copyParams.srcStride = 0;
114+ copyParams.rsv = 0;
115+ LocalTensor<T1> sLocal = inQueueScale_.AllocTensor<T1>();
116+ DataCopyPad(sLocal, scaleGm_, copyParams, {false, 0, 0, 0});
117+ inQueueScale_.EnQue(sLocal);
118+}
119+ 
120+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
121+__aicore__ inline void AscendAntiQuantV2PerTensorNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyXAndCompute(
122+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal)
123+{
124+ CopyInX(dataCount, offset);
125+ Compute(dataCount, sLocal);
126+ CopyOutY(dataCount, offset);
127+}
128+ 
129+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
130+__aicore__ inline void AscendAntiQuantV2PerTensorNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
131+ int64_t xLen, int64_t xInOffset)
132+{
133+ if constexpr (IsSameType<T, int4b_t>::value) {
134+ xInOffset = xInOffset >> 1;
135+ }
136+
137+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
138+ DataCopyExtParams copyParams;
139+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
140+ this->GetXInCopyParams(tilingData_->dim1, tilingData_->baseLen, tilingData_->baseN, xLen, copyParams);
141+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
142+ inQueueX_.EnQue(xLocal);
143+}
144+ 
145+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
146+__aicore__ inline void AscendAntiQuantV2PerTensorNoOffsetRegbase<T, T1, T2, U, SqrtMode>::Compute(
147+ int64_t dataCount, LocalTensor<T1>& sLocal)
148+{
149+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
150+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
151+ 
152+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
153+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
154+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
155+ 
156+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
157+ uint16_t HalfVL = VL / 2;
158+ uint16_t vfLoopNum = (dataCount + VL - 1) / VL;
159+ 
160+ // has offset
161+ __VEC_SCOPE__
162+ {
163+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
164+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
165+ AscendC::Reg::RegTensor<half> vregHalfX;
166+ AscendC::Reg::RegTensor<float> vregFloatX;
167+ // scales: fp32, bf16
168+ AscendC::Reg::RegTensor<T1> vregS;
169+ AscendC::Reg::RegTensor<float> vregFloatS;
170+ // y: fp16, bf16
171+ AscendC::Reg::RegTensor<float> vregFloatY;
172+ AscendC::Reg::RegTensor<U> vregY;
173+ 
174+ AscendC::Reg::MaskReg mask;
175+ 
176+ mask = AscendC::Reg::CreateMask<float>();
177+ uint32_t count = dataCount;
178+ for (uint16_t i = 0; i < vfLoopNum; i++) {
179+ mask = AscendC::Reg::UpdateMask<float>(count);
180+ // ld and cast for x
181+ if constexpr (IsSameType<T, hifloat8_t>::value) {
182+ // hifp8
183+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
184+ vregX, xLocalAddr + i * VL);
185+ AscendC::Reg::Cast<
186+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
187+ vregFloatX, vregX, mask);
188+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
189+ // fp8_e5m2
190+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
191+ vregX, xLocalAddr + i * VL);
192+ AscendC::Reg::Cast<
193+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
194+ vregFloatX, vregX, mask);
195+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
196+ // fp8_e4m3
197+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
198+ vregX, xLocalAddr + i * VL);
199+ AscendC::Reg::Cast<
200+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
201+ vregFloatX, vregX, mask);
202+ } else if constexpr (IsSameType<T, int8_t>::value) {
203+ // int8
204+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
205+ vregX, xLocalAddr + i * VL);
206+ AscendC::Reg::Cast<
207+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
208+ vregHalfX, vregX, mask);
209+ AscendC::Reg::Cast<
210+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
211+ vregFloatX, vregHalfX, mask);
212+ } else if constexpr (IsSameType<T, int4b_t>::value) {
213+ // int4
214+ AscendC::Reg::RegTensor<half> vregTmpX;
215+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
216+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
217+ vregX, xLocalAddr + i * HalfVL);
218+ AscendC::Reg::Cast<
219+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
220+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
221+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
222+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
223+ AscendC::Reg::Cast<
224+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
225+ vregFloatX, vregTmpX, mask);
226+ }
227+ 
228+ // ld and cast for scale
229+ if constexpr (IsSameType<T1, float>::value) {
230+ // fp32
231+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_BRC_B32>(
232+ vregFloatS, scaleLocalAddr);
233+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
234+ // bf16
235+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_BRC_B16>(vregS, scaleLocalAddr);
236+ AscendC::Reg::Cast<
237+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
238+ vregFloatS, vregS, mask);
239+ }
240+ 
241+ // compute
242+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
243+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
244+ }
245+ AscendC::Reg::Mul(vregFloatY, vregFloatX, vregFloatS, mask);
246+ 
247+ // cast and sd for y
248+ if constexpr (IsSameType<U, half>::value) {
249+ // fp16
250+ AscendC::Reg::Cast<
251+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
252+ vregY, vregFloatY, mask);
253+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
254+ outLocalAddr + i * VL, vregY, mask);
255+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
256+ // bf16
257+ AscendC::Reg::Cast<
258+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
259+ vregY, vregFloatY, mask);
260+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
261+ outLocalAddr + i * VL, vregY, mask);
262+ }
263+ }
264+ }
265+ inQueueX_.FreeTensor(xLocal);
266+ outQueueY_.EnQue(outLocal);
267+}
268+ 
269+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
270+__aicore__ inline void AscendAntiQuantV2PerTensorNoOffsetRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
271+ int64_t yLen, int64_t yOutOffset)
272+{
273+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
274+ DataCopyExtParams copyParams;
275+ this->GetOutCopyParams(tilingData_->dim1, tilingData_->baseLen, tilingData_->baseN, yLen, copyParams);
276+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
277+ outQueueY_.FreeTensor(outLocal);
278+}
279+} // namespace AscendAntiQuantV2
280+#endif
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_per_tensor_regbase.h+321-0
@@ -0,0 +1,321 @@
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 ascend_anti_quant_v2_per_tensor_regbase.h
13+ * \brief ascendantiquantv2 kernel
14+ */
15+ 
16+#ifndef ASCEND_ANTI_QUANT_V2_PER_TENSOR_REGBASE_H_
17+#define ASCEND_ANTI_QUANT_V2_PER_TENSOR_REGBASE_H_
18+ 
19+ 
20+#include "kernel_tiling/kernel_tiling.h"
21+#include "../inc/platform.h"
22+#include "../inc/kernel_utils.h"
23+#include "ascend_anti_quant_v2_common.h"
24+ 
25+namespace AscendAntiQuantV2 {
26+using namespace AscendC;
27+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
28+class AscendAntiQuantV2PerTensorRegbase : public AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode> {
29+public:
30+ __aicore__ inline AscendAntiQuantV2PerTensorRegbase(const AscendAntiQuantV2TilingData* tilingData)
31+ : tilingData_(tilingData){};
32+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y);
33+ __aicore__ inline void Process();
34+ 
35+private:
36+ __aicore__ inline void CopyXAndCompute(int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
37+ __aicore__ inline void CopyInScale();
38+ __aicore__ inline void CopyInOffset();
39+ __aicore__ inline void CopyInX(int64_t xLen, int64_t xInOffset);
40+ __aicore__ inline void CopyOutY(int64_t yLen, int64_t yOutOffset);
41+ __aicore__ inline void Compute(int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal);
42+ 
43+private:
44+ using xCopyDtype = std::conditional_t<IsSameType<T, int4b_t>::value, uint8_t, T>;
45+ constexpr static int32_t bufferNum_ = 2;
46+ TPipe pipe_;
47+ TQue<QuePosition::VECIN, bufferNum_> inQueueX_;
48+ TQue<QuePosition::VECIN, bufferNum_> inQueueScale_;
49+ TQue<QuePosition::VECIN, bufferNum_> inQueueOffset_;
50+ TQue<QuePosition::VECOUT, bufferNum_> outQueueY_;
51+ GlobalTensor<uint8_t> xGm_;
52+ GlobalTensor<T1> scaleGm_;
53+ GlobalTensor<T2> offsetGm_;
54+ GlobalTensor<U> yGm_;
55+ 
56+ const AscendAntiQuantV2TilingData* tilingData_;
57+ int32_t blockIdx_ = 0;
58+ int64_t gmXOffset_ = 0;
59+ int64_t blockN_ = 1;
60+ int64_t blockLen_ = 1;
61+};
62+ 
63+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
64+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::Init(
65+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y)
66+{
67+ blockIdx_ = GetBlockIdx();
68+ xGm_.SetGlobalBuffer(reinterpret_cast<__gm__ uint8_t*>(x));
69+ scaleGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T1*>(scale));
70+ offsetGm_.SetGlobalBuffer(reinterpret_cast<__gm__ T2*>(offset));
71+ yGm_.SetGlobalBuffer(reinterpret_cast<__gm__ U*>(y));
72+ 
73+ blockN_ = tilingData_->dim0;
74+ if (blockIdx_ == tilingData_->numCore - 1) {
75+ blockLen_ = tilingData_->blockTailFactor;
76+ } else {
77+ blockLen_ = tilingData_->blockFactor;
78+ }
79+ 
80+ // calc n size to alloc queue
81+ pipe_.InitBuffer(inQueueX_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(xCopyDtype));
82+ pipe_.InitBuffer(inQueueScale_, bufferNum_, this->BLOCK_SIZE);
83+ pipe_.InitBuffer(inQueueOffset_, bufferNum_, this->BLOCK_SIZE);
84+ 
85+ pipe_.InitBuffer(outQueueY_, bufferNum_, tilingData_->baseN * tilingData_->baseLen * sizeof(U));
86+}
87+ 
88+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
89+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::Process()
90+{
91+ if (blockIdx_ >= tilingData_->numCore) {
92+ return;
93+ }
94+ 
95+ gmXOffset_ = blockIdx_ * tilingData_->blockFactor;
96+
97+ // main loop with column, for scale and offset only need copy once
98+ int64_t lenLoopNum = blockLen_ / tilingData_->baseLen;
99+ int64_t lenLoopTail = blockLen_ % tilingData_->baseLen;
100+ CopyInScale();
101+ CopyInOffset();
102+ LocalTensor<T1> sLocal = inQueueScale_.DeQue<T1>();
103+ LocalTensor<T2> oLocal = inQueueOffset_.DeQue<T2>();
104+ for (int64_t i = 0; i < lenLoopNum; ++i) {
105+ CopyXAndCompute(tilingData_->baseLen, gmXOffset_ + i * tilingData_->baseLen, sLocal, oLocal);
106+ }
107+ if (lenLoopTail != 0) {
108+ CopyXAndCompute(lenLoopTail, gmXOffset_ + lenLoopNum * tilingData_->baseLen, sLocal, oLocal);
109+ }
110+ inQueueScale_.FreeTensor(sLocal);
111+ inQueueOffset_.FreeTensor(oLocal);
112+}
113+ 
114+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
115+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::CopyInScale()
116+{
117+ DataCopyExtParams copyParams;
118+ copyParams.blockCount = 1;
119+ copyParams.blockLen = sizeof(T1);
120+ copyParams.dstStride = 0;
121+ copyParams.srcStride = 0;
122+ copyParams.rsv = 0;
123+ LocalTensor<T1> sLocal = inQueueScale_.AllocTensor<T1>();
124+ DataCopyPad(sLocal, scaleGm_, copyParams, {false, 0, 0, 0});
125+ inQueueScale_.EnQue(sLocal);
126+}
127+ 
128+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
129+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::CopyInOffset()
130+{
131+ DataCopyExtParams copyParams;
132+ copyParams.blockCount = 1;
133+ copyParams.blockLen = sizeof(T2);
134+ copyParams.dstStride = 0;
135+ copyParams.srcStride = 0;
136+ copyParams.rsv = 0;
137+ LocalTensor<T2> oLocal = inQueueOffset_.AllocTensor<T2>();
138+ DataCopyPad(oLocal, offsetGm_, copyParams, {false, 0, 0, 0});
139+ inQueueOffset_.EnQue(oLocal);
140+}
141+ 
142+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
143+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::CopyXAndCompute(
144+ int64_t dataCount, int64_t offset, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
145+{
146+ CopyInX(dataCount, offset);
147+ Compute(dataCount, sLocal, oLocal);
148+ CopyOutY(dataCount, offset);
149+}
150+ 
151+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
152+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::CopyInX(
153+ int64_t xLen, int64_t xInOffset)
154+{
155+ if constexpr (IsSameType<T, int4b_t>::value) {
156+ xInOffset = xInOffset >> 1;
157+ }
158+ 
159+ LocalTensor<uint8_t> xLocal = inQueueX_.AllocTensor<uint8_t>();
160+ DataCopyExtParams copyParams;
161+ DataCopyPadExtParams<uint8_t> padParams = {false, 0, 0, 0};
162+ this->GetXInCopyParams(tilingData_->dim1, tilingData_->baseLen, tilingData_->baseN, xLen, copyParams);
163+ DataCopyPad<uint8_t>(xLocal, xGm_[xInOffset], copyParams, padParams);
164+ inQueueX_.EnQue(xLocal);
165+}
166+ 
167+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
168+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::Compute(
169+ int64_t dataCount, LocalTensor<T1>& sLocal, LocalTensor<T2>& oLocal)
170+{
171+ LocalTensor<xCopyDtype> xLocal = inQueueX_.DeQue<xCopyDtype>();
172+ LocalTensor<U> outLocal = outQueueY_.AllocTensor<U>();
173+ 
174+ __local_mem__ xCopyDtype* xLocalAddr = (__local_mem__ xCopyDtype*)xLocal.GetPhyAddr();
175+ __local_mem__ T1* scaleLocalAddr = (__local_mem__ T1*)sLocal.GetPhyAddr();
176+ __local_mem__ T2* offsetLocalAddr = (__local_mem__ T2*)oLocal.GetPhyAddr();
177+ __local_mem__ U* outLocalAddr = (__local_mem__ U*)outLocal.GetPhyAddr();
178+ 
179+ uint16_t VL = AscendC::VECTOR_REG_WIDTH / sizeof(float);
180+ uint16_t HalfVL = VL / 2;
181+ uint16_t vfLoopNum = (dataCount + VL - 1) / VL;
182+ 
183+ // has offset
184+ __VEC_SCOPE__
185+ {
186+ // x: int4, int8, hifp8, fp8_e5m2, fp8_e4m3
187+ AscendC::Reg::RegTensor<xCopyDtype> vregX;
188+ AscendC::Reg::RegTensor<half> vregHalfX;
189+ AscendC::Reg::RegTensor<float> vregFloatX;
190+ // scales: fp32, bf16
191+ AscendC::Reg::RegTensor<T1> vregS;
192+ AscendC::Reg::RegTensor<float> vregFloatS;
193+ // offset: fp32, bf16
194+ AscendC::Reg::RegTensor<T2> vregO;
195+ AscendC::Reg::RegTensor<float> vregFloatO;
196+ // y: fp16, bf16
197+ AscendC::Reg::RegTensor<float> vregFloatY;
198+ AscendC::Reg::RegTensor<U> vregY;
199+ 
200+ AscendC::Reg::RegTensor<float> vregTmp1;
201+ AscendC::Reg::MaskReg mask;
202+ 
203+ mask = AscendC::Reg::CreateMask<float>();
204+ uint32_t count = dataCount;
205+ for (uint16_t i = 0; i < vfLoopNum; i++) {
206+ mask = AscendC::Reg::UpdateMask<float>(count);
207+ // ld and cast for x
208+ if constexpr (IsSameType<T, hifloat8_t>::value) {
209+ // hifp8
210+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
211+ vregX, xLocalAddr + i * VL);
212+ AscendC::Reg::Cast<
213+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HIFP8_TO_FP32>(
214+ vregFloatX, vregX, mask);
215+ } else if constexpr (IsSameType<T, fp8_e5m2_t>::value) {
216+ // fp8_e5m2
217+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
218+ vregX, xLocalAddr + i * VL);
219+ AscendC::Reg::Cast<
220+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E5M2_TO_FP32>(
221+ vregFloatX, vregX, mask);
222+ } else if constexpr (IsSameType<T, fp8_e4m3fn_t>::value) {
223+ // fp8_e4m3
224+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
225+ vregX, xLocalAddr + i * VL);
226+ AscendC::Reg::Cast<
227+ float, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP8E4M3_TO_FP32>(
228+ vregFloatX, vregX, mask);
229+ } else if constexpr (IsSameType<T, int8_t>::value) {
230+ // int8
231+ AscendC::Reg::DataCopy<T, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
232+ vregX, xLocalAddr + i * VL);
233+ AscendC::Reg::Cast<
234+ half, T, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
235+ vregHalfX, vregX, mask);
236+ AscendC::Reg::Cast<
237+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
238+ vregFloatX, vregHalfX, mask);
239+ } else if constexpr (IsSameType<T, int4b_t>::value) {
240+ // int4
241+ AscendC::Reg::RegTensor<half> vregTmpX;
242+ AscendC::Reg::RegTensor<uint16_t> vregTmpU16X;
243+ AscendC::Reg::DataCopy<xCopyDtype, AscendC::Reg::LoadDist::DIST_UNPACK4_B8>(
244+ vregX, xLocalAddr + i * HalfVL);
245+ AscendC::Reg::Cast<
246+ half, int4x2_t, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_INT8_TO_HALF>(
247+ (AscendC::Reg::RegTensor<half>&)vregTmpU16X,
248+ (AscendC::Reg::RegTensor<int4x2_t>&)vregX, mask);
249+ AscendC::Reg::UnPack((AscendC::Reg::RegTensor<uint32_t>&)vregTmpX, vregTmpU16X);
250+ AscendC::Reg::Cast<
251+ float, half, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_HALF_TO_FP32>(
252+ vregFloatX, vregTmpX, mask);
253+ }
254+ 
255+ // ld and cast for scale
256+ if constexpr (IsSameType<T1, float>::value) {
257+ // fp32
258+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_BRC_B32>(
259+ vregFloatS, scaleLocalAddr);
260+ } else if constexpr (IsSameType<T1, bfloat16_t>::value) {
261+ // bf16
262+ AscendC::Reg::DataCopy<T1, AscendC::Reg::LoadDist::DIST_BRC_B16>(vregS, scaleLocalAddr);
263+ AscendC::Reg::Cast<
264+ float, T1, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
265+ vregFloatS, vregS, mask);
266+ }
267+ 
268+ // ld and cast for offset
269+ if constexpr (IsSameType<T2, float>::value) {
270+ // fp32
271+ AscendC::Reg::DataCopy<float, AscendC::Reg::LoadDist::DIST_BRC_B32>(
272+ vregFloatO, offsetLocalAddr);
273+ } else if constexpr (IsSameType<T2, bfloat16_t>::value) {
274+ // bf16
275+ AscendC::Reg::DataCopy<T2, AscendC::Reg::LoadDist::DIST_BRC_B16>(vregO, offsetLocalAddr);
276+ AscendC::Reg::Cast<
277+ float, T2, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_BF16_TO_FP32>(
278+ vregFloatO, vregO, mask);
279+ }
280+ 
281+ // compute
282+ AscendC::Reg::Add<float, AscendC::Reg::MaskMergeMode::ZEROING>(vregTmp1, vregFloatX, vregFloatO, mask);
283+ if constexpr (SqrtMode == TPL_SQRT_MODE) {
284+ AscendC::Reg::Mul(vregFloatS, vregFloatS, vregFloatS, mask);
285+ }
286+ AscendC::Reg::Mul(vregFloatY, vregTmp1, vregFloatS, mask);
287+ 
288+ // cast and sd for y
289+ if constexpr (IsSameType<U, half>::value) {
290+ // fp16
291+ AscendC::Reg::Cast<
292+ half, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_HALF>(
293+ vregY, vregFloatY, mask);
294+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
295+ outLocalAddr + i * VL, vregY, mask);
296+ } else if constexpr (IsSameType<U, bfloat16_t>::value) {
297+ // bf16
298+ AscendC::Reg::Cast<
299+ U, float, AscendAntiQuantV2Base<T, T1, T2, U, SqrtMode>::CAST_TRAIT_FP32_TO_BF16>(
300+ vregY, vregFloatY, mask);
301+ AscendC::Reg::DataCopy<U, AscendC::Reg::StoreDist::DIST_PACK_B32>(
302+ outLocalAddr + i * VL, vregY, mask);
303+ }
304+ }
305+ }
306+ inQueueX_.FreeTensor(xLocal);
307+ outQueueY_.EnQue(outLocal);
308+}
309+ 
310+template <typename T, typename T1, typename T2, typename U, uint64_t SqrtMode>
311+__aicore__ inline void AscendAntiQuantV2PerTensorRegbase<T, T1, T2, U, SqrtMode>::CopyOutY(
312+ int64_t yLen, int64_t yOutOffset)
313+{
314+ LocalTensor<U> outLocal = outQueueY_.DeQue<U>();
315+ DataCopyExtParams copyParams;
316+ this->GetOutCopyParams(tilingData_->dim1, tilingData_->baseLen, tilingData_->baseN, yLen, copyParams);
317+ DataCopyPad<U>(yGm_[yOutOffset], outLocal, copyParams);
318+ outQueueY_.FreeTensor(outLocal);
319+}
320+} // namespace AscendAntiQuantV2
321+#endif
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_struct.h+48-0
@@ -0,0 +1,48 @@
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 ascend_anti_quant_v2_struct.h
13+ * \brief
14+ */
15+#ifndef ASCEND_ANTI_QUANT_V2_STRUCT_H_
16+#define ASCEND_ANTI_QUANT_V2_STRUCT_H_
17+ 
18+#include "ascendc/host_api/tiling/template_argument.h"
19+ 
20+#ifndef TPL_PER_TENSOR
21+ 
22+#define TPL_PER_TENSOR 0
23+#define TPL_PER_CHANNEL 1
24+#define TPL_PER_HEAD 2
25+#define TPL_PER_CHANNEL_NDDMA 3
26+#define TPL_PER_HEAD_NDDMA 4
27+#define TPL_NO_OFFSET 0
28+#define TPL_HAS_OFFSET 1
29+#define TPL_NO_SQRT_MODE 0
30+#define TPL_SQRT_MODE 1
31+ 
32+#endif
33+ 
34+namespace AscendAntiQuantV2Op {
35+ASCENDC_TPL_ARGS_DECL(
36+ AscendAntiQuantV2,
37+ ASCENDC_TPL_UINT_DECL(perMode, 3, ASCENDC_TPL_UI_LIST, TPL_PER_TENSOR, TPL_PER_CHANNEL, TPL_PER_HEAD, TPL_PER_CHANNEL_NDDMA, TPL_PER_HEAD_NDDMA),
38+ ASCENDC_TPL_UINT_DECL(zeroPointsType, 1, ASCENDC_TPL_UI_LIST, TPL_NO_OFFSET, TPL_HAS_OFFSET),
39+ ASCENDC_TPL_UINT_DECL(sqrtMode, 1, ASCENDC_TPL_UI_LIST, TPL_NO_SQRT_MODE, TPL_SQRT_MODE));
40+ 
41+ASCENDC_TPL_SEL(ASCENDC_TPL_ARGS_SEL(
42+ ASCENDC_TPL_UINT_SEL(perMode, ASCENDC_TPL_UI_LIST, TPL_PER_TENSOR, TPL_PER_CHANNEL, TPL_PER_HEAD, TPL_PER_CHANNEL_NDDMA, TPL_PER_HEAD_NDDMA),
43+ ASCENDC_TPL_UINT_SEL(zeroPointsType, ASCENDC_TPL_UI_LIST, TPL_NO_OFFSET, TPL_HAS_OFFSET),
44+ ASCENDC_TPL_UINT_SEL(sqrtMode, ASCENDC_TPL_UI_LIST, TPL_NO_SQRT_MODE, TPL_SQRT_MODE)));
45+ 
46+} // namespace AscendAntiQuantV2Op
47+ 
48+#endif // _ASCEND_ANTI_QUANT_V2_STRUCT_H_
Aquant/ascend_anti_quant_v2/op_kernel/arch35/ascend_anti_quant_v2_tilingdata.h+35-0
@@ -0,0 +1,35 @@
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 ascend_anti_quant_v2_tilingdata.h
13+ * \brief
14+ */
15+#ifndef ASCEND_ANTI_QUANT_V2_TILINGDATA_H_
16+#define ASCEND_ANTI_QUANT_V2_TILINGDATA_H_
17+#include <cstdint>
18+ 
19+class AscendAntiQuantV2TilingData {
20+public:
21+ int64_t numCore;
22+ int64_t blockAxis;
23+ int64_t dim0;
24+ int64_t dim1;
25+ int64_t dim2;
26+ int64_t blockUnion;
27+ int64_t blockFactor;
28+ int64_t blockTailFactor;
29+ int64_t baseN;
30+ int64_t baseLen;
31+ int64_t hasOffset;
32+ int64_t sqrtMode;
33+};
34+ 
35+#endif // ASCEND_ANTI_QUANT_V2_TILINGDATA_H_
Aquant/ascend_anti_quant_v2/op_kernel/ascend_anti_quant_v2_apt.cpp+100-0
@@ -0,0 +1,100 @@
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 ascend_anti_quant_v2_apt.cpp
13+ * \brief ascend_anti_quant_v2 kernel enter
14+ */
15+ 
16+#include "kernel_operator.h"
17+#include "arch35/ascend_anti_quant_v2_struct.h"
18+#include "arch35/ascend_anti_quant_v2_tilingdata.h"
19+#include "arch35/ascend_anti_quant_v2_per_channel_no_offset_regbase.h"
20+#include "arch35/ascend_anti_quant_v2_per_channel_regbase.h"
21+#include "arch35/ascend_anti_quant_v2_per_tensor_no_offset_regbase.h"
22+#include "arch35/ascend_anti_quant_v2_per_tensor_regbase.h"
23+#include "arch35/ascend_anti_quant_v2_per_head_no_offset_regbase.h"
24+#include "arch35/ascend_anti_quant_v2_per_head_regbase.h"
25+#include "arch35/ascend_anti_quant_v2_per_channel_nddma_regbase.h"
26+#include "arch35/ascend_anti_quant_v2_per_channel_nddma_no_offset_regbase.h"
27+#include "arch35/ascend_anti_quant_v2_per_head_nddma_regbase.h"
28+#include "arch35/ascend_anti_quant_v2_per_head_nddma_no_offset_regbase.h"
29+ 
30+using namespace AscendC;
31+using namespace AscendAntiQuantV2;
32+using namespace AscendAntiQuantV2Op;
33+ 
34+template <uint64_t perMode, uint64_t zeroPointsType, uint64_t sqrtMode>
35+__global__ __aicore__ void ascend_anti_quant_v2(
36+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling)
37+{
38+ KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_AIV_ONLY);
39+ if constexpr (perMode == TPL_PER_TENSOR) {
40+ REGISTER_TILING_DEFAULT(AscendAntiQuantV2TilingData);
41+ GET_TILING_DATA_WITH_STRUCT(AscendAntiQuantV2TilingData, tilingData, tiling);
42+ if constexpr (zeroPointsType == TPL_HAS_OFFSET) {
43+ AscendAntiQuantV2PerTensorRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
44+ op.Init(x, scale, offset, y);
45+ op.Process();
46+ } else {
47+ AscendAntiQuantV2PerTensorNoOffsetRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
48+ op.Init(x, scale, offset, y);
49+ op.Process();
50+ }
51+ } else if constexpr (perMode == TPL_PER_CHANNEL) {
52+ REGISTER_TILING_DEFAULT(AscendAntiQuantV2TilingData);
53+ GET_TILING_DATA_WITH_STRUCT(AscendAntiQuantV2TilingData, tilingData, tiling);
54+ if constexpr (zeroPointsType == TPL_HAS_OFFSET) {
55+ AscendAntiQuantV2PerChannelRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
56+ op.Init(x, scale, offset, y);
57+ op.Process();
58+ } else {
59+ AscendAntiQuantV2PerChannelNoOffsetRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
60+ op.Init(x, scale, offset, y);
61+ op.Process();
62+ }
63+ } else if constexpr (perMode == TPL_PER_HEAD) {
64+ REGISTER_TILING_DEFAULT(AscendAntiQuantV2TilingData);
65+ GET_TILING_DATA_WITH_STRUCT(AscendAntiQuantV2TilingData, tilingData, tiling);
66+ if constexpr (zeroPointsType == TPL_HAS_OFFSET) {
67+ AscendAntiQuantV2PerHeadRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
68+ op.Init(x, scale, offset, y);
69+ op.Process();
70+ } else {
71+ AscendAntiQuantV2PerHeadNoOffsetRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
72+ op.Init(x, scale, offset, y);
73+ op.Process();
74+ }
75+ } else if constexpr (perMode == TPL_PER_CHANNEL_NDDMA) {
76+ REGISTER_TILING_DEFAULT(AscendAntiQuantV2TilingData);
77+ GET_TILING_DATA_WITH_STRUCT(AscendAntiQuantV2TilingData, tilingData, tiling);
78+ if constexpr (zeroPointsType == TPL_HAS_OFFSET) {
79+ AscendAntiQuantV2PerChannelNddmaRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
80+ op.Init(x, scale, offset, y);
81+ op.Process();
82+ } else {
83+ AscendAntiQuantV2PerChannelNddmaNoOffsetRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
84+ op.Init(x, scale, offset, y);
85+ op.Process();
86+ }
87+ } else if constexpr (perMode == TPL_PER_HEAD_NDDMA) {
88+ REGISTER_TILING_DEFAULT(AscendAntiQuantV2TilingData);
89+ GET_TILING_DATA_WITH_STRUCT(AscendAntiQuantV2TilingData, tilingData, tiling);
90+ if constexpr (zeroPointsType == TPL_HAS_OFFSET) {
91+ AscendAntiQuantV2PerHeadNddmaRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
92+ op.Init(x, scale, offset, y);
93+ op.Process();
94+ } else {
95+ AscendAntiQuantV2PerHeadNddmaNoOffsetRegbase<DTYPE_X, DTYPE_SCALE, DTYPE_SCALE, DTYPE_Y, sqrtMode> op(&tilingData);
96+ op.Init(x, scale, offset, y);
97+ op.Process();
98+ }
99+ }
100+}
Mquant/ascend_anti_quant_v2/tests/CMakeLists.txt+1-1
@@ -7,7 +7,7 @@
7# See LICENSE in the root of the software repository for the full text of the License.7# See LICENSE in the root of the software repository for the full text of the License.
8#/8#/
9 9 
10-message(STATUS "=== Debug: start ops.fusedop.ascend_quant_v2.tests.CMakeLists.txt ")10+message(STATUS "=== Debug: start ops.quant.ascend_anti_quant_v2.tests.CMakeLists.txt ")
11file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)11file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
12message(STATUS "=== Debug: CURRENT_DIRS =${CURRENT_DIRS} ")12message(STATUS "=== Debug: CURRENT_DIRS =${CURRENT_DIRS} ")
13foreach(SUB_DIR ${CURRENT_DIRS})13foreach(SUB_DIR ${CURRENT_DIRS})
Mquant/ascend_anti_quant_v2/tests/ut/op_host/CMakeLists.txt+2-2
@@ -9,8 +9,8 @@
9 9 
10file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)10file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
11if(UT_TEST_ALL OR OP_HOST_UT)11if(UT_TEST_ALL OR OP_HOST_UT)
12- #add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})12+ add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})
13- #add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})13+ add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})
14endif()14endif()
15if(UT_TEST_ALL OR OP_API_UT)15if(UT_TEST_ALL OR OP_API_UT)
16 add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})16 add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})
Mquant/ascend_anti_quant_v2/tests/ut/op_host/test_aclnn_ascend_anti_quant.cpp+497-11
@@ -15,6 +15,7 @@
15#include "op_api_ut_common/tensor_desc.h"15#include "op_api_ut_common/tensor_desc.h"
16#include "op_api_ut_common/scalar_desc.h"16#include "op_api_ut_common/scalar_desc.h"
17#include "op_api_ut_common/op_api_ut.h"17#include "op_api_ut_common/op_api_ut.h"
18+#include "opdev/platform.h"
18 19 
19using namespace std;20using namespace std;
20 21 
@@ -49,7 +50,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_1)
49 50 
50 uint64_t workspace_size = 0;51 uint64_t workspace_size = 0;
51 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);52 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
52- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);53+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
53}54}
54 55 
55TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_3)56TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_3)
@@ -68,7 +69,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_3)
68 69 
69 uint64_t workspace_size = 0;70 uint64_t workspace_size = 0;
70 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);71 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
71- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);72+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
72}73}
73 74 
74TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_2)75TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_2)
@@ -88,7 +89,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_2)
88 89 
89 uint64_t workspace_size = 0;90 uint64_t workspace_size = 0;
90 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);91 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
91- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);92+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
92}93}
93 94 
94TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_4)95TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_4)
@@ -108,7 +109,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_4)
108 109 
109 uint64_t workspace_size = 0;110 uint64_t workspace_size = 0;
110 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);111 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
111- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);112+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
112}113}
113 114 
114TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_5)115TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_5)
@@ -127,7 +128,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_normal_5)
127 128 
128 uint64_t workspace_size = 0;129 uint64_t workspace_size = 0;
129 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);130 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
130- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);131+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
131}132}
132 133 
133TEST_F(l2_ascend_anti_quant_test, ascend910B2_int4)134TEST_F(l2_ascend_anti_quant_test, ascend910B2_int4)
@@ -147,7 +148,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_int4)
147 148 
148 uint64_t workspace_size = 0;149 uint64_t workspace_size = 0;
149 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);150 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
150- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);151+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
151}152}
152 153 
153TEST_F(l2_ascend_anti_quant_test, ascend910B2_int32)154TEST_F(l2_ascend_anti_quant_test, ascend910B2_int32)
@@ -167,7 +168,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_int32)
167 168 
168 uint64_t workspace_size = 0;169 uint64_t workspace_size = 0;
169 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);170 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
170- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);171+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
171}172}
172 173 
173TEST_F(l2_ascend_anti_quant_test, ascend910B2_int32_scalar)174TEST_F(l2_ascend_anti_quant_test, ascend910B2_int32_scalar)
@@ -193,7 +194,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_int32_scalar)
193 194 
194 uint64_t workspace_size = 0;195 uint64_t workspace_size = 0;
195 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);196 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
196- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);197+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
197}198}
198 199 
199TEST_F(l2_ascend_anti_quant_test, ascend910B2_input_out_dtype_dif_1)200TEST_F(l2_ascend_anti_quant_test, ascend910B2_input_out_dtype_dif_1)
@@ -329,7 +330,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_empty_tensor)
329 330 
330 uint64_t workspace_size = 0;331 uint64_t workspace_size = 0;
331 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);332 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
332- // EXPECT_EQ(aclRet, ACLNN_SUCCESS);333+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
333}334}
334 335 
335TEST_F(l2_ascend_anti_quant_test, ascend910A_empty_tensor0)336TEST_F(l2_ascend_anti_quant_test, ascend910A_empty_tensor0)
@@ -401,7 +402,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend310P_empty_tensor3)
401 402 
402 uint64_t workspace_size = 0;403 uint64_t workspace_size = 0;
403 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);404 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
404- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);405+ // EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
405}406}
406 407 
407TEST_F(l2_ascend_anti_quant_test, ascend310P_check_input_bf16)408TEST_F(l2_ascend_anti_quant_test, ascend310P_check_input_bf16)
@@ -440,7 +441,7 @@ TEST_F(l2_ascend_anti_quant_test, ascend310P_check_output_bf16)
440 // EXPECT_EQ(aclRet, ACLNN_SUCCESS);441 // EXPECT_EQ(aclRet, ACLNN_SUCCESS);
441}442}
442 443 
443-TEST_F(l2_ascend_anti_quant_test, ascend910B2_empty_tensor4)444+TEST_F(l2_ascend_anti_quant_test, ascend910B2_scale_cannot_broadcast_1)
444{445{
445 auto tensor_1_desc = TensorDesc({3, 1}, ACL_INT8, ACL_FORMAT_ND).ValueRange(-2, 2);446 auto tensor_1_desc = TensorDesc({3, 1}, ACL_INT8, ACL_FORMAT_ND).ValueRange(-2, 2);
446 auto tensor_scale = TensorDesc({2}, ACL_FLOAT, ACL_FORMAT_ND);447 auto tensor_scale = TensorDesc({2}, ACL_FLOAT, ACL_FORMAT_ND);
@@ -457,3 +458,488 @@ TEST_F(l2_ascend_anti_quant_test, ascend910B2_empty_tensor4)
457 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);458 aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
458 EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);459 EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
459}460}
461+ 
462+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_1)
463+{
464+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
465+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_HIFLOAT8, ACL_FORMAT_ND)
466+ .ValueRange(-2, 2)
467+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
468+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
469+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
470+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_FLOAT16, ACL_FORMAT_ND);
471+ int dstType = ACL_FLOAT16;
472+ bool sqrtMode = false;
473+ 
474+ auto ut = OP_API_UT(
475+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
476+ OUTPUT(out_tensor_desc));
477+ 
478+ uint64_t workspace_size = 0;
479+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
480+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
481+}
482+ 
483+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_2)
484+{
485+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
486+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_HIFLOAT8, ACL_FORMAT_ND)
487+ .ValueRange(-2, 2)
488+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
489+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
490+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
491+ int dstType = ACL_BF16;
492+ bool sqrtMode = false;
493+ 
494+ auto ut = OP_API_UT(
495+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, (aclTensor*)nullptr, dstType, sqrtMode),
496+ OUTPUT(out_tensor_desc));
497+ 
498+ uint64_t workspace_size = 0;
499+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
500+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
501+}
502+ 
503+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_3)
504+{
505+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
506+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_FLOAT8_E5M2, ACL_FORMAT_ND)
507+ .ValueRange(-2, 2)
508+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
509+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
510+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
511+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_FLOAT16, ACL_FORMAT_ND);
512+ int dstType = ACL_FLOAT16;
513+ bool sqrtMode = false;
514+ 
515+ auto ut = OP_API_UT(
516+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
517+ OUTPUT(out_tensor_desc));
518+ 
519+ uint64_t workspace_size = 0;
520+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
521+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
522+}
523+ 
524+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_4)
525+{
526+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
527+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_FLOAT8_E5M2, ACL_FORMAT_ND)
528+ .ValueRange(-2, 2)
529+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
530+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
531+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
532+ int dstType = ACL_BF16;
533+ bool sqrtMode = false;
534+ 
535+ auto ut = OP_API_UT(
536+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, (aclTensor*)nullptr, dstType, sqrtMode),
537+ OUTPUT(out_tensor_desc));
538+ 
539+ uint64_t workspace_size = 0;
540+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
541+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
542+}
543+ 
544+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_5)
545+{
546+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
547+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_FLOAT8_E4M3FN, ACL_FORMAT_ND)
548+ .ValueRange(-2, 2)
549+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
550+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
551+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
552+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_FLOAT16, ACL_FORMAT_ND);
553+ int dstType = ACL_FLOAT16;
554+ bool sqrtMode = false;
555+ 
556+ auto ut = OP_API_UT(
557+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
558+ OUTPUT(out_tensor_desc));
559+ 
560+ uint64_t workspace_size = 0;
561+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
562+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
563+}
564+ 
565+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_6)
566+{
567+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
568+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_FLOAT8_E4M3FN, ACL_FORMAT_ND)
569+ .ValueRange(-2, 2)
570+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
571+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
572+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
573+ int dstType = ACL_BF16;
574+ bool sqrtMode = false;
575+ 
576+ auto ut = OP_API_UT(
577+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, (aclTensor*)nullptr, dstType, sqrtMode),
578+ OUTPUT(out_tensor_desc));
579+ 
580+ uint64_t workspace_size = 0;
581+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
582+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
583+}
584+ 
585+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_7)
586+{
587+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
588+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
589+ .ValueRange(-2, 2)
590+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
591+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
592+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
593+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_FLOAT16, ACL_FORMAT_ND);
594+ int dstType = ACL_FLOAT16;
595+ bool sqrtMode = false;
596+ 
597+ auto ut = OP_API_UT(
598+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
599+ OUTPUT(out_tensor_desc));
600+ 
601+ uint64_t workspace_size = 0;
602+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
603+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
604+}
605+ 
606+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_8)
607+{
608+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
609+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
610+ .ValueRange(-2, 2)
611+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
612+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
613+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_FLOAT16, ACL_FORMAT_ND);
614+ int dstType = ACL_FLOAT16;
615+ bool sqrtMode = false;
616+ 
617+ auto ut = OP_API_UT(
618+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, (aclTensor*)nullptr, dstType, sqrtMode),
619+ OUTPUT(out_tensor_desc));
620+ 
621+ uint64_t workspace_size = 0;
622+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
623+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
624+}
625+ 
626+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_9)
627+{
628+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
629+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
630+ .ValueRange(-2, 2)
631+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
632+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
633+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
634+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
635+ int dstType = ACL_BF16;
636+ bool sqrtMode = false;
637+ 
638+ auto ut = OP_API_UT(
639+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
640+ OUTPUT(out_tensor_desc));
641+ 
642+ uint64_t workspace_size = 0;
643+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
644+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
645+}
646+ 
647+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_10)
648+{
649+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
650+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
651+ .ValueRange(-2, 2)
652+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
653+ auto tensor_scale = TensorDesc({1}, ACL_BF16, ACL_FORMAT_ND);
654+ auto tensor_offset = TensorDesc({1}, ACL_BF16, ACL_FORMAT_ND);
655+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
656+ int dstType = ACL_BF16;
657+ bool sqrtMode = true;
658+ 
659+ auto ut = OP_API_UT(
660+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
661+ OUTPUT(out_tensor_desc));
662+ 
663+ uint64_t workspace_size = 0;
664+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
665+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
666+}
667+ 
668+TEST_F(l2_ascend_anti_quant_test, ascend950PR_normal_11)
669+{
670+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
671+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
672+ .ValueRange(-2, 2)
673+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
674+ auto tensor_scale = TensorDesc({1}, ACL_BF16, ACL_FORMAT_ND);
675+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
676+ int dstType = ACL_BF16;
677+ bool sqrtMode = true;
678+ 
679+ auto ut = OP_API_UT(
680+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, (aclTensor*)nullptr, dstType, sqrtMode),
681+ OUTPUT(out_tensor_desc));
682+ 
683+ uint64_t workspace_size = 0;
684+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
685+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
686+}
687+ 
688+TEST_F(l2_ascend_anti_quant_test, ascend950PR_int4)
689+{
690+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
691+ auto tensor_1_desc = TensorDesc({3, 4}, ACL_INT4, ACL_FORMAT_ND)
692+ .ValueRange(-2, 2)
693+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
694+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
695+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
696+ auto out_tensor_desc = TensorDesc({3, 4}, ACL_FLOAT16, ACL_FORMAT_ND);
697+ int dstType = ACL_FLOAT16;
698+ bool sqrtMode = false;
699+ 
700+ auto ut = OP_API_UT(
701+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
702+ OUTPUT(out_tensor_desc));
703+ 
704+ uint64_t workspace_size = 0;
705+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
706+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
707+}
708+ 
709+TEST_F(l2_ascend_anti_quant_test, ascend950PR_int32)
710+{
711+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
712+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT32, ACL_FORMAT_ND)
713+ .ValueRange(-2, 2)
714+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
715+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
716+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
717+ auto out_tensor_desc = TensorDesc({3, 40}, ACL_FLOAT16, ACL_FORMAT_ND);
718+ int dstType = ACL_FLOAT16;
719+ bool sqrtMode = false;
720+ 
721+ auto ut = OP_API_UT(
722+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
723+ OUTPUT(out_tensor_desc));
724+ 
725+ uint64_t workspace_size = 0;
726+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
727+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
728+}
729+ 
730+TEST_F(l2_ascend_anti_quant_test, ascend950PR_scale_dim_not_1_01)
731+{
732+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
733+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_HIFLOAT8, ACL_FORMAT_ND)
734+ .ValueRange(-2, 2)
735+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
736+ auto tensor_scale = TensorDesc({1, 5}, ACL_FLOAT, ACL_FORMAT_ND);
737+ auto tensor_offset = TensorDesc({1, 5}, ACL_FLOAT, ACL_FORMAT_ND);
738+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_FLOAT16, ACL_FORMAT_ND);
739+ int dstType = ACL_FLOAT16;
740+ bool sqrtMode = false;
741+ 
742+ auto ut = OP_API_UT(
743+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
744+ OUTPUT(out_tensor_desc));
745+ 
746+ uint64_t workspace_size = 0;
747+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
748+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
749+}
750+ 
751+TEST_F(l2_ascend_anti_quant_test, ascend950PR_per_head_1)
752+{
753+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
754+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_HIFLOAT8, ACL_FORMAT_ND)
755+ .ValueRange(-2, 2)
756+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
757+ auto tensor_scale = TensorDesc({3, 1}, ACL_FLOAT, ACL_FORMAT_ND);
758+ auto tensor_offset = TensorDesc({3, 1}, ACL_FLOAT, ACL_FORMAT_ND);
759+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
760+ int dstType = ACL_BF16;
761+ bool sqrtMode = false;
762+ 
763+ auto ut = OP_API_UT(
764+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
765+ OUTPUT(out_tensor_desc));
766+ 
767+ uint64_t workspace_size = 0;
768+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
769+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
770+}
771+ 
772+TEST_F(l2_ascend_anti_quant_test, ascend950PR_per_head_2)
773+{
774+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
775+ auto tensor_1_desc = TensorDesc({3, 4}, ACL_INT4, ACL_FORMAT_ND)
776+ .ValueRange(-2, 2);
777+ auto tensor_scale = TensorDesc({3}, ACL_BF16, ACL_FORMAT_ND);
778+ auto tensor_offset = TensorDesc({3}, ACL_BF16, ACL_FORMAT_ND);
779+ auto out_tensor_desc = TensorDesc({3, 4}, ACL_BF16, ACL_FORMAT_ND);
780+ int dstType = ACL_BF16;
781+ bool sqrtMode = true;
782+ 
783+ auto ut = OP_API_UT(
784+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
785+ OUTPUT(out_tensor_desc));
786+ 
787+ uint64_t workspace_size = 0;
788+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
789+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
790+}
791+ 
792+TEST_F(l2_ascend_anti_quant_test, ascend950PR_int32_scalar)
793+{
794+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
795+ auto tensor_1_desc = TensorDesc({}, ACL_INT32, ACL_FORMAT_ND)
796+ .ValueRange(-2, 2)
797+ .Value(vector<float>{
798+ 1,
799+ });
800+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
801+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
802+ auto out_tensor_desc = TensorDesc(
803+ {
804+ 8,
805+ },
806+ ACL_FLOAT16, ACL_FORMAT_ND);
807+ int dstType = ACL_FLOAT16;
808+ bool sqrtMode = false;
809+ 
810+ auto ut = OP_API_UT(
811+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
812+ OUTPUT(out_tensor_desc));
813+ 
814+ uint64_t workspace_size = 0;
815+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
816+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
817+}
818+ 
819+TEST_F(l2_ascend_anti_quant_test, ascend950PR_hifloat8_scalar)
820+{
821+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
822+ auto tensor_1_desc = TensorDesc({}, ACL_HIFLOAT8, ACL_FORMAT_ND)
823+ .ValueRange(-2, 2)
824+ .Value(vector<float>{
825+ 1,
826+ });
827+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
828+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
829+ auto out_tensor_desc = TensorDesc(
830+ {
831+ 8,
832+ },
833+ ACL_FLOAT16, ACL_FORMAT_ND);
834+ int dstType = ACL_FLOAT16;
835+ bool sqrtMode = false;
836+ 
837+ auto ut = OP_API_UT(
838+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
839+ OUTPUT(out_tensor_desc));
840+ 
841+ uint64_t workspace_size = 0;
842+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
843+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
844+}
845+ 
846+TEST_F(l2_ascend_anti_quant_test, ascend950PR_input_out_dtype_dif_1)
847+{
848+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
849+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
850+ .ValueRange(-2, 2)
851+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
852+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
853+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
854+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
855+ int dstType = ACL_FLOAT16;
856+ bool sqrtMode = false;
857+ 
858+ auto ut = OP_API_UT(
859+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
860+ OUTPUT(out_tensor_desc));
861+ 
862+ uint64_t workspace_size = 0;
863+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
864+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
865+}
866+ 
867+TEST_F(l2_ascend_anti_quant_test, ascend950PR_input_out_dtype_dif_2)
868+{
869+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
870+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
871+ .ValueRange(-2, 2)
872+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
873+ auto tensor_scale = TensorDesc({1}, ACL_BF16, ACL_FORMAT_ND);
874+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
875+ int dstType = ACL_FLOAT16;
876+ bool sqrtMode = false;
877+ 
878+ auto ut = OP_API_UT(
879+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, (aclTensor*)nullptr, dstType, sqrtMode),
880+ OUTPUT(out_tensor_desc));
881+ 
882+ uint64_t workspace_size = 0;
883+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
884+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
885+}
886+ 
887+TEST_F(l2_ascend_anti_quant_test, ascend950PR_offset_dim_not_1)
888+{
889+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
890+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
891+ .ValueRange(-2, 2)
892+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
893+ auto tensor_scale = TensorDesc({1, 2}, ACL_FLOAT, ACL_FORMAT_ND);
894+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
895+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_FLOAT16, ACL_FORMAT_ND);
896+ int dstType = ACL_FLOAT16;
897+ bool sqrtMode = false;
898+ 
899+ auto ut = OP_API_UT(
900+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
901+ OUTPUT(out_tensor_desc));
902+ 
903+ uint64_t workspace_size = 0;
904+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
905+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
906+}
907+ 
908+TEST_F(l2_ascend_anti_quant_test, ascend950PR_scale_dim_not_1_Nonoffset)
909+{
910+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
911+ auto tensor_1_desc = TensorDesc({3, 5}, ACL_INT8, ACL_FORMAT_ND)
912+ .ValueRange(-2, 2)
913+ .Value(vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
914+ auto tensor_scale = TensorDesc({1, 2}, ACL_FLOAT, ACL_FORMAT_ND);
915+ auto out_tensor_desc = TensorDesc({3, 5}, ACL_BF16, ACL_FORMAT_ND);
916+ int dstType = ACL_FLOAT16;
917+ bool sqrtMode = false;
918+ 
919+ auto ut = OP_API_UT(
920+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, (aclTensor*)nullptr, dstType, sqrtMode),
921+ OUTPUT(out_tensor_desc));
922+ 
923+ uint64_t workspace_size = 0;
924+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
925+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
926+}
927+ 
928+TEST_F(l2_ascend_anti_quant_test, ascend950PR_empty_tensor)
929+{
930+ op::SocVersionManager versionManager(op::SocVersion::ASCEND950);
931+ auto tensor_1_desc = TensorDesc({3, 0}, ACL_INT8, ACL_FORMAT_ND).ValueRange(-2, 2);
932+ auto tensor_scale = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
933+ auto tensor_offset = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND);
934+ auto out_tensor_desc = TensorDesc({3, 0}, ACL_FLOAT16, ACL_FORMAT_ND);
935+ int dstType = ACL_FLOAT16;
936+ bool sqrtMode = false;
937+ 
938+ auto ut = OP_API_UT(
939+ aclnnAscendAntiQuant, INPUT(tensor_1_desc, tensor_scale, tensor_offset, dstType, sqrtMode),
940+ OUTPUT(out_tensor_desc));
941+ 
942+ uint64_t workspace_size = 0;
943+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size);
944+ EXPECT_EQ(aclRet, ACLNN_SUCCESS);
945+}
Aquant/ascend_anti_quant_v2/tests/ut/op_host/test_ascend_anti_quant_v2_infershape.cpp+58-0文件内容审核中,请稍后刷新重试
Aquant/ascend_anti_quant_v2/tests/ut/op_host/test_ascend_anti_quant_v2_tiling.cpp+1166-0
@@ -0,0 +1,1166 @@
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+#include <iostream>
11+#include <fstream>
12+#include <vector>
13+ 
14+#include <gtest/gtest.h>
15+#include "log/log.h"
16+#include "platform/platform_infos_def.h"
17+#include "ut_op_util.h"
18+#include "kernel_run_context_facker.h"
19+#include "test_cube_util.h"
20+#include "exe_graph/runtime/storage_format.h"
21+#include "exe_graph/runtime/storage_shape.h"
22+ 
23+using namespace std;
24+using namespace ge;
25+using namespace ut_util;
26+ 
27+class AscendAntiQuantV2Tiling : public testing::Test {
28+protected:
29+ static void SetUpTestCase()
30+ {
31+ std::cout << "AscendAntiQuantV2Tiling SetUp" << std::endl;
32+ }
33+ 
34+ static void TearDownTestCase()
35+ {
36+ std::cout << "AscendAntiQuantV2Tiling TearDown" << std::endl;
37+ }
38+};
39+ 
40+struct AscendAntiQuantV2CompileInfo {
41+ int32_t vectorCoreNum = 0;
42+ uint64_t ubSize = 0;
43+ bool isAscend910B = false;
44+};
45+ 
46+static string TilingData2Str(const gert::TilingData* tiling_data)
47+{
48+ auto data = tiling_data->GetData();
49+ string result;
50+ for (size_t i = 0; i < tiling_data->GetDataSize(); i += sizeof(int64_t)) {
51+ result += std::to_string((reinterpret_cast<const int64_t*>(tiling_data->GetData())[i / sizeof(int64_t)]));
52+ result += " ";
53+ }
54+ 
55+ return result;
56+}
57+ 
58+static void InitPlatForm(
59+ fe::PlatFormInfos& platform_info, map<string, string>& soc_infos, map<string, string>& aicore_spec,
60+ map<string, string>& intrinsics)
61+{
62+ string compile_info_string = R"({
63+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
64+ "Intrinsic_fix_pipe_l0c2out": false,
65+ "Intrinsic_data_move_l12ub": true,
66+ "Intrinsic_data_move_l0c2ub": true,
67+ "Intrinsic_data_move_out2l1_nd2nz": false,
68+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
69+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
70+ "CORE_NUM": 48}
71+ })";
72+ GetPlatFormInfos(compile_info_string.c_str(), soc_infos, aicore_spec, intrinsics);
73+ 
74+ platform_info.Init();
75+}
76+ 
77+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_per_channel_950_1)
78+{
79+ // test int8, block cut last axis
80+ fe::PlatFormInfos platform_info;
81+ map<string, string> soc_infos;
82+ map<string, string> aicore_spec;
83+ map<string, string> intrinsics;
84+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
85+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
86+ string compile_info_string = R"({
87+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
88+ "Intrinsic_fix_pipe_l0c2out": false,
89+ "Intrinsic_data_move_l12ub": true,
90+ "Intrinsic_data_move_l0c2ub": true,
91+ "Intrinsic_data_move_out2l1_nd2nz": false,
92+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
93+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
94+ "CORE_NUM": 48}
95+ })";
96+ 
97+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
98+ gert::StorageShape scale_shape = {{10240}, {10240}};
99+ gert::StorageShape offset_shape = {{10240}, {10240}};
100+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
101+ 
102+ AscendAntiQuantV2CompileInfo compile_info;
103+ std::string op_type("AscendAntiQuantV2");
104+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
105+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
106+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
107+ 
108+ // tilingParseFunc simulate
109+ auto kernel_holder =
110+ gert::KernelRunContextFaker()
111+ .KernelIONum(2, 1)
112+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
113+ .Outputs({&compile_info})
114+ .Build();
115+ 
116+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
117+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
118+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
119+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
120+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
121+ "AICoreintrinsicDtypeMap", intrinsics);
122+ 
123+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
124+ 
125+ // tilingFunc simulate
126+ auto param = gert::TilingData::CreateCap(4096);
127+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
128+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
129+ ASSERT_NE(param, nullptr);
130+ auto holder = gert::TilingContextFaker()
131+ .NodeIoNum(3, 1)
132+ .IrInstanceNum({1, 1, 1})
133+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
134+ .OutputShapes({&out_shape})
135+ .CompileInfo(&compile_info)
136+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
137+ .NodeInputTd(0, ge::DT_INT8, ge::FORMAT_ND, ge::FORMAT_ND)
138+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
139+ .NodeInputTd(2, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
140+ .NodeOutputTd(0, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
141+ .NodeAttrs({
142+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(27)},
143+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
144+ })
145+ .TilingData(param.get())
146+ .Workspace(ws_size)
147+ .Build();
148+ 
149+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
150+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
151+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
152+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
153+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
154+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
155+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
156+ 
157+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
158+ 
159+}
160+ 
161+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_per_tensor_950_2)
162+{
163+ // test hifloat8, block cut last axis
164+ fe::PlatFormInfos platform_info;
165+ map<string, string> soc_infos;
166+ map<string, string> aicore_spec;
167+ map<string, string> intrinsics;
168+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
169+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
170+ map<string, string> npuarchs = {{"NpuArch", "3510"}};
171+ string compile_info_string = R"({
172+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
173+ "Intrinsic_fix_pipe_l0c2out": false,
174+ "Intrinsic_data_move_l12ub": true,
175+ "Intrinsic_data_move_l0c2ub": true,
176+ "Intrinsic_data_move_out2l1_nd2nz": false,
177+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
178+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
179+ "CORE_NUM": 48}
180+ })";
181+ 
182+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
183+ gert::StorageShape scale_shape = {{1}, {1}};
184+ gert::StorageShape offset_shape = {{1}, {1}};
185+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
186+ 
187+ AscendAntiQuantV2CompileInfo compile_info;
188+ std::string op_type("AscendAntiQuantV2");
189+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
190+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
191+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
192+ 
193+ // tilingParseFunc simulate
194+ auto kernel_holder =
195+ gert::KernelRunContextFaker()
196+ .KernelIONum(2, 1)
197+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
198+ .Outputs({&compile_info})
199+ .Build();
200+ 
201+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
202+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
203+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
204+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
205+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
206+ "AICoreintrinsicDtypeMap", intrinsics);
207+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
208+ 
209+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
210+ 
211+ // tilingFunc simulate
212+ auto param = gert::TilingData::CreateCap(4096);
213+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
214+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
215+ ASSERT_NE(param, nullptr);
216+ auto holder = gert::TilingContextFaker()
217+ .NodeIoNum(3, 1)
218+ .IrInstanceNum({1, 1, 1})
219+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
220+ .OutputShapes({&out_shape})
221+ .CompileInfo(&compile_info)
222+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
223+ .NodeInputTd(0, ge::DT_HIFLOAT8, ge::FORMAT_ND, ge::FORMAT_ND)
224+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
225+ .NodeInputTd(2, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
226+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
227+ .NodeAttrs({
228+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
229+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
230+ })
231+ .TilingData(param.get())
232+ .Workspace(ws_size)
233+ .Build();
234+ 
235+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
236+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
237+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
238+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
239+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
240+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
241+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
242+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
243+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
244+ 
245+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
246+ 
247+}
248+ 
249+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_per_channel_no_offset_950_3)
250+{
251+ // test float8_e5m2, block cut last axis
252+ fe::PlatFormInfos platform_info;
253+ map<string, string> soc_infos;
254+ map<string, string> aicore_spec;
255+ map<string, string> intrinsics;
256+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
257+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
258+ string compile_info_string = R"({
259+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
260+ "Intrinsic_fix_pipe_l0c2out": false,
261+ "Intrinsic_data_move_l12ub": true,
262+ "Intrinsic_data_move_l0c2ub": true,
263+ "Intrinsic_data_move_out2l1_nd2nz": false,
264+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
265+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
266+ "CORE_NUM": 48}
267+ })";
268+ 
269+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
270+ gert::StorageShape scale_shape = {{10240}, {10240}};
271+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
272+ 
273+ AscendAntiQuantV2CompileInfo compile_info;
274+ std::string op_type("AscendAntiQuantV2");
275+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
276+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
277+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
278+ 
279+ // tilingParseFunc simulate
280+ auto kernel_holder =
281+ gert::KernelRunContextFaker()
282+ .KernelIONum(2, 1)
283+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
284+ .Outputs({&compile_info})
285+ .Build();
286+ 
287+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
288+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
289+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
290+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
291+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
292+ "AICoreintrinsicDtypeMap", intrinsics);
293+ 
294+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
295+ 
296+ // tilingFunc simulate
297+ auto param = gert::TilingData::CreateCap(4096);
298+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
299+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
300+ ASSERT_NE(param, nullptr);
301+ auto holder = gert::TilingContextFaker()
302+ .NodeIoNum(3, 1)
303+ .IrInstanceNum({1, 1, 0})
304+ .InputShapes({&x_shape, &scale_shape})
305+ .OutputShapes({&out_shape})
306+ .CompileInfo(&compile_info)
307+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
308+ .NodeInputTd(0, ge::DT_FLOAT8_E5M2, ge::FORMAT_ND, ge::FORMAT_ND)
309+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
310+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
311+ .NodeAttrs({
312+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
313+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
314+ })
315+ .TilingData(param.get())
316+ .Workspace(ws_size)
317+ .Build();
318+ 
319+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
320+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
321+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
322+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
323+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
324+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
325+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
326+ 
327+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
328+}
329+ 
330+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_per_tensor_no_offset_950_4)
331+{
332+ // test float8_e4m3, block cut last axis
333+ fe::PlatFormInfos platform_info;
334+ map<string, string> soc_infos;
335+ map<string, string> aicore_spec;
336+ map<string, string> intrinsics;
337+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
338+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
339+ string compile_info_string = R"({
340+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
341+ "Intrinsic_fix_pipe_l0c2out": false,
342+ "Intrinsic_data_move_l12ub": true,
343+ "Intrinsic_data_move_l0c2ub": true,
344+ "Intrinsic_data_move_out2l1_nd2nz": false,
345+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
346+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
347+ "CORE_NUM": 48}
348+ })";
349+ 
350+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
351+ gert::StorageShape scale_shape = {{1}, {1}};
352+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
353+ 
354+ AscendAntiQuantV2CompileInfo compile_info;
355+ std::string op_type("AscendAntiQuantV2");
356+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
357+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
358+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
359+ 
360+ // tilingParseFunc simulate
361+ auto kernel_holder =
362+ gert::KernelRunContextFaker()
363+ .KernelIONum(2, 1)
364+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
365+ .Outputs({&compile_info})
366+ .Build();
367+ 
368+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
369+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
370+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
371+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
372+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
373+ "AICoreintrinsicDtypeMap", intrinsics);
374+ 
375+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
376+ 
377+ // tilingFunc simulate
378+ auto param = gert::TilingData::CreateCap(4096);
379+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
380+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
381+ ASSERT_NE(param, nullptr);
382+ auto holder = gert::TilingContextFaker()
383+ .NodeIoNum(3, 1)
384+ .IrInstanceNum({1, 1, 0})
385+ .InputShapes({&x_shape, &scale_shape})
386+ .OutputShapes({&out_shape})
387+ .CompileInfo(&compile_info)
388+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
389+ .NodeInputTd(0, ge::DT_FLOAT8_E4M3FN, ge::FORMAT_ND, ge::FORMAT_ND)
390+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
391+ .NodeOutputTd(0, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
392+ .NodeAttrs({
393+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(27)},
394+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
395+ })
396+ .TilingData(param.get())
397+ .Workspace(ws_size)
398+ .Build();
399+ 
400+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
401+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
402+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
403+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
404+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
405+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
406+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
407+ 
408+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
409+}
410+ 
411+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_int4_950_5)
412+{
413+ // test int4, block cut last axis
414+ fe::PlatFormInfos platform_info;
415+ map<string, string> soc_infos;
416+ map<string, string> aicore_spec;
417+ map<string, string> intrinsics;
418+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
419+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
420+ string compile_info_string = R"({
421+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
422+ "Intrinsic_fix_pipe_l0c2out": false,
423+ "Intrinsic_data_move_l12ub": true,
424+ "Intrinsic_data_move_l0c2ub": true,
425+ "Intrinsic_data_move_out2l1_nd2nz": false,
426+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
427+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
428+ "CORE_NUM": 48}
429+ })";
430+ 
431+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
432+ gert::StorageShape scale_shape = {{10240}, {10240}};
433+ gert::StorageShape offset_shape = {{10240}, {10240}};
434+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
435+ 
436+ AscendAntiQuantV2CompileInfo compile_info;
437+ std::string op_type("AscendAntiQuantV2");
438+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
439+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
440+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
441+ 
442+ // tilingParseFunc simulate
443+ auto kernel_holder =
444+ gert::KernelRunContextFaker()
445+ .KernelIONum(2, 1)
446+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
447+ .Outputs({&compile_info})
448+ .Build();
449+ 
450+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
451+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
452+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
453+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
454+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
455+ "AICoreintrinsicDtypeMap", intrinsics);
456+ 
457+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
458+ 
459+ // tilingFunc simulate
460+ auto param = gert::TilingData::CreateCap(4096);
461+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
462+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
463+ ASSERT_NE(param, nullptr);
464+ auto holder = gert::TilingContextFaker()
465+ .NodeIoNum(3, 1)
466+ .IrInstanceNum({1, 1, 1})
467+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
468+ .OutputShapes({&out_shape})
469+ .CompileInfo(&compile_info)
470+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
471+ .NodeInputTd(0, ge::DT_INT4, ge::FORMAT_ND, ge::FORMAT_ND)
472+ .NodeInputTd(1, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
473+ .NodeInputTd(2, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
474+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
475+ .NodeAttrs({
476+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
477+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
478+ })
479+ .TilingData(param.get())
480+ .Workspace(ws_size)
481+ .Build();
482+ 
483+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
484+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
485+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
486+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
487+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
488+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
489+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
490+ 
491+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
492+}
493+ 
494+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_per_head_950_6)
495+{
496+ // test int4, block cut -2 axis
497+ fe::PlatFormInfos platform_info;
498+ map<string, string> soc_infos;
499+ map<string, string> aicore_spec;
500+ map<string, string> intrinsics;
501+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
502+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
503+ string compile_info_string = R"({
504+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
505+ "Intrinsic_fix_pipe_l0c2out": false,
506+ "Intrinsic_data_move_l12ub": true,
507+ "Intrinsic_data_move_l0c2ub": true,
508+ "Intrinsic_data_move_out2l1_nd2nz": false,
509+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
510+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
511+ "CORE_NUM": 48}
512+ })";
513+ 
514+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
515+ gert::StorageShape scale_shape = {{1, 2, 1}, {1, 2, 1}};
516+ gert::StorageShape offset_shape = {{1, 2, 1}, {1, 2, 1}};
517+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
518+ 
519+ AscendAntiQuantV2CompileInfo compile_info;
520+ std::string op_type("AscendAntiQuantV2");
521+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
522+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
523+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
524+ 
525+ // tilingParseFunc simulate
526+ auto kernel_holder =
527+ gert::KernelRunContextFaker()
528+ .KernelIONum(2, 1)
529+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
530+ .Outputs({&compile_info})
531+ .Build();
532+ 
533+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
534+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
535+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
536+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
537+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
538+ "AICoreintrinsicDtypeMap", intrinsics);
539+ 
540+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
541+ 
542+ // tilingFunc simulate
543+ auto param = gert::TilingData::CreateCap(4096);
544+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
545+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
546+ ASSERT_NE(param, nullptr);
547+ auto holder = gert::TilingContextFaker()
548+ .NodeIoNum(3, 1)
549+ .IrInstanceNum({1, 1, 1})
550+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
551+ .OutputShapes({&out_shape})
552+ .CompileInfo(&compile_info)
553+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
554+ .NodeInputTd(0, ge::DT_INT4, ge::FORMAT_ND, ge::FORMAT_ND)
555+ .NodeInputTd(1, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
556+ .NodeInputTd(2, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
557+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
558+ .NodeAttrs({
559+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
560+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
561+ })
562+ .TilingData(param.get())
563+ .Workspace(ws_size)
564+ .Build();
565+ 
566+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
567+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
568+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
569+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
570+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
571+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
572+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
573+ 
574+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
575+}
576+ 
577+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_per_head_950_7)
578+{
579+ // test int8, block cut -2 axis
580+ fe::PlatFormInfos platform_info;
581+ map<string, string> soc_infos;
582+ map<string, string> aicore_spec;
583+ map<string, string> intrinsics;
584+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
585+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
586+ string compile_info_string = R"({
587+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
588+ "Intrinsic_fix_pipe_l0c2out": false,
589+ "Intrinsic_data_move_l12ub": true,
590+ "Intrinsic_data_move_l0c2ub": true,
591+ "Intrinsic_data_move_out2l1_nd2nz": false,
592+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
593+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
594+ "CORE_NUM": 48}
595+ })";
596+ 
597+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
598+ gert::StorageShape scale_shape = {{2}, {2}};
599+ gert::StorageShape offset_shape = {{2}, {2}};
600+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
601+ 
602+ AscendAntiQuantV2CompileInfo compile_info;
603+ std::string op_type("AscendAntiQuantV2");
604+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
605+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
606+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
607+ 
608+ // tilingParseFunc simulate
609+ auto kernel_holder =
610+ gert::KernelRunContextFaker()
611+ .KernelIONum(2, 1)
612+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
613+ .Outputs({&compile_info})
614+ .Build();
615+ 
616+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
617+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
618+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
619+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
620+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
621+ "AICoreintrinsicDtypeMap", intrinsics);
622+ 
623+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
624+ 
625+ // tilingFunc simulate
626+ auto param = gert::TilingData::CreateCap(4096);
627+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
628+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
629+ ASSERT_NE(param, nullptr);
630+ auto holder = gert::TilingContextFaker()
631+ .NodeIoNum(3, 1)
632+ .IrInstanceNum({1, 1, 1})
633+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
634+ .OutputShapes({&out_shape})
635+ .CompileInfo(&compile_info)
636+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
637+ .NodeInputTd(0, ge::DT_INT8, ge::FORMAT_ND, ge::FORMAT_ND)
638+ .NodeInputTd(1, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
639+ .NodeInputTd(2, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
640+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
641+ .NodeAttrs({
642+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
643+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
644+ })
645+ .TilingData(param.get())
646+ .Workspace(ws_size)
647+ .Build();
648+ 
649+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
650+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
651+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
652+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
653+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
654+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
655+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
656+ 
657+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
658+}
659+ 
660+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_per_head_no_offset_950_8)
661+{
662+ // test float8_e5m2, block cut -2 axis
663+ fe::PlatFormInfos platform_info;
664+ map<string, string> soc_infos;
665+ map<string, string> aicore_spec;
666+ map<string, string> intrinsics;
667+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
668+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
669+ string compile_info_string = R"({
670+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
671+ "Intrinsic_fix_pipe_l0c2out": false,
672+ "Intrinsic_data_move_l12ub": true,
673+ "Intrinsic_data_move_l0c2ub": true,
674+ "Intrinsic_data_move_out2l1_nd2nz": false,
675+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
676+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
677+ "CORE_NUM": 48}
678+ })";
679+ 
680+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
681+ gert::StorageShape scale_shape = {{2}, {2}};
682+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
683+ 
684+ AscendAntiQuantV2CompileInfo compile_info;
685+ std::string op_type("AscendAntiQuantV2");
686+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
687+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
688+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
689+ 
690+ // tilingParseFunc simulate
691+ auto kernel_holder =
692+ gert::KernelRunContextFaker()
693+ .KernelIONum(2, 1)
694+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
695+ .Outputs({&compile_info})
696+ .Build();
697+ 
698+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
699+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
700+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
701+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
702+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
703+ "AICoreintrinsicDtypeMap", intrinsics);
704+ 
705+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
706+ 
707+ // tilingFunc simulate
708+ auto param = gert::TilingData::CreateCap(4096);
709+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
710+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
711+ ASSERT_NE(param, nullptr);
712+ auto holder = gert::TilingContextFaker()
713+ .NodeIoNum(3, 1)
714+ .IrInstanceNum({1, 1, 0})
715+ .InputShapes({&x_shape, &scale_shape})
716+ .OutputShapes({&out_shape})
717+ .CompileInfo(&compile_info)
718+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
719+ .NodeInputTd(0, ge::DT_FLOAT8_E5M2, ge::FORMAT_ND, ge::FORMAT_ND)
720+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
721+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
722+ .NodeAttrs({
723+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
724+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
725+ })
726+ .TilingData(param.get())
727+ .Workspace(ws_size)
728+ .Build();
729+ 
730+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
731+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
732+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
733+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
734+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
735+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
736+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
737+ 
738+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS);
739+}
740+ 
741+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_950_error_shape_1)
742+{
743+ // test int4, blcok cut last axis
744+ fe::PlatFormInfos platform_info;
745+ map<string, string> soc_infos;
746+ map<string, string> aicore_spec;
747+ map<string, string> intrinsics;
748+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
749+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
750+ string compile_info_string = R"({
751+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
752+ "Intrinsic_fix_pipe_l0c2out": false,
753+ "Intrinsic_data_move_l12ub": true,
754+ "Intrinsic_data_move_l0c2ub": true,
755+ "Intrinsic_data_move_out2l1_nd2nz": false,
756+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
757+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
758+ "CORE_NUM": 48}
759+ })";
760+ 
761+ gert::StorageShape x_shape = {{4, 1280, 1021}, {4, 1280, 1021}};
762+ gert::StorageShape scale_shape = {{1}, {1}};
763+ gert::StorageShape offset_shape = {{1}, {1}};
764+ gert::StorageShape out_shape = {{4, 1280, 1021}, {4, 1280, 1021}};
765+ 
766+ AscendAntiQuantV2CompileInfo compile_info;
767+ std::string op_type("AscendAntiQuantV2");
768+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
769+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
770+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
771+ 
772+ // tilingParseFunc simulate
773+ auto kernel_holder =
774+ gert::KernelRunContextFaker()
775+ .KernelIONum(2, 1)
776+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
777+ .Outputs({&compile_info})
778+ .Build();
779+ 
780+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
781+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
782+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
783+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
784+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
785+ "AICoreintrinsicDtypeMap", intrinsics);
786+ 
787+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
788+ 
789+ // tilingFunc simulate
790+ auto param = gert::TilingData::CreateCap(4096);
791+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
792+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
793+ ASSERT_NE(param, nullptr);
794+ auto holder = gert::TilingContextFaker()
795+ .NodeIoNum(3, 1)
796+ .IrInstanceNum({1, 1, 1})
797+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
798+ .OutputShapes({&out_shape})
799+ .CompileInfo(&compile_info)
800+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
801+ .NodeInputTd(0, ge::DT_INT4, ge::FORMAT_ND, ge::FORMAT_ND)
802+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
803+ .NodeInputTd(2, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
804+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
805+ .NodeAttrs({
806+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
807+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(true)}
808+ })
809+ .TilingData(param.get())
810+ .Workspace(ws_size)
811+ .Build();
812+ 
813+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
814+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
815+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
816+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
817+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
818+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
819+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
820+ 
821+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_FAILED);
822+}
823+ 
824+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_950_error_shape_2)
825+{
826+ // test hifloat8, blcok cut last axis
827+ fe::PlatFormInfos platform_info;
828+ map<string, string> soc_infos;
829+ map<string, string> aicore_spec;
830+ map<string, string> intrinsics;
831+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
832+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
833+ map<string, string> npuarchs = {{"NpuArch", "3510"}};
834+ string compile_info_string = R"({
835+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
836+ "Intrinsic_fix_pipe_l0c2out": false,
837+ "Intrinsic_data_move_l12ub": true,
838+ "Intrinsic_data_move_l0c2ub": true,
839+ "Intrinsic_data_move_out2l1_nd2nz": false,
840+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
841+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
842+ "CORE_NUM": 48}
843+ })";
844+ 
845+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
846+ gert::StorageShape scale_shape = {{10}, {10}};
847+ gert::StorageShape offset_shape = {{10}, {10}};
848+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
849+ 
850+ AscendAntiQuantV2CompileInfo compile_info;
851+ std::string op_type("AscendAntiQuantV2");
852+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
853+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
854+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
855+ 
856+ // tilingParseFunc simulate
857+ auto kernel_holder =
858+ gert::KernelRunContextFaker()
859+ .KernelIONum(2, 1)
860+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
861+ .Outputs({&compile_info})
862+ .Build();
863+ 
864+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
865+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
866+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
867+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
868+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
869+ "AICoreintrinsicDtypeMap", intrinsics);
870+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
871+ 
872+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
873+ 
874+ // tilingFunc simulate
875+ auto param = gert::TilingData::CreateCap(4096);
876+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
877+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
878+ ASSERT_NE(param, nullptr);
879+ auto holder = gert::TilingContextFaker()
880+ .NodeIoNum(3, 1)
881+ .IrInstanceNum({1, 1, 1})
882+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
883+ .OutputShapes({&out_shape})
884+ .CompileInfo(&compile_info)
885+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
886+ .NodeInputTd(0, ge::DT_HIFLOAT8, ge::FORMAT_ND, ge::FORMAT_ND)
887+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
888+ .NodeInputTd(2, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
889+ .NodeOutputTd(0, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
890+ .NodeAttrs({
891+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(27)},
892+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
893+ })
894+ .TilingData(param.get())
895+ .Workspace(ws_size)
896+ .Build();
897+ 
898+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
899+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
900+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
901+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
902+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
903+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
904+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
905+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
906+ 
907+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_FAILED);
908+}
909+ 
910+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_950_error_shape_3)
911+{
912+ // test float8_e5m2, blcok cut last axis
913+ fe::PlatFormInfos platform_info;
914+ map<string, string> soc_infos;
915+ map<string, string> aicore_spec;
916+ map<string, string> intrinsics;
917+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
918+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
919+ map<string, string> npuarchs = {{"NpuArch", "3510"}};
920+ string compile_info_string = R"({
921+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
922+ "Intrinsic_fix_pipe_l0c2out": false,
923+ "Intrinsic_data_move_l12ub": true,
924+ "Intrinsic_data_move_l0c2ub": true,
925+ "Intrinsic_data_move_out2l1_nd2nz": false,
926+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
927+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
928+ "CORE_NUM": 48}
929+ })";
930+ 
931+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
932+ gert::StorageShape scale_shape = {{2, 10240}, {2, 10240}};
933+ gert::StorageShape offset_shape = {{2, 10240}, {2, 10240}};
934+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
935+ 
936+ AscendAntiQuantV2CompileInfo compile_info;
937+ std::string op_type("AscendAntiQuantV2");
938+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
939+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
940+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
941+ 
942+ // tilingParseFunc simulate
943+ auto kernel_holder =
944+ gert::KernelRunContextFaker()
945+ .KernelIONum(2, 1)
946+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
947+ .Outputs({&compile_info})
948+ .Build();
949+ 
950+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
951+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
952+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
953+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
954+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
955+ "AICoreintrinsicDtypeMap", intrinsics);
956+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
957+ 
958+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
959+ 
960+ // tilingFunc simulate
961+ auto param = gert::TilingData::CreateCap(4096);
962+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
963+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
964+ ASSERT_NE(param, nullptr);
965+ auto holder = gert::TilingContextFaker()
966+ .NodeIoNum(3, 1)
967+ .IrInstanceNum({1, 1, 1})
968+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
969+ .OutputShapes({&out_shape})
970+ .CompileInfo(&compile_info)
971+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
972+ .NodeInputTd(0, ge::DT_FLOAT8_E5M2, ge::FORMAT_ND, ge::FORMAT_ND)
973+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
974+ .NodeInputTd(2, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
975+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
976+ .NodeAttrs({
977+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
978+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(false)}
979+ })
980+ .TilingData(param.get())
981+ .Workspace(ws_size)
982+ .Build();
983+ 
984+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
985+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
986+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
987+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
988+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
989+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
990+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
991+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
992+ 
993+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_FAILED);
994+}
995+ 
996+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_950_error_sqrtMode_4)
997+{
998+ // test float8_e5m2, blcok cut last axis
999+ fe::PlatFormInfos platform_info;
1000+ map<string, string> soc_infos;
1001+ map<string, string> aicore_spec;
1002+ map<string, string> intrinsics;
1003+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
1004+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
1005+ map<string, string> npuarchs = {{"NpuArch", "3510"}};
1006+ string compile_info_string = R"({
1007+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
1008+ "Intrinsic_fix_pipe_l0c2out": false,
1009+ "Intrinsic_data_move_l12ub": true,
1010+ "Intrinsic_data_move_l0c2ub": true,
1011+ "Intrinsic_data_move_out2l1_nd2nz": false,
1012+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
1013+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
1014+ "CORE_NUM": 48}
1015+ })";
1016+ 
1017+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
1018+ gert::StorageShape scale_shape = {{1, 10240}, {1, 10240}};
1019+ gert::StorageShape offset_shape = {{1, 10240}, {1, 10240}};
1020+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
1021+ 
1022+ AscendAntiQuantV2CompileInfo compile_info;
1023+ std::string op_type("AscendAntiQuantV2");
1024+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
1025+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
1026+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
1027+ 
1028+ // tilingParseFunc simulate
1029+ auto kernel_holder =
1030+ gert::KernelRunContextFaker()
1031+ .KernelIONum(2, 1)
1032+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
1033+ .Outputs({&compile_info})
1034+ .Build();
1035+ 
1036+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
1037+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
1038+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
1039+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
1040+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
1041+ "AICoreintrinsicDtypeMap", intrinsics);
1042+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
1043+ 
1044+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
1045+ 
1046+ // tilingFunc simulate
1047+ auto param = gert::TilingData::CreateCap(4096);
1048+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
1049+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
1050+ ASSERT_NE(param, nullptr);
1051+ auto holder = gert::TilingContextFaker()
1052+ .NodeIoNum(3, 1)
1053+ .IrInstanceNum({1, 1, 1})
1054+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
1055+ .OutputShapes({&out_shape})
1056+ .CompileInfo(&compile_info)
1057+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
1058+ .NodeInputTd(0, ge::DT_FLOAT8_E5M2, ge::FORMAT_ND, ge::FORMAT_ND)
1059+ .NodeInputTd(1, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
1060+ .NodeInputTd(2, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND)
1061+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
1062+ .NodeAttrs({
1063+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
1064+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(true)}
1065+ })
1066+ .TilingData(param.get())
1067+ .Workspace(ws_size)
1068+ .Build();
1069+ 
1070+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
1071+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
1072+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
1073+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
1074+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
1075+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
1076+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
1077+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
1078+ 
1079+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_FAILED);
1080+}
1081+ 
1082+TEST_F(AscendAntiQuantV2Tiling, ascend_anti_quant_v2_tiling_950_error_Float_4)
1083+{
1084+ // test float8_e5m2, blcok cut last axis
1085+ fe::PlatFormInfos platform_info;
1086+ map<string, string> soc_infos;
1087+ map<string, string> aicore_spec;
1088+ map<string, string> intrinsics;
1089+ InitPlatForm(platform_info, soc_infos, aicore_spec, intrinsics);
1090+ map<string, string> socversions = {{"Short_SoC_version", "Ascend950"}, {"NpuArch", "3510"}};
1091+ map<string, string> npuarchs = {{"NpuArch", "3510"}};
1092+ string compile_info_string = R"({
1093+ "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1",
1094+ "Intrinsic_fix_pipe_l0c2out": false,
1095+ "Intrinsic_data_move_l12ub": true,
1096+ "Intrinsic_data_move_l0c2ub": true,
1097+ "Intrinsic_data_move_out2l1_nd2nz": false,
1098+ "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288,
1099+ "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072,
1100+ "CORE_NUM": 48}
1101+ })";
1102+ 
1103+ gert::StorageShape x_shape = {{4, 2, 10240}, {4, 2, 10240}};
1104+ gert::StorageShape scale_shape = {{1, 10240}, {1, 10240}};
1105+ gert::StorageShape offset_shape = {{1, 10240}, {1, 10240}};
1106+ gert::StorageShape out_shape = {{4, 2, 10240}, {4, 2, 10240}};
1107+ 
1108+ AscendAntiQuantV2CompileInfo compile_info;
1109+ std::string op_type("AscendAntiQuantV2");
1110+ ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr);
1111+ auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling;
1112+ auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse;
1113+ 
1114+ // tilingParseFunc simulate
1115+ auto kernel_holder =
1116+ gert::KernelRunContextFaker()
1117+ .KernelIONum(2, 1)
1118+ .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)})
1119+ .Outputs({&compile_info})
1120+ .Build();
1121+ 
1122+ ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init());
1123+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
1124+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
1125+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
1126+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes(
1127+ "AICoreintrinsicDtypeMap", intrinsics);
1128+ kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
1129+ 
1130+ ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS);
1131+ 
1132+ // tilingFunc simulate
1133+ auto param = gert::TilingData::CreateCap(4096);
1134+ auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(16 * 1024 * 1024);
1135+ auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get());
1136+ ASSERT_NE(param, nullptr);
1137+ auto holder = gert::TilingContextFaker()
1138+ .NodeIoNum(3, 1)
1139+ .IrInstanceNum({1, 1, 1})
1140+ .InputShapes({&x_shape, &scale_shape, &offset_shape})
1141+ .OutputShapes({&out_shape})
1142+ .CompileInfo(&compile_info)
1143+ .PlatformInfo(reinterpret_cast<char*>(&platform_info))
1144+ .NodeInputTd(0, ge::DT_FLOAT8_E5M2, ge::FORMAT_ND, ge::FORMAT_ND)
1145+ .NodeInputTd(1, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
1146+ .NodeInputTd(2, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND)
1147+ .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND)
1148+ .NodeAttrs({
1149+ {"dst_type", Ops::NN::AnyValue::CreateFrom<int64_t>(1)},
1150+ {"sqrt_mode", Ops::NN::AnyValue::CreateFrom<bool>(true)}
1151+ })
1152+ .TilingData(param.get())
1153+ .Workspace(ws_size)
1154+ .Build();
1155+ 
1156+ gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>();
1157+ ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr);
1158+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos);
1159+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec);
1160+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore");
1161+ holder.GetContext<gert::TilingContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics);
1162+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", socversions);
1163+ tiling_context->GetPlatformInfo()->SetPlatformRes("version", npuarchs);
1164+ 
1165+ EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_FAILED);
1166+}
Aquant/ascend_anti_quant_v2/tests/ut/op_kernel/CMakeLists.txt+12-0文件内容审核中,请稍后刷新重试
Aquant/ascend_anti_quant_v2/tests/ut/op_kernel/test_ascend_anti_quant_v2_apt.cpp+94-0
@@ -0,0 +1,94 @@
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 test_ascend_anti_quant_v2.cpp
13+ * \brief
14+ */
15+ 
16+#include <array>
17+#include <vector>
18+#include <iostream>
19+#include <string>
20+#include <cstdint>
21+#include "gtest/gtest.h"
22+#include "tikicpulib.h"
23+#include "../../../op_kernel/ascend_anti_quant_v2_apt.cpp"
24+#include <cstdint>
25+ 
26+using namespace std;
27+ 
28+extern "C" __global__ __aicore__ void ascend_anti_quant_v2(
29+ GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling);
30+ 
31+class ascend_anti_quant_v2_test : public testing::Test {
32+protected:
33+ static void SetUpTestCase()
34+ {
35+ cout << "ascend_anti_quant_v2_test SetUp\n" << endl;
36+ }
37+ static void TearDownTestCase()
38+ {
39+ cout << "ascend_anti_quant_v2_test TearDown\n" << endl;
40+ }
41+};
42+ 
43+TEST_F(ascend_anti_quant_v2_test, test_case_100)
44+{
45+ size_t inputXSize = 128 * 512 * sizeof(hifloat8_t);
46+ size_t inputScaleSize = 512 * sizeof(float);
47+ size_t inputOffsetSize = 512 * sizeof(float);
48+ size_t outputYSize = 128 * 512 * sizeof(half);
49+ size_t tiling_data_size = sizeof(AscendAntiQuantV2TilingData);
50+ uint32_t blockDim = 2;
51+ 
52+ uint8_t* x = (uint8_t*)AscendC::GmAlloc(inputXSize);
53+ uint8_t* scale = (uint8_t*)AscendC::GmAlloc(inputScaleSize);
54+ uint8_t* offset = (uint8_t*)AscendC::GmAlloc(inputOffsetSize);
55+ uint8_t* y = (uint8_t*)AscendC::GmAlloc(outputYSize);
56+ 
57+ uint8_t* workSpace = (uint8_t*)AscendC::GmAlloc(1024 * 1024 * 16);
58+ uint8_t* tiling = (uint8_t*)AscendC::GmAlloc(tiling_data_size);
59+ 
60+ char* path_ = get_current_dir_name();
61+ string path(path_);
62+ 
63+ AscendC::SetKernelMode(KernelMode::AIV_MODE);
64+ AscendAntiQuantV2TilingData* tilingDatafromBin = reinterpret_cast<AscendAntiQuantV2TilingData*>(tiling);
65+ 
66+ tilingDatafromBin->numCore = 43;
67+ tilingDatafromBin->blockAxis = 0;
68+ tilingDatafromBin->dim0 = 128;
69+ tilingDatafromBin->dim1 = 512;
70+ tilingDatafromBin->dim2 = 1;
71+ tilingDatafromBin->blockFactor = 3;
72+ tilingDatafromBin->blockTailFactor = 2;
73+ tilingDatafromBin->baseN = 3;
74+ tilingDatafromBin->baseLen = 512;
75+ tilingDatafromBin->hasOffset = 1;
76+ tilingDatafromBin->sqrtMode = 1;
77+ 
78+ ICPU_SET_TILING_KEY(13);
79+ 
80+ auto ascend_anti_quant_v2_kernel = [](GM_ADDR x, GM_ADDR scale, GM_ADDR offset, GM_ADDR y,
81+ GM_ADDR workSpace, GM_ADDR tiling) {
82+ ::ascend_anti_quant_v2<1, 1, 1>(x, scale, offset, y, workSpace, tiling);
83+ };
84+ ICPU_RUN_KF(
85+ ascend_anti_quant_v2_kernel, blockDim, x, scale, offset, y, workSpace, tiling);
86+ 
87+ AscendC::GmFree(x);
88+ AscendC::GmFree(scale);
89+ AscendC::GmFree(offset);
90+ AscendC::GmFree(y);
91+ AscendC::GmFree(workSpace);
92+ AscendC::GmFree(tilingDatafromBin);
93+ free(path_);
94+}
Mscripts/kernel/binary_config/ascendc_config.json+1-0
@@ -535,6 +535,7 @@
535 {"name":"AscendQuant", "compute_units": ["ascend950"], "auto_sync": false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},535 {"name":"AscendQuant", "compute_units": ["ascend950"], "auto_sync": false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},
536 {"name":"Quantize", "compute_units": ["ascend950"], "auto_sync": false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},536 {"name":"Quantize", "compute_units": ["ascend950"], "auto_sync": false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},
537 {"name":"AscendQuantV2", "compute_units": ["ascend310p", "ascend910b", "ascend910_93", "ascend950", "kirinx90", "kirin9030"], "auto_sync": false, "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},537 {"name":"AscendQuantV2", "compute_units": ["ascend310p", "ascend910b", "ascend910_93", "ascend950", "kirinx90", "kirin9030"], "auto_sync": false, "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},
538+ {"name":"AscendAntiQuantV2", "compute_units": ["ascend950"], "auto_sync": false, "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},
538 {"name":"QuantUpdateScatter", "compute_units": ["ascend950"], "auto_sync": false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},539 {"name":"QuantUpdateScatter", "compute_units": ["ascend950"], "auto_sync": false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},
539 {"name":"MSELossV2", "compute_units": ["ascend310p", "ascend910b", "ascend910_93", "ascend950"], "auto_sync" : true},540 {"name":"MSELossV2", "compute_units": ["ascend310p", "ascend910b", "ascend910_93", "ascend950"], "auto_sync" : true},
540 {"name":"BinaryCrossEntropyGrad", "compute_units": ["ascend950"], "auto_sync" : false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},541 {"name":"BinaryCrossEntropyGrad", "compute_units": ["ascend950"], "auto_sync" : false, "impl_mode": "", "compile_options": {"ascend950": ["-mllvm -cce-aicore-dcci-before-kernel-end=false"]}},