已合并
将matmul_compress_dequant算子从math仓迁到nn仓 #4166
wmg1创建于 4月24日
将matmul_compress_dequant算子从math仓迁到nn仓 #4166
已合并
共 33 个文件变更+3864-0
| @@ -293,6 +293,7 @@ | |||
| 293 | | [aclnnMatmul](../../matmul/mat_mul_v3/docs/aclnnMatmul.md) | 完成1到6维张量self与张量mat2的矩阵乘计算。 | 默认确定性实现 | 默认确定性实现 | | 293 | | [aclnnMatmul](../../matmul/mat_mul_v3/docs/aclnnMatmul.md) | 完成1到6维张量self与张量mat2的矩阵乘计算。 | 默认确定性实现 | 默认确定性实现 | |
| 294 | | [aclnnMatmulWeightNz](../../matmul/mat_mul_v3/docs/aclnnMatmulWeightNz.md) | 完成张量self与张量mat2的矩阵乘计算,mat2仅支持昇腾亲和数据排布格式。 | 默认确定性实现 | 默认确定性实现 | | 294 | | [aclnnMatmulWeightNz](../../matmul/mat_mul_v3/docs/aclnnMatmulWeightNz.md) | 完成张量self与张量mat2的矩阵乘计算,mat2仅支持昇腾亲和数据排布格式。 | 默认确定性实现 | 默认确定性实现 | |
| 295 | | [aclnnMatmulCompress](../../matmul/matmul_compress/docs/aclnnMatmulCompress.md) | 进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩,矩阵乘,反量化计算。 | 默认确定性实现 | - | | 295 | | [aclnnMatmulCompress](../../matmul/matmul_compress/docs/aclnnMatmulCompress.md) | 进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩,矩阵乘,反量化计算。 | 默认确定性实现 | - | |
| 296 | +| [aclnnMatmulCompressDequant](../../matmul/matmul_v2_compress_dequant/docs/aclnnMatmulCompressDequant.md) | 进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩,矩阵乘,反量化计算。 | 默认确定性实现 | - | | ||
| 296 | | [aclnnMaxPool](../../pooling/max_pool_v3/docs/aclnnMaxPool.md) | 对于dim=3 或4维的输入张量,进行最大池化(max pooling)操作。 | 默认确定性实现 | 默认确定性实现 | | 297 | | [aclnnMaxPool](../../pooling/max_pool_v3/docs/aclnnMaxPool.md) | 对于dim=3 或4维的输入张量,进行最大池化(max pooling)操作。 | 默认确定性实现 | 默认确定性实现 | |
| 297 | | [aclnnMaxPool2dWithIndices](../../pooling/max_pool3d_with_argmax_v2/docs/aclnnMaxPool2dWithIndices.md) | 对于输入信号的输入通道,提供2维(H,W维度)最大池化(max pooling)操作,输出池化后的值out和索引indices。 | 默认确定性实现 | 默认确定性实现 | | 298 | | [aclnnMaxPool2dWithIndices](../../pooling/max_pool3d_with_argmax_v2/docs/aclnnMaxPool2dWithIndices.md) | 对于输入信号的输入通道,提供2维(H,W维度)最大池化(max pooling)操作,输出池化后的值out和索引indices。 | 默认确定性实现 | 默认确定性实现 | |
| 298 | | [aclnnMaxPool2dWithIndicesBackward](../../pooling/max_pool3d_grad_with_argmax/docs/aclnnMaxPool2dWithIndicesBackward.md) | 正向最大池化aclnnMaxPool2dWithIndices的反向传播。 | 默认非确定性实现,支持配置开启。 | 默认确定性实现 | | 299 | | [aclnnMaxPool2dWithIndicesBackward](../../pooling/max_pool3d_grad_with_argmax/docs/aclnnMaxPool2dWithIndicesBackward.md) | 正向最大池化aclnnMaxPool2dWithIndices的反向传播。 | 默认非确定性实现,支持配置开启。 | 默认确定性实现 | |
| @@ -2397,6 +2397,16 @@ | |||
| 2397 | <td>AI Core</td> | 2397 | <td>AI Core</td> |
| 2398 | <td>完成无损压缩矩阵乘计算。</td> | 2398 | <td>完成无损压缩矩阵乘计算。</td> |
| 2399 | </tr> | 2399 | </tr> |
| 2400 | + <tr> | ||
| 2401 | + <td>matmul</td> | ||
| 2402 | + <td><a href="../../matmul/matmul_v2_compress_dequant/README.md">matmul_v2_compress_dequant</a></td> | ||
| 2403 | + <td>✗</td> | ||
| 2404 | + <td>✗</td> | ||
| 2405 | + <td>✓</td> | ||
| 2406 | + <td>✗</td> | ||
| 2407 | + <td>AI Core</td> | ||
| 2408 | + <td>完成无损解压缩、矩阵乘、反量化计算。</td> | ||
| 2409 | + </tr> | ||
| 2400 | <tr> | 2410 | <tr> |
| 2401 | <td>matmul</td> | 2411 | <td>matmul</td> |
| 2402 | <td><a href="../../matmul/mv/README.md">mv</a></td> | 2412 | <td><a href="../../matmul/mv/README.md">mv</a></td> |
| @@ -0,0 +1,20 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This file is a part of the CANN Open Software. | ||
| 5 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 8 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 13 | +if(NOT ENABLE_TEST AND NOT BENCHMARK) | ||
| 14 | + list(REMOVE_ITEM CURRENT_DIRS tests) | ||
| 15 | +endif() | ||
| 16 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 17 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 18 | + add_subdirectory(${SUB_DIR}) | ||
| 19 | + endif() | ||
| 20 | +endforeach() | ||
| @@ -0,0 +1,114 @@ | |||
| 1 | +# MatMulV2CompressDequant | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +| 产品 | 是否支持 | | ||
| 6 | +| ---- | :----:| | ||
| 7 | +|Ascend 950PR/Ascend 950DT|×| | ||
| 8 | +|Atlas A3 训练系列产品/Atlas A3 推理系列产品|×| | ||
| 9 | +|Atlas A2 训练系列产品/Atlas A2 推理系列产品|×| | ||
| 10 | +|Atlas 200I/500 A2推理产品|×| | ||
| 11 | +|Atlas 推理系列产品|√| | ||
| 12 | +|Atlas 训练系列产品|×| | ||
| 13 | + | ||
| 14 | +## 功能说明 | ||
| 15 | + | ||
| 16 | +- **算子功能**:进行矩阵乘计算时,可先通过msModelSlim工具对右矩阵进行无损压缩,减少内存占用,然后通过本接口完成无损解压缩、矩阵乘和反量化计算。 | ||
| 17 | +- **计算公式**: | ||
| 18 | + | ||
| 19 | + ``` | ||
| 20 | + x2_unzip = unzip(x2, compressIndex, compressInfo) | ||
| 21 | + result = (x1 @ x2_unzip + bias) * deqScale | ||
| 22 | + ``` | ||
| 23 | + | ||
| 24 | + 其中x2表示右矩阵经过msModelSlim工具压缩后的一维数据,x2_unzip是接口内部进行无损解压缩后的数据(与原始右矩阵数据一致)。 | ||
| 25 | + | ||
| 26 | +## 参数说明 | ||
| 27 | + | ||
| 28 | +<table style="undefined;table-layout: fixed; width: 869px"><colgroup> | ||
| 29 | +<col style="width: 144px"> | ||
| 30 | +<col style="width: 166px"> | ||
| 31 | +<col style="width: 343px"> | ||
| 32 | +<col style="width: 114px"> | ||
| 33 | +<col style="width: 102px"> | ||
| 34 | +</colgroup> | ||
| 35 | +<thead> | ||
| 36 | + <tr> | ||
| 37 | + <th>参数名</th> | ||
| 38 | + <th>输入/输出/属性</th> | ||
| 39 | + <th>描述</th> | ||
| 40 | + <th>数据类型</th> | ||
| 41 | + <th>数据格式</th> | ||
| 42 | + </tr></thead> | ||
| 43 | +<tbody> | ||
| 44 | + <tr> | ||
| 45 | + <td>x1</td> | ||
| 46 | + <td>输入张量</td> | ||
| 47 | + <td>矩阵乘的左输入,2维张量。</td> | ||
| 48 | + <td>INT8</td> | ||
| 49 | + <td>ND</td> | ||
| 50 | + </tr> | ||
| 51 | + <tr> | ||
| 52 | + <td>x2</td> | ||
| 53 | + <td>输入张量</td> | ||
| 54 | + <td>压缩后的矩阵乘右输入,1维张量。</td> | ||
| 55 | + <td>INT8</td> | ||
| 56 | + <td>ND</td> | ||
| 57 | + </tr> | ||
| 58 | + <tr> | ||
| 59 | + <td>compressIndex</td> | ||
| 60 | + <td>输入张量</td> | ||
| 61 | + <td>矩阵乘右输入的压缩索引表,1维张量。</td> | ||
| 62 | + <td>INT8</td> | ||
| 63 | + <td>ND</td> | ||
| 64 | + </tr> | ||
| 65 | + <tr> | ||
| 66 | + <td>bias</td> | ||
| 67 | + <td>输入张量</td> | ||
| 68 | + <td>偏置项,支持空指针传入。</td> | ||
| 69 | + <td>INT32</td> | ||
| 70 | + <td>ND</td> | ||
| 71 | + </tr> | ||
| 72 | + <tr> | ||
| 73 | + <td>deqScale</td> | ||
| 74 | + <td>输入张量</td> | ||
| 75 | + <td>反量化参数,数据类型为UINT64。</td> | ||
| 76 | + <td>UINT64</td> | ||
| 77 | + <td>ND</td> | ||
| 78 | + </tr> | ||
| 79 | + <tr> | ||
| 80 | + <td>offsetW</td> | ||
| 81 | + <td>输入张量</td> | ||
| 82 | + <td>矩阵乘右输入的偏移量,当前仅支持空指针传入。</td> | ||
| 83 | + <td>INT8</td> | ||
| 84 | + <td>ND</td> | ||
| 85 | + </tr> | ||
| 86 | + <tr> | ||
| 87 | + <td>offsetX</td> | ||
| 88 | + <td>输入属性</td> | ||
| 89 | + <td>矩阵乘左输入的偏移量,当前仅支持0。</td> | ||
| 90 | + <td>INT32</td> | ||
| 91 | + <td>-</td> | ||
| 92 | + </tr> | ||
| 93 | + <tr> | ||
| 94 | + <td>compressInfo</td> | ||
| 95 | + <td>输入数组</td> | ||
| 96 | + <td>压缩数据相关信息,包括压缩块信息和原始shape等。</td> | ||
| 97 | + <td>INT64</td> | ||
| 98 | + <td>-</td> | ||
| 99 | + </tr> | ||
| 100 | + <tr> | ||
| 101 | + <td>out</td> | ||
| 102 | + <td>输出张量</td> | ||
| 103 | + <td>计算结果输出。</td> | ||
| 104 | + <td>FLOAT16</td> | ||
| 105 | + <td>ND</td> | ||
| 106 | + </tr> | ||
| 107 | +</tbody></table> | ||
| 108 | + | ||
| 109 | +## 约束说明 | ||
| 110 | + | ||
| 111 | +- x1和x2_unzip的Reduce维度大小必须相等。 | ||
| 112 | +- 所有输入张量不支持非连续的Tensor。 | ||
| 113 | +- deqScale需要将原始float类型参数转换为UINT64数据格式。 | ||
| 114 | +- 当前offsetW仅支持空指针,offsetX仅支持0。 | ||
| @@ -0,0 +1,609 @@ | |||
| 1 | +# aclnnMatmulCompressDequant | ||
| 2 | + | ||
| 3 | +[📄 查看源码](https://gitcode.com/cann/ops-nn/tree/master/matmul/matmul_v2_compress_dequant) | ||
| 4 | + | ||
| 5 | +## 产品支持情况 | ||
| 6 | + | ||
| 7 | +| 产品 | 是否支持 | | ||
| 8 | +| :----------------------------------------------------------- | :------: | | ||
| 9 | +| <term>Ascend 950PR/Ascend 950DT</term> | × | | ||
| 10 | +| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | × | | ||
| 11 | +| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | × | | ||
| 12 | +| <term>Atlas 200I/500 A2 推理产品</term> | × | | ||
| 13 | +| <term>Atlas 推理系列产品 </term> | √ | | ||
| 14 | +| <term>Atlas 训练系列产品</term> | × | | ||
| 15 | + | ||
| 16 | +## 功能说明 | ||
| 17 | + | ||
| 18 | +- 接口功能:进行l@r矩阵乘计算时,可先通过msModelSlim工具对r矩阵进行无损压缩,减少r矩阵的内存占用大小,然后通过本接口完成无损解压缩、矩阵乘、反量化计算。 | ||
| 19 | +- 计算公式: | ||
| 20 | + | ||
| 21 | + $$ | ||
| 22 | + x2\_unzip = unzip(x2, compressIndex, compressInfo)\\ | ||
| 23 | + result=(x1 @ x2\_unzip + bias)*deqScale | ||
| 24 | + $$ | ||
| 25 | + | ||
| 26 | + 其中x2表示r矩阵经过msModelSlim工具进行压缩后的一维数据,compressIndex以及compressInfo表示压缩算法相关的信息,$x2\_unzip$是本接口内部进行无损解压缩后的数据(与原始r矩阵数据一致),压缩和调用本接口的详细使用样例参考[调用示例](#调用示例)。 | ||
| 27 | + | ||
| 28 | +## 函数原型 | ||
| 29 | + | ||
| 30 | +每个算子分为[两段式接口](../../../docs/zh/context/两段式接口.md),必须先调用“aclnnMatmulCompressDequantGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnMatmulCompressDequant”接口执行计算。 | ||
| 31 | + | ||
| 32 | +```cpp | ||
| 33 | +aclnnStatus aclnnMatmulCompressDequantGetWorkspaceSize( | ||
| 34 | + const aclTensor* x1, | ||
| 35 | + const aclTensor* x2, | ||
| 36 | + const aclTensor* compressIndex, | ||
| 37 | + const aclTensor* bias, | ||
| 38 | + const aclTensor* deqScale, | ||
| 39 | + const aclTensor* offsetW, | ||
| 40 | + int offsetX, | ||
| 41 | + const aclIntArray* compressInfo, | ||
| 42 | + aclTensor* out, | ||
| 43 | + uint64_t* workspaceSize, | ||
| 44 | + aclOpExecutor** executor) | ||
| 45 | +``` | ||
| 46 | + | ||
| 47 | +```cpp | ||
| 48 | +aclnnStatus aclnnMatmulCompressDequant( | ||
| 49 | + void* workspace, | ||
| 50 | + uint64_t workspaceSize, | ||
| 51 | + aclOpExecutor* executor, | ||
| 52 | + aclrtStream stream) | ||
| 53 | +``` | ||
| 54 | + | ||
| 55 | +## aclnnMatmulCompressDequantGetWorkspaceSize | ||
| 56 | + | ||
| 57 | +- **参数说明** | ||
| 58 | + <table style="undefined;table-layout: fixed; width: 1475px"><colgroup> | ||
| 59 | + <col style="width: 167px"> | ||
| 60 | + <col style="width: 123px"> | ||
| 61 | + <col style="width: 325px"> | ||
| 62 | + <col style="width: 230px"> | ||
| 63 | + <col style="width: 128px"> | ||
| 64 | + <col style="width: 118px"> | ||
| 65 | + <col style="width: 239px"> | ||
| 66 | + <col style="width: 145px"> | ||
| 67 | + </colgroup> | ||
| 68 | + <thead> | ||
| 69 | + <tr> | ||
| 70 | + <th>参数名</th> | ||
| 71 | + <th>输入/输出</th> | ||
| 72 | + <th>描述</th> | ||
| 73 | + <th>使用说明</th> | ||
| 74 | + <th>数据类型</th> | ||
| 75 | + <th>数据格式</th> | ||
| 76 | + <th>维度(shape)</th> | ||
| 77 | + <th>非连续tensor</th> | ||
| 78 | + </tr></thead> | ||
| 79 | + <tbody> | ||
| 80 | + <tr> | ||
| 81 | + <td>x1</td> | ||
| 82 | + <td>输入</td> | ||
| 83 | + <td>表示矩阵乘的左输入。</td> | ||
| 84 | + <td>-</td> | ||
| 85 | + <td>INT8</td> | ||
| 86 | + <td>ND</td> | ||
| 87 | + <td>2</td> | ||
| 88 | + <td>-</td> | ||
| 89 | + </tr> | ||
| 90 | + <tr> | ||
| 91 | + <td>x2</td> | ||
| 92 | + <td>输入</td> | ||
| 93 | + <td>表示压缩后的矩阵乘的右输入,为通过msModelSlim工具中weight_compression模块压缩后的输入。</td> | ||
| 94 | + <td>-</td> | ||
| 95 | + <td>INT8</td> | ||
| 96 | + <td>ND</td> | ||
| 97 | + <td>1</td> | ||
| 98 | + <td>-</td> | ||
| 99 | + </tr> | ||
| 100 | + <tr> | ||
| 101 | + <td>compressIndex</td> | ||
| 102 | + <td>输入</td> | ||
| 103 | + <td>表示矩阵乘右输入的压缩索引表。</td> | ||
| 104 | + <td>通过示例中的msModelSlim工具中获取</td> | ||
| 105 | + <td>INT8</td> | ||
| 106 | + <td>ND</td> | ||
| 107 | + <td>1</td> | ||
| 108 | + <td>-</td> | ||
| 109 | + </tr> | ||
| 110 | + <tr> | ||
| 111 | + <td>bias</td> | ||
| 112 | + <td>输入</td> | ||
| 113 | + <td>参与矩阵乘计算的偏置项。</td> | ||
| 114 | + <td>支持空指针传入。</td> | ||
| 115 | + <td>INT8</td> | ||
| 116 | + <td>ND</td> | ||
| 117 | + <td>2维,shape仅支持(1, n)或者(n),其中n为输出shape(m, n)的n</td> | ||
| 118 | + <td>-</td> | ||
| 119 | + </tr> | ||
| 120 | + <tr> | ||
| 121 | + <td>deqScale</td> | ||
| 122 | + <td>输入</td> | ||
| 123 | + <td>表示反量化参数。</td> | ||
| 124 | + <td>tensor中的值为float通过下述示例中转换后的UINT64的数据。</td> | ||
| 125 | + <td>UINT64</td> | ||
| 126 | + <td>ND</td> | ||
| 127 | + <td>2维,shape支持(1, n)或者(1, 1), 其中n为输出shape(m, n)中的n。</td> | ||
| 128 | + <td>-</td> | ||
| 129 | + </tr> | ||
| 130 | + <tr> | ||
| 131 | + <td>offsetW</td> | ||
| 132 | + <td>输入</td> | ||
| 133 | + <td>标量,表示矩阵乘右输入的偏移量。</td> | ||
| 134 | + <td>当前仅支持空指针传入。</td> | ||
| 135 | + <td>INT8</td> | ||
| 136 | + <td>-</td> | ||
| 137 | + <td>与x2_unzip一致。</td> | ||
| 138 | + <td>-</td> | ||
| 139 | + </tr> | ||
| 140 | + <tr> | ||
| 141 | + <td>offsetX</td> | ||
| 142 | + <td>输入</td> | ||
| 143 | + <td>标量,表示矩阵乘左输入的偏移量。</td> | ||
| 144 | + <td>当前仅支持0。</td> | ||
| 145 | + <td>INT32</td> | ||
| 146 | + <td>-</td> | ||
| 147 | + <td>-</td> | ||
| 148 | + <td>-</td> | ||
| 149 | + </tr> | ||
| 150 | + <tr> | ||
| 151 | + <td>compressInfo</td> | ||
| 152 | + <td>输入</td> | ||
| 153 | + <td>整型数据列表,数据类型为INT64。其中包括压缩块信息tilingN、tilingK(通过msModelSlim工具中weight_compression模块压缩后获取,分别表示压缩前shape(n, k)在n方向和k方向上一个基本压缩块的大小),压缩前x2矩阵原始shape(shape为2维,用(n, k)表示),以及压缩块遍历方向的标识。</td> | ||
| 154 | + <td>-</td> | ||
| 155 | + <td>INT64</td> | ||
| 156 | + <td>-</td> | ||
| 157 | + <td>-</td> | ||
| 158 | + <td>-</td> | ||
| 159 | + </tr> | ||
| 160 | + <tr> | ||
| 161 | + <td>out</td> | ||
| 162 | + <td>输出</td> | ||
| 163 | + <td>计算输出。</td> | ||
| 164 | + <td>-</td> | ||
| 165 | + <td>FLOAT16</td> | ||
| 166 | + <td>ND</td> | ||
| 167 | + <td>2</td> | ||
| 168 | + <td>-</td> | ||
| 169 | + </tr> | ||
| 170 | + <tr> | ||
| 171 | + <td>workspaceSize</td> | ||
| 172 | + <td>出参</td> | ||
| 173 | + <td>返回需要在Device侧申请的workspace大小。</td> | ||
| 174 | + <td>-</td> | ||
| 175 | + <td>-</td> | ||
| 176 | + <td>-</td> | ||
| 177 | + <td>-</td> | ||
| 178 | + <td>-</td> | ||
| 179 | + </tr> | ||
| 180 | + <tr> | ||
| 181 | + <td>executor</td> | ||
| 182 | + <td>出参</td> | ||
| 183 | + <td>返回op执行器,包含了算子计算流程。</td> | ||
| 184 | + <td>-</td> | ||
| 185 | + <td>-</td> | ||
| 186 | + <td>-</td> | ||
| 187 | + <td>-</td> | ||
| 188 | + <td>-</td> | ||
| 189 | + </tr> | ||
| 190 | + </tbody> | ||
| 191 | + </table> | ||
| 192 | + | ||
| 193 | +- **返回值** | ||
| 194 | + | ||
| 195 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../docs/zh/context/aclnn返回码.md)。 | ||
| 196 | + | ||
| 197 | + 第一段接口完成入参校验,出现以下场景时报错: | ||
| 198 | + | ||
| 199 | + <table style="undefined;table-layout: fixed; width: 1475px"><colgroup> | ||
| 200 | + <col style="width: 300px"> | ||
| 201 | + <col style="width: 200px"> | ||
| 202 | + <col style="width: 975px"> | ||
| 203 | + </colgroup> | ||
| 204 | + <thead> | ||
| 205 | + <tr> | ||
| 206 | + <th>返回值</th> | ||
| 207 | + <th>错误码</th> | ||
| 208 | + <th>描述</th> | ||
| 209 | + </tr></thead> | ||
| 210 | + <tbody> | ||
| 211 | + <tr> | ||
| 212 | + <td>ACLNN_ERR_PARAM_NULLPTR</td> | ||
| 213 | + <td>161001</td> | ||
| 214 | + <td>传入的x1、x2或out是空指针。</td> | ||
| 215 | + </tr> | ||
| 216 | + <tr> | ||
| 217 | + <td rowspan="3">ACLNN_ERR_PARAM_INVALID</td> | ||
| 218 | + <td rowspan="3">161002</td> | ||
| 219 | + <td>x1或x2的数据类型和数据格式不在支持的范围之内。</td> | ||
| 220 | + </tr> | ||
| 221 | + <tr> | ||
| 222 | + <td>x1或x2无法做数据类型推导。</td> | ||
| 223 | + </tr> | ||
| 224 | + <tr> | ||
| 225 | + <td>推导出的数据类型无法转换为指定输出out的类型。</td> | ||
| 226 | + </tr> | ||
| 227 | + </tbody> | ||
| 228 | + </table> | ||
| 229 | + | ||
| 230 | +## aclnnMatmulCompressDequant | ||
| 231 | + | ||
| 232 | +- **参数说明** | ||
| 233 | + <table style="undefined;table-layout: fixed; width: 1475px"><colgroup> | ||
| 234 | + <col style="width: 300px"> | ||
| 235 | + <col style="width: 200px"> | ||
| 236 | + <col style="width: 975px"> | ||
| 237 | + </colgroup> | ||
| 238 | + <thead> | ||
| 239 | + <tr> | ||
| 240 | + <th>参数名</th> | ||
| 241 | + <th>输入/输出</th> | ||
| 242 | + <th>描述</th> | ||
| 243 | + </tr></thead> | ||
| 244 | + <tbody> | ||
| 245 | + <tr> | ||
| 246 | + <td>workspace</td> | ||
| 247 | + <td>输入</td> | ||
| 248 | + <td>在Device侧申请的workspace内存地址。</td> | ||
| 249 | + </tr> | ||
| 250 | + <tr> | ||
| 251 | + <td>workspaceSize</td> | ||
| 252 | + <td>输入</td> | ||
| 253 | + <td>在Device侧申请的workspace大小,由第一段接口aclnnMatmulCompressDequantGetWorkspaceSize获取。</td> | ||
| 254 | + </tr> | ||
| 255 | + <tr> | ||
| 256 | + <td>executor</td> | ||
| 257 | + <td>输入</td> | ||
| 258 | + <td>op执行器,包含了算子计算流程。</td> | ||
| 259 | + </tr> | ||
| 260 | + <tr> | ||
| 261 | + <td>stream</td> | ||
| 262 | + <td>输入</td> | ||
| 263 | + <td>指定执行任务的Stream。</td> | ||
| 264 | + </tr> | ||
| 265 | + </tbody> | ||
| 266 | + </table> | ||
| 267 | + | ||
| 268 | +- **返回值** | ||
| 269 | + | ||
| 270 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../docs/zh/context/aclnn返回码.md)。 | ||
| 271 | + | ||
| 272 | +## 约束说明 | ||
| 273 | + | ||
| 274 | +- 确定性计算: | ||
| 275 | + - aclnnMatmulCompressDequant默认确定性实现。 | ||
| 276 | + | ||
| 277 | +## 调用示例 | ||
| 278 | + | ||
| 279 | +- **准备压缩前的数据** | ||
| 280 | + | ||
| 281 | + 假设通过脚本gen_data.py生成输入数据,示例如下,仅供参考: | ||
| 282 | + | ||
| 283 | + ```python | ||
| 284 | + import numpy as np | ||
| 285 | + import os | ||
| 286 | + import sys | ||
| 287 | + from numpy import random | ||
| 288 | + | ||
| 289 | + def write2file(data, path): | ||
| 290 | + with open(path, 'wb') as f: | ||
| 291 | + data.tofile(f) | ||
| 292 | + | ||
| 293 | + if not os.path.exists("./data"): | ||
| 294 | + os.mkdir("./data") | ||
| 295 | + | ||
| 296 | + if len(sys.argv) != 4: | ||
| 297 | + print("Usage: python gen_data.py m k n") | ||
| 298 | + sys.exit(1) | ||
| 299 | + | ||
| 300 | + m = int(sys.argv[1]) | ||
| 301 | + k = int(sys.argv[2]) | ||
| 302 | + n = int(sys.argv[3]) | ||
| 303 | + | ||
| 304 | + if m <= 0 or k <= 0 or n <= 0: | ||
| 305 | + print("Error: m, k and n must be positive integers.") | ||
| 306 | + sys.exit(1) | ||
| 307 | + | ||
| 308 | + # 随机生成矩阵mat1,shape为(m,k ) | ||
| 309 | + mat1 = random.randn(m, k).astype(np.int8) | ||
| 310 | + write2file(mat1, "./data/mat1.bin") | ||
| 311 | + | ||
| 312 | + # 随机生成矩阵mat2,shape为(n, k) | ||
| 313 | + mat2 = random.randint(0, 100, size=(n, k)).astype(np.int8) | ||
| 314 | + np.save("./data/weight.npy", {'weight': mat2}) | ||
| 315 | + os.chmod("./data/weight.npy", 0o0640) | ||
| 316 | + | ||
| 317 | + # 生成output | ||
| 318 | + output = np.random.randn(m, n).astype(np.float16) | ||
| 319 | + write2file(output, "./data/output.bin") | ||
| 320 | + | ||
| 321 | + # 生成bias | ||
| 322 | + bias = random.randn(n).astype(np.float32) | ||
| 323 | + write2file(bias, "./data/bias.bin") | ||
| 324 | + | ||
| 325 | + # 生成deq_scale | ||
| 326 | + deq_scale = random.randn(n).astype(np.float32) | ||
| 327 | + write2file(deq_scale, "./data/deqScale_ori.bin") | ||
| 328 | + deq_scale_int64 = np.fromfile("./data/deqScale_ori.bin", dtype=np.int32).astype(np.int64) | ||
| 329 | + deq_scale_int64.tofile("./data/deqScale.bin") | ||
| 330 | + ``` | ||
| 331 | + | ||
| 332 | + 执行gen_data.py,假设mat1和mat2的shape入参为m=512、k=1024、n=1024。 | ||
| 333 | + | ||
| 334 | + ```shell | ||
| 335 | + python3 gen_data.py 512 1024 1024 | ||
| 336 | + ``` | ||
| 337 | + | ||
| 338 | +- **对数据进行预处理** | ||
| 339 | + | ||
| 340 | + - **原始权重通过msModelSlim压缩工具生成压缩后的x2、compressIndex以及compressInfo** | ||
| 341 | + | ||
| 342 | + 使用以下接口时,需对CANN包中msModelSlim压缩工具进行编译,具体操作参考[Gitee msit仓](https://gitee.com/ascend/msit/tree/master/msmodelslim)中msmodelslim/pytorch/weight_compression目录下的README.md。 | ||
| 343 | + | ||
| 344 | + ```python | ||
| 345 | + from msmodelslim.pytorch.weight_compression import CompressConfig, Compressor | ||
| 346 | + | ||
| 347 | + compress_config = CompressConfig(do_pseudo_sparse=False, sparse_ratio=1) | ||
| 348 | + compressor = Compressor(compress_config, weight_path=weight_path) | ||
| 349 | + | ||
| 350 | + compress_weight, compress_index, compress_info = compressor.run() | ||
| 351 | + # 压缩后的权重,对应aclnnMatmulCompressDequantGetWorkspaceSize接口的x2 | ||
| 352 | + compressor.export(compress_weight, './data/weight') | ||
| 353 | + # 压缩权重的索引,对应aclnnMatmulCompressDequantGetWorkspaceSize接口的compressIndex | ||
| 354 | + compressor.export(compress_index, './data/index') | ||
| 355 | + # 压缩数据的相关信息,对应aclnnMatmulCompressDequantGetWorkspaceSize接口的compressInfo | ||
| 356 | + compressor.export(compress_info, './data/compress_info') | ||
| 357 | + ``` | ||
| 358 | + | ||
| 359 | + - **将原始float类型的反量化参数deqscale进行转换, 得到aclnn接口需要的uint64数据** | ||
| 360 | + | ||
| 361 | + deqScale原始为float类型,以int32读取并转换为int64 | ||
| 362 | + | ||
| 363 | + ```python | ||
| 364 | + import numpy as np | ||
| 365 | + data = np.fromfile('./deqScale_original.bin', dtype=np.int32).astype(np.int64) | ||
| 366 | + data.tofile('./deqScale.bin') | ||
| 367 | + ``` | ||
| 368 | + | ||
| 369 | +- **调用aclnn接口运算** | ||
| 370 | + | ||
| 371 | + 示例代码如下,仅供参考,具体编译和执行过程请参考[编译与运行样例](../../../docs/zh/context/编译与运行样例.md)。 | ||
| 372 | + | ||
| 373 | +```Cpp | ||
| 374 | +#include <iostream> | ||
| 375 | +#include <vector> | ||
| 376 | +#include <acl/acl.h> | ||
| 377 | +#include <aclnnop/aclnn_matmul_compress_dequant.h> | ||
| 378 | +#include <fstream> | ||
| 379 | +#include <unistd.h> | ||
| 380 | +#include <sys/stat.h> | ||
| 381 | +#include <stdio.h> | ||
| 382 | +#include <cstdlib> | ||
| 383 | +#include <string> | ||
| 384 | + | ||
| 385 | +#define CHECK_RET(cond, return_expr) \ | ||
| 386 | + do { \ | ||
| 387 | + if (!(cond)) { \ | ||
| 388 | + return_expr; \ | ||
| 389 | + } \ | ||
| 390 | + } while (0) | ||
| 391 | + | ||
| 392 | +#define LOG_PRINT(message, ...) \ | ||
| 393 | + do { \ | ||
| 394 | + printf(message, ##__VA_ARGS__); \ | ||
| 395 | + } while (0) | ||
| 396 | + | ||
| 397 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 398 | + int64_t shapeSize = 1; | ||
| 399 | + for (auto i : shape) { | ||
| 400 | + shapeSize *= i; | ||
| 401 | + } | ||
| 402 | + return shapeSize; | ||
| 403 | +} | ||
| 404 | + | ||
| 405 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 406 | + // 固定写法,资源初始化 | ||
| 407 | + auto ret = aclInit(nullptr); | ||
| 408 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 409 | + ret = aclrtSetDevice(deviceId); | ||
| 410 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 411 | + ret = aclrtCreateStream(stream); | ||
| 412 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 413 | + return 0; | ||
| 414 | +} | ||
| 415 | + | ||
| 416 | +int ReadBinFileNNop(std::string filePath, void* buffer, size_t bufferSize) | ||
| 417 | +{ | ||
| 418 | + struct stat sBuf; | ||
| 419 | + int fileStatus = stat(filePath.data(), &sBuf); | ||
| 420 | + CHECK_RET(fileStatus == ACL_SUCCESS, LOG_PRINT("Failed to get file %s\n", filePath); return -1); | ||
| 421 | + | ||
| 422 | + std::ifstream file; | ||
| 423 | + file.open(filePath, std::ios::binary); | ||
| 424 | + CHECK_RET(file.is_open(), LOG_PRINT("Open file failed.\n"); return -1); | ||
| 425 | + | ||
| 426 | + file.seekg(0, file.end); | ||
| 427 | + uint64_t binFileBufferLen = file.tellg(); | ||
| 428 | + CHECK_RET(binFileBufferLen > 0, | ||
| 429 | + std::cout<<"File size is 0.\n"; | ||
| 430 | + file.close(); | ||
| 431 | + return -1); | ||
| 432 | + | ||
| 433 | + file.seekg(0, file.beg); | ||
| 434 | + file.read(static_cast<char *>(buffer), binFileBufferLen); | ||
| 435 | + file.close(); | ||
| 436 | + return ACL_SUCCESS; | ||
| 437 | +} | ||
| 438 | + | ||
| 439 | +int CreateAclTensor(std::string filePath, const std::vector<int64_t>& shape, int typeSize, | ||
| 440 | + void** deviceAddr, aclDataType dataType, aclTensor** tensor) { | ||
| 441 | + auto size = GetShapeSize(shape) * typeSize; | ||
| 442 | + // 调用aclrtMalloc申请device侧内存 | ||
| 443 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 444 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 445 | + | ||
| 446 | + // 调用aclrtMallocHost申请host侧内存 | ||
| 447 | + void* binBufferHost = nullptr; | ||
| 448 | + ret = aclrtMallocHost(&binBufferHost, size); | ||
| 449 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMallocHost failed. ERROR: %d\n", ret); return ret); | ||
| 450 | + | ||
| 451 | + // 读取文件 | ||
| 452 | + ret = ReadBinFileNNop(filePath, binBufferHost, size); | ||
| 453 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("ReadBinFileNNop failed. ERROR: %d\n", ret); return ret); | ||
| 454 | + | ||
| 455 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 456 | + ret = aclrtMemcpy(*deviceAddr, size, binBufferHost, size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 457 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 458 | + | ||
| 459 | + // 计算连续tensor的strides | ||
| 460 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 461 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 462 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 463 | + } | ||
| 464 | + | ||
| 465 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 466 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 467 | + shape.data(), shape.size(), *deviceAddr); | ||
| 468 | + return 0; | ||
| 469 | +} | ||
| 470 | + | ||
| 471 | +int main(int argc, char* argv[]) { | ||
| 472 | + // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 473 | + // 根据自己的实际device填写deviceId | ||
| 474 | + int32_t deviceId = 0; | ||
| 475 | + aclrtStream stream; | ||
| 476 | + auto ret = Init(deviceId, &stream); | ||
| 477 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 478 | + | ||
| 479 | + if (argc != 6) { | ||
| 480 | + std::cerr << "Error: Invalid number of arguments. Usage: <program> m k n wCompressedSize indexSize" << std::endl; | ||
| 481 | + return -1; | ||
| 482 | + } | ||
| 483 | + | ||
| 484 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 485 | + int m = atoi(argv[1]); | ||
| 486 | + int k = atoi(argv[2]); | ||
| 487 | + int n = atoi(argv[3]); | ||
| 488 | + // wShape是右矩阵压缩后数据的大小 | ||
| 489 | + int wCompressedSize = atoi(argv[4]); | ||
| 490 | + // indexShape是压缩索引数据的大小 | ||
| 491 | + int indexSize = atoi(argv[5]); | ||
| 492 | + | ||
| 493 | + if (m <= 0 || k <= 0 || n <= 0 || wCompressedSize <= 0 || indexSize <= 0) { | ||
| 494 | + std::cerr << "Error: m, k, n, wCompressedSize and indexSize must be positive integers." << std::endl; | ||
| 495 | + return -1; | ||
| 496 | + } | ||
| 497 | + | ||
| 498 | + std::vector<int64_t> mat1Shape = {m, k}; | ||
| 499 | + std::vector<int64_t> mat2CompressedShape = {wCompressedSize}; | ||
| 500 | + std::vector<int64_t> indexShape = {indexSize}; | ||
| 501 | + std::vector<int64_t> biasShape = {n}; | ||
| 502 | + std::vector<int64_t> deqScaleShape = {n}; | ||
| 503 | + std::vector<int64_t> outputShape = {m, n}; | ||
| 504 | + | ||
| 505 | + std::vector<int64_t> compressInfoHostData = {8, 8, k, n, 1}; | ||
| 506 | + | ||
| 507 | + void* mat1DeviceAddr = nullptr; | ||
| 508 | + void* mat2CompressedDeviceAddr = nullptr; | ||
| 509 | + void* indexDeviceAddr = nullptr; | ||
| 510 | + void* biasDeviceAddr = nullptr; | ||
| 511 | + void* deqScaleDeviceAddr = nullptr; | ||
| 512 | + void* outputDeviceAddr = nullptr; | ||
| 513 | + | ||
| 514 | + aclTensor* mat1 = nullptr; | ||
| 515 | + aclTensor* mat2Compressed = nullptr; | ||
| 516 | + aclTensor* index = nullptr; | ||
| 517 | + aclTensor* bias = nullptr; | ||
| 518 | + aclTensor* deqScale = nullptr; | ||
| 519 | + aclTensor* output = nullptr; | ||
| 520 | + aclIntArray* compressInfo = nullptr; | ||
| 521 | + | ||
| 522 | + std::string rootPath = "./data/"; | ||
| 523 | + | ||
| 524 | + // 创建mat1 aclTensor | ||
| 525 | + std::string mat1FilePath = rootPath + "mat1.bin"; | ||
| 526 | + ret = CreateAclTensor(mat1FilePath, mat1Shape, sizeof(int8_t), &mat1DeviceAddr, aclDataType::ACL_INT8, &mat1); | ||
| 527 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create mat1 tensor failed. ERROR: %d\n", ret); return ret); | ||
| 528 | + // 创建mat2Compressed aclTensor | ||
| 529 | + std::string mat2FilePath = rootPath + "weight/weight.dat"; | ||
| 530 | + ret = CreateAclTensor(mat2FilePath, mat2CompressedShape, sizeof(int8_t), &mat2CompressedDeviceAddr, | ||
| 531 | + aclDataType::ACL_INT8, &mat2Compressed); | ||
| 532 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create mat2 tensor failed. ERROR: %d\n", ret); return ret); | ||
| 533 | + // 创建index aclTensor | ||
| 534 | + std::string indexFilePath = rootPath + "index/weight.dat"; | ||
| 535 | + ret = CreateAclTensor(indexFilePath, indexShape, sizeof(int8_t), &indexDeviceAddr, aclDataType::ACL_INT8, &index); | ||
| 536 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create index tensor failed. ERROR: %d\n", ret); return ret); | ||
| 537 | + // 创建bias aclTensor | ||
| 538 | + std::string biasFilePath = rootPath + "bias.bin"; | ||
| 539 | + ret = CreateAclTensor(biasFilePath, biasShape, sizeof(int32_t), &biasDeviceAddr, aclDataType::ACL_INT32, &bias); | ||
| 540 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create bias tensor failed. ERROR: %d\n", ret); return ret); | ||
| 541 | + // 创建deqScale aclTensor | ||
| 542 | + std::string deqScaleFilePath = rootPath + "deqScale.bin"; | ||
| 543 | + ret = CreateAclTensor(deqScaleFilePath, deqScaleShape, sizeof(int32_t), &deqScaleDeviceAddr, aclDataType::ACL_UINT64, | ||
| 544 | + &deqScale); | ||
| 545 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create deqScale tensor failed. ERROR: %d\n", ret); return ret); | ||
| 546 | + // 创建compressInfo | ||
| 547 | + compressInfo = aclCreateIntArray(compressInfoHostData.data(), aclDataType::ACL_INT64); | ||
| 548 | + // 创建out aclTensor | ||
| 549 | + std::string outputFilePath = rootPath + "output.bin"; | ||
| 550 | + ret = CreateAclTensor(outputFilePath, outputShape, 2, &outputDeviceAddr, aclDataType::ACL_FLOAT16, &output); | ||
| 551 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Create output tensor failed. ERROR: %d\n", ret); return ret); | ||
| 552 | + | ||
| 553 | + int32_t offsetX = 0; | ||
| 554 | + | ||
| 555 | + // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 556 | + uint64_t workspaceSize = 0; | ||
| 557 | + aclOpExecutor* executor; | ||
| 558 | + // 调用aclnnMm第一段接口 | ||
| 559 | + ret = aclnnMatmulCompressDequantGetWorkspaceSize(mat1, mat2Compressed, index, bias, deqScale, nullptr, offsetX, compressInfo, output, &workspaceSize, &executor); | ||
| 560 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMatmulCompressDequantGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 561 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 562 | + void* workspaceAddr = nullptr; | ||
| 563 | + if (workspaceSize > 0) { | ||
| 564 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 565 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 566 | + } | ||
| 567 | + // 调用aclnnMm第二段接口 | ||
| 568 | + ret = aclnnMatmulCompressDequant(workspaceAddr, workspaceSize, executor, stream); | ||
| 569 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMatmulCompressDequant failed. ERROR: %d\n", ret); return ret); | ||
| 570 | + | ||
| 571 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 572 | + ret = aclrtSynchronizeStream(stream); | ||
| 573 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 574 | + | ||
| 575 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 576 | + auto size = GetShapeSize(outputShape); | ||
| 577 | + std::vector<float> resultData(size, 0); | ||
| 578 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outputDeviceAddr, | ||
| 579 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 580 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 581 | + for (int64_t i = 0; i < size; i++) { | ||
| 582 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 583 | + } | ||
| 584 | + | ||
| 585 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 586 | + aclDestroyTensor(mat1); | ||
| 587 | + aclDestroyTensor(mat2Compressed); | ||
| 588 | + aclDestroyTensor(index); | ||
| 589 | + aclDestroyTensor(bias); | ||
| 590 | + aclDestroyTensor(deqScale); | ||
| 591 | + aclDestroyTensor(output); | ||
| 592 | + aclDestroyIntArray(compressInfo); | ||
| 593 | + | ||
| 594 | + // 7.释放硬件资源,需要根据具体API的接口定义修改 | ||
| 595 | + aclrtFree(mat1DeviceAddr); | ||
| 596 | + aclrtFree(mat2CompressedDeviceAddr); | ||
| 597 | + aclrtFree(indexDeviceAddr); | ||
| 598 | + aclrtFree(biasDeviceAddr); | ||
| 599 | + aclrtFree(deqScaleDeviceAddr); | ||
| 600 | + aclrtFree(outputDeviceAddr); | ||
| 601 | + if (workspaceSize > 0) { | ||
| 602 | + aclrtFree(workspaceAddr); | ||
| 603 | + } | ||
| 604 | + aclrtDestroyStream(stream); | ||
| 605 | + aclrtResetDevice(deviceId); | ||
| 606 | + aclFinalize(); | ||
| 607 | + return 0; | ||
| 608 | +} | ||
| 609 | +``` | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This file is a part of the CANN Open Software. | ||
| 5 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 8 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +# add_modules_sources(OPTYPE matmul_v2_compress_dequant ACLNNTYPE aclnn_exclude) | ||
| 13 | +# add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE matmul_v2_compress_dequant) | ||
| 14 | +add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE matmul_v2_compress_dequant ACLNNTYPE aclnn_exclude DEPENDENCIES transpose_batch_mat_mul) | ||
Amatmul/matmul_v2_compress_dequant/op_host/config/ascend310p/matmul_v2_compress_dequant_binary.json+95-0
| @@ -0,0 +1,95 @@ | |||
| 1 | +{ | ||
| 2 | + "op_type": "MatMulV2CompressDequant", | ||
| 3 | + "op_list": [ | ||
| 4 | + { | ||
| 5 | + "bin_filename": "MatmulV2CompressDequant_Int8", | ||
| 6 | + "inputs": [ | ||
| 7 | + { | ||
| 8 | + "name": "x1", | ||
| 9 | + "index": 0, | ||
| 10 | + "dtype": "int8", | ||
| 11 | + "format": "ND", | ||
| 12 | + "paramType": "required", | ||
| 13 | + "shape": [-2] | ||
| 14 | + }, | ||
| 15 | + { | ||
| 16 | + "name": "x2", | ||
| 17 | + "index": 1, | ||
| 18 | + "dtype": "int8", | ||
| 19 | + "format": "ND", | ||
| 20 | + "paramType": "required", | ||
| 21 | + "shape": [-2] | ||
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + "name": "compress_index", | ||
| 25 | + "index": 2, | ||
| 26 | + "dtype": "int8", | ||
| 27 | + "format": "ND", | ||
| 28 | + "paramType": "required", | ||
| 29 | + "shape": [-2] | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + "name": "deq_scale", | ||
| 33 | + "index": 3, | ||
| 34 | + "dtype": "uint64", | ||
| 35 | + "format": "ND", | ||
| 36 | + "paramType": "required", | ||
| 37 | + "shape": [-2] | ||
| 38 | + }, | ||
| 39 | + { | ||
| 40 | + "name": "bias", | ||
| 41 | + "index": 4, | ||
| 42 | + "dtype": "int32", | ||
| 43 | + "format": "ND", | ||
| 44 | + "paramType": "required", | ||
| 45 | + "shape": [-2] | ||
| 46 | + }, | ||
| 47 | + { | ||
| 48 | + "name": "offset_w", | ||
| 49 | + "index": 5, | ||
| 50 | + "dtype": "int8", | ||
| 51 | + "format": "ND", | ||
| 52 | + "paramType": "optional", | ||
| 53 | + "shape": [-2] | ||
| 54 | + } | ||
| 55 | + ], | ||
| 56 | + "outputs": [ | ||
| 57 | + { | ||
| 58 | + "name": "out", | ||
| 59 | + "index": 0, | ||
| 60 | + "dtype": "float16", | ||
| 61 | + "format": "ND", | ||
| 62 | + "paramType": "required", | ||
| 63 | + "shape": [-2] | ||
| 64 | + } | ||
| 65 | + ], | ||
| 66 | + "attrs": [ | ||
| 67 | + { | ||
| 68 | + "name": "transpose_x1", | ||
| 69 | + "dtype": "bool", | ||
| 70 | + "value": null | ||
| 71 | + }, | ||
| 72 | + { | ||
| 73 | + "name": "transpose_x2", | ||
| 74 | + "dtype": "bool", | ||
| 75 | + "value": null | ||
| 76 | + }, | ||
| 77 | + { | ||
| 78 | + "name": "compress_info", | ||
| 79 | + "dtype": "list_int", | ||
| 80 | + "value": null | ||
| 81 | + }, | ||
| 82 | + { | ||
| 83 | + "name": "offset_x", | ||
| 84 | + "dtype": "int", | ||
| 85 | + "value": null | ||
| 86 | + }, | ||
| 87 | + { | ||
| 88 | + "name": "alg", | ||
| 89 | + "dtype": "string", | ||
| 90 | + "value": null | ||
| 91 | + } | ||
| 92 | + ] | ||
| 93 | + } | ||
| 94 | + ] | ||
| 95 | +} | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file matmul_v2_compress_dequant_def.cpp | ||
| 13 | + * \brief MatMulV2CompressDequant op definition for ascend310p | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +namespace ops { | ||
| 18 | +class MatMulV2CompressDequant : public OpDef { | ||
| 19 | +public: | ||
| 20 | + explicit MatMulV2CompressDequant(const char* name) : OpDef(name) | ||
| 21 | + { | ||
| 22 | + this->Input("x1") | ||
| 23 | + .ParamType(REQUIRED) | ||
| 24 | + .DataType({ge::DT_INT8}) | ||
| 25 | + .Format({ge::FORMAT_ND}) | ||
| 26 | + .UnknownShapeFormat({ge::FORMAT_ND}); | ||
| 27 | + this->Input("x2") | ||
| 28 | + .ParamType(REQUIRED) | ||
| 29 | + .DataType({ge::DT_INT8}) | ||
| 30 | + .Format({ge::FORMAT_ND}) | ||
| 31 | + .UnknownShapeFormat({ge::FORMAT_ND}); | ||
| 32 | + this->Input("compress_index") | ||
| 33 | + .ParamType(REQUIRED) | ||
| 34 | + .DataType({ge::DT_INT8}) | ||
| 35 | + .Format({ge::FORMAT_ND}) | ||
| 36 | + .UnknownShapeFormat({ge::FORMAT_ND}); | ||
| 37 | + this->Input("deq_scale") | ||
| 38 | + .ParamType(REQUIRED) | ||
| 39 | + .DataType({ge::DT_UINT64}) | ||
| 40 | + .Format({ge::FORMAT_ND}) | ||
| 41 | + .UnknownShapeFormat({ge::FORMAT_ND}); | ||
| 42 | + this->Input("bias") | ||
| 43 | + .ParamType(REQUIRED) | ||
| 44 | + .DataType({ge::DT_INT32}) | ||
| 45 | + .Format({ge::FORMAT_ND}) | ||
| 46 | + .UnknownShapeFormat({ge::FORMAT_ND}); | ||
| 47 | + this->Input("offset_w") | ||
| 48 | + .ParamType(OPTIONAL) | ||
| 49 | + .DataType({ge::DT_INT8}) | ||
| 50 | + .Format({ge::FORMAT_ND}) | ||
| 51 | + .UnknownShapeFormat({ge::FORMAT_ND}); | ||
| 52 | + this->Attr("transpose_x1").AttrType(OPTIONAL).Bool(false); | ||
| 53 | + this->Attr("transpose_x2").AttrType(OPTIONAL).Bool(false); | ||
| 54 | + this->Attr("compress_info").AttrType(OPTIONAL).ListInt({1, 1, 1, 1, 1}); | ||
| 55 | + this->Attr("offset_x").AttrType(OPTIONAL).Int(0); | ||
| 56 | + this->Attr("alg").AttrType(OPTIONAL).String("weight_unzip"); | ||
| 57 | + this->Output("out") | ||
| 58 | + .ParamType(REQUIRED) | ||
| 59 | + .DataType({ge::DT_FLOAT16}) | ||
| 60 | + .Format({ge::FORMAT_ND}) | ||
| 61 | + .UnknownShapeFormat({ge::FORMAT_ND}); | ||
| 62 | + | ||
| 63 | + OpAICoreConfig config_310p; | ||
| 64 | + config_310p.DynamicCompileStaticFlag(true) | ||
| 65 | + .DynamicRankSupportFlag(true) | ||
| 66 | + .DynamicShapeSupportFlag(true) | ||
| 67 | + .NeedCheckSupportFlag(false) | ||
| 68 | + .ExtendCfgInfo("opFile.value", "matmul_v2_compress_dequant"); | ||
| 69 | + this->AICore().AddConfig("ascend310p", config_310p); | ||
| 70 | + } | ||
| 71 | +}; | ||
| 72 | + | ||
| 73 | +OP_ADD(MatMulV2CompressDequant); | ||
| 74 | +} // namespace ops | ||
| @@ -0,0 +1,301 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file matmul_v2_compress_dequant_tiling.cpp | ||
| 13 | + * \brief Tiling implementation for matmul_v2_compress_dequant | ||
| 14 | + * Core algorithm ported from pp_matmul_i8_nz_tiling.cpp | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace optiling { | ||
| 25 | +namespace { | ||
| 26 | + | ||
| 27 | +// ============================================================ | ||
| 28 | +// Constants (aligned with pp_matmul common_tiling.h) | ||
| 29 | +// ============================================================ | ||
| 30 | +constexpr uint32_t BLOCK_SIZE_16 = 16; | ||
| 31 | +constexpr uint32_t BLOCK_SIZE_INT8_K = 32; | ||
| 32 | +constexpr uint32_t BASE_BLOCK_STEP = 2; | ||
| 33 | +constexpr uint32_t FP16_BYTE_SIZE = 2; | ||
| 34 | +constexpr uint32_t FP32_BYTE_SIZE = 4; | ||
| 35 | +constexpr float INT8_DTYPE_SIZE = 1.0f; | ||
| 36 | +constexpr uint32_t AXES_ALIGN_SIZE = 512; | ||
| 37 | +constexpr uint32_t AXES_ALIGN_SIZE_INT8 = 256; | ||
| 38 | +constexpr uint32_t L0AB_PP_BUF_LEN_FP16 = 131072; // 128 KB | ||
| 39 | +constexpr uint32_t L1AB_PP_BUF_LEN_INT8_SPARSE = 163840; // 160 KB | ||
| 40 | +constexpr uint32_t ALIGNMENT_16 = 16; | ||
| 41 | +constexpr uint32_t CONST_3 = 3; | ||
| 42 | +constexpr uint32_t CONST_4 = 4; | ||
| 43 | +constexpr uint32_t CONST_256 = 256; | ||
| 44 | +constexpr uint32_t TRANS_B_MASK = 0b001000; | ||
| 45 | +constexpr float L2_BW_RATIO = 5.0f; | ||
| 46 | +constexpr uint64_t DEFAULT_L2_SIZE = 48UL * 1024 * 1024; // 48 MB | ||
| 47 | +constexpr uint64_t DEFAULT_L0C_SIZE = 256UL * 1024; // 256 KB | ||
| 48 | + | ||
| 49 | +constexpr size_t TRANSPOSE_X1_ATTR_IDX = 0; | ||
| 50 | +constexpr size_t TRANSPOSE_X2_ATTR_IDX = 1; | ||
| 51 | +constexpr size_t COMPRESS_INFO_ATTR_IDX = 2; | ||
| 52 | + | ||
| 53 | +constexpr size_t CI_IDX_TILING_K = 0; | ||
| 54 | +constexpr size_t CI_IDX_TILING_N = 1; | ||
| 55 | +constexpr size_t CI_IDX_K = 2; | ||
| 56 | +constexpr size_t CI_IDX_N = 3; | ||
| 57 | +constexpr size_t COMPRESS_INFO_MIN_ELEMS = 4; | ||
| 58 | + | ||
| 59 | +constexpr size_t INPUT_IDX_X1 = 0; | ||
| 60 | +constexpr size_t INPUT_IDX_BIAS = 4; | ||
| 61 | + | ||
| 62 | +// ============================================================ | ||
| 63 | +// Utility functions | ||
| 64 | +// ============================================================ | ||
| 65 | + | ||
| 66 | + | ||
| 67 | +inline uint32_t CeilDivU32(uint32_t dividend, uint32_t divisor) | ||
| 68 | +{ | ||
| 69 | + if (divisor == 0 || dividend + divisor - 1 < dividend) { | ||
| 70 | + return dividend; | ||
| 71 | + } | ||
| 72 | + return (dividend + divisor - 1) / divisor; | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | + | ||
| 76 | +// // ============================================================ | ||
| 77 | +// // Compute k0 and compressOverlapN | ||
| 78 | +// // Ported from PpTilingData310P::End | ||
| 79 | +// // ============================================================ | ||
| 80 | +uint32_t ComputeK0(uint32_t n0, uint32_t n, | ||
| 81 | + bool isCompress, uint32_t tilingNVal, | ||
| 82 | + uint32_t &compressOverlapN) | ||
| 83 | +{ | ||
| 84 | + compressOverlapN = 0; | ||
| 85 | + | ||
| 86 | + if (isCompress) { | ||
| 87 | + if (n0 == 0) { | ||
| 88 | + return 1; | ||
| 89 | + } | ||
| 90 | + uint32_t nTail = n % n0; | ||
| 91 | + uint32_t compressNTile = (tilingNVal > 0) ? (CeilDivU32(nTail, ALIGNMENT_16) % tilingNVal) : 0; | ||
| 92 | + compressOverlapN = (compressNTile == 0) ? 0 : tilingNVal - compressNTile; | ||
| 93 | + } | ||
| 94 | + return 0; | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +// ============================================================ | ||
| 98 | +// Extract M, K, N, batchSize from TilingContext | ||
| 99 | +// Handles both ND shapes (2D: [M, K]) and NZ shapes (4D) | ||
| 100 | +// ============================================================ | ||
| 101 | +ge::graphStatus ExtractMatmulDims(const gert::TilingContext *context, uint32_t &batchSize, uint32_t &m, uint32_t &k, | ||
| 102 | + uint32_t &n, const int64_t *compressInfoData, size_t compressInfoCount) | ||
| 103 | +{ | ||
| 104 | + const auto *x1ShapePtr = context->GetInputShape(INPUT_IDX_X1); | ||
| 105 | + if (x1ShapePtr == nullptr) { | ||
| 106 | + OP_LOGE("MatMulV2CompressDequant", "x1 shape is nullptr."); | ||
| 107 | + return ge::GRAPH_FAILED; | ||
| 108 | + } | ||
| 109 | + const auto &x1Shape = x1ShapePtr->GetOriginShape(); | ||
| 110 | + | ||
| 111 | + m = static_cast<uint32_t>(x1Shape.GetDim(0)); | ||
| 112 | + k = static_cast<uint32_t>(x1Shape.GetDim(1)); | ||
| 113 | + // 输入是个2维 | ||
| 114 | + batchSize = 1; | ||
| 115 | + | ||
| 116 | + n = 0; | ||
| 117 | + if (compressInfoCount > CI_IDX_N && compressInfoData != nullptr) { | ||
| 118 | + n = static_cast<uint32_t>(compressInfoData[CI_IDX_N]); | ||
| 119 | + } | ||
| 120 | + if (n == 0) { | ||
| 121 | + const auto *outShapePtr = context->GetOutputShape(0); | ||
| 122 | + if (outShapePtr != nullptr) { | ||
| 123 | + const auto &outShape = outShapePtr->GetStorageShape(); | ||
| 124 | + size_t outNdim = outShape.GetDimNum(); | ||
| 125 | + if (outNdim >= 4) { | ||
| 126 | + n = static_cast<uint32_t>(outShape.GetDim(outNdim - 4) * | ||
| 127 | + outShape.GetDim(outNdim - 1)); | ||
| 128 | + } else if (outNdim >= 2) { | ||
| 129 | + n = static_cast<uint32_t>(outShape.GetDim(outNdim - 1)); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + if (m == 0 || k == 0 || n == 0) { | ||
| 135 | + OP_LOGE("MatMulV2CompressDequant", "Invalid dims: m=%u, k=%u, n=%u.", m, k, n); | ||
| 136 | + return ge::GRAPH_FAILED; | ||
| 137 | + } | ||
| 138 | + return ge::GRAPH_SUCCESS; | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +} // namespace | ||
| 142 | + | ||
| 143 | + | ||
| 144 | +static ge::graphStatus TbmmEinsumTilingFunc (gert::TilingContext* context, | ||
| 145 | + uint32_t &batchSize, uint32_t &m, uint32_t &k, uint32_t &n, | ||
| 146 | + uint32_t& tilingK, uint32_t& tilingN) | ||
| 147 | +{ | ||
| 148 | + if (context == nullptr) { | ||
| 149 | + OP_LOGE("MatMulV2CompressDequant", "context is null."); | ||
| 150 | + return ge::GRAPH_FAILED; | ||
| 151 | + } | ||
| 152 | + auto compileInfo = reinterpret_cast<const MatmulV2CompressDequantCompileInfo *>(context->GetCompileInfo()); | ||
| 153 | + uint32_t coreNum = static_cast<uint32_t>(compileInfo->aivNum); | ||
| 154 | + | ||
| 155 | + size_t sysWorkspaceSize = static_cast<size_t>(24 * 1024 * 1024); // 24M same as ppmatmul tiling | ||
| 156 | + size_t* currentWorkSpace = context->GetWorkspaceSizes(1); | ||
| 157 | + currentWorkSpace[0] = sysWorkspaceSize; | ||
| 158 | + | ||
| 159 | + optiling::pp_matmul::matmulCompressDequant::PpMatMulDefault tbmmEinsumTiling(context); | ||
| 160 | + auto inputDType = context->GetInputDesc(0)->GetDataType(); | ||
| 161 | + | ||
| 162 | + tbmmEinsumTiling.matMulInfo_.isInt8 = (inputDType == ge::DT_INT8); | ||
| 163 | + tbmmEinsumTiling.matMulInfo_.inDtype = ge::GetSizeByDataType(inputDType); | ||
| 164 | + (void)tbmmEinsumTiling.GetHardwareInfo(); | ||
| 165 | + | ||
| 166 | + // 设置一个m, k, n | ||
| 167 | + tbmmEinsumTiling.matMulInfo_.m = m; | ||
| 168 | + tbmmEinsumTiling.matMulInfo_.k = k; | ||
| 169 | + tbmmEinsumTiling.matMulInfo_.n = n; | ||
| 170 | + tbmmEinsumTiling.matMulInfo_.batchSize = batchSize; | ||
| 171 | + (void)tbmmEinsumTiling.GetMatMulTilingData(); | ||
| 172 | + (void)tbmmEinsumTiling.PrintTiling(); | ||
| 173 | + | ||
| 174 | + uint32_t compressOverlapN = 0; | ||
| 175 | + (void)ComputeK0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n0, | ||
| 176 | + tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n, true, tilingN, compressOverlapN); | ||
| 177 | + // PostTiling | ||
| 178 | + uint32_t blockDim = std::min(tbmmEinsumTiling.ppMatmulDefaultTilingData_.coreLoop, (uint64_t)coreNum); | ||
| 179 | + context->SetBlockDim(blockDim); | ||
| 180 | + MatmulV2CompressDequantTilingData tiling; | ||
| 181 | + tiling.set_batchSize(batchSize); | ||
| 182 | + tiling.set_m(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.m); | ||
| 183 | + tiling.set_k(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.k); | ||
| 184 | + tiling.set_n(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n); | ||
| 185 | + tiling.set_m0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.m0); | ||
| 186 | + tiling.set_k0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.k0); | ||
| 187 | + tiling.set_n0(tbmmEinsumTiling.ppMatmulDefaultTilingData_.opShape.n0); | ||
| 188 | + tiling.set_mLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.mLoop); | ||
| 189 | + tiling.set_kLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.kLoop); | ||
| 190 | + tiling.set_nLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.nLoop); | ||
| 191 | + tiling.set_coreLoop(tbmmEinsumTiling.ppMatmulDefaultTilingData_.coreLoop); | ||
| 192 | + tiling.set_swizzlCount(tbmmEinsumTiling.ppMatmulDefaultTilingData_.swizzlCount); | ||
| 193 | + tiling.set_tilingK(tilingK); | ||
| 194 | + tiling.set_tilingN(tilingN); | ||
| 195 | + tiling.set_compressOverlapN(compressOverlapN); | ||
| 196 | + tiling.set_tilingKey(0); | ||
| 197 | + tiling.set_blockDimVal(blockDim); | ||
| 198 | + tiling.set_splitK(0); | ||
| 199 | + tiling.SaveToBuffer(context->GetRawTilingData()->GetData(), context->GetRawTilingData()->GetCapacity()); | ||
| 200 | + context->GetRawTilingData()->SetDataSize(tiling.GetDataSize()); | ||
| 201 | + | ||
| 202 | + return ge::GRAPH_SUCCESS; | ||
| 203 | +} | ||
| 204 | + | ||
| 205 | + | ||
| 206 | +// ============================================================ | ||
| 207 | +// Main tiling function | ||
| 208 | +// ============================================================ | ||
| 209 | +ge::graphStatus TilingForMatmulV2CompressDequant(gert::TilingContext *context) | ||
| 210 | +{ | ||
| 211 | + OP_LOGI(context->GetNodeName(), "TbmmEinsum Tiling start."); | ||
| 212 | + | ||
| 213 | + uint32_t batchSize = 1; | ||
| 214 | + uint32_t m = 0; | ||
| 215 | + uint32_t k = 0; | ||
| 216 | + uint32_t n = 0; | ||
| 217 | + const int64_t *compressInfoData = nullptr; | ||
| 218 | + size_t compressInfoCount = 0; | ||
| 219 | + auto *attrs = context->GetAttrs(); | ||
| 220 | + const auto *compressInfoVec = attrs->GetAttrPointer<gert::ContinuousVector>(COMPRESS_INFO_ATTR_IDX); | ||
| 221 | + compressInfoCount = compressInfoVec->GetSize(); | ||
| 222 | + compressInfoData = reinterpret_cast<const int64_t *>(compressInfoVec->GetData()); | ||
| 223 | + | ||
| 224 | + (void)ExtractMatmulDims(context, batchSize, m, k, n, | ||
| 225 | + compressInfoData, compressInfoCount); | ||
| 226 | + | ||
| 227 | + uint32_t tilingKVal = 0; | ||
| 228 | + uint32_t tilingNVal = 0; | ||
| 229 | + if (compressInfoData != nullptr && compressInfoCount >= 2) { | ||
| 230 | + tilingKVal = static_cast<uint32_t>(compressInfoData[CI_IDX_TILING_K]); | ||
| 231 | + tilingNVal = static_cast<uint32_t>(compressInfoData[CI_IDX_TILING_N]); | ||
| 232 | + } | ||
| 233 | + TbmmEinsumTilingFunc(context, batchSize, m, k, n, tilingKVal, tilingNVal); | ||
| 234 | + | ||
| 235 | + auto compileInfo = reinterpret_cast<const MatmulV2CompressDequantCompileInfo *>(context->GetCompileInfo()); | ||
| 236 | + | ||
| 237 | + // ---- Workspace ---- | ||
| 238 | + size_t *currentWorkspace = context->GetWorkspaceSizes(1); | ||
| 239 | + currentWorkspace[0] = compileInfo->workSpaceSize; | ||
| 240 | + return ge::GRAPH_SUCCESS; | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +// ============================================================ | ||
| 244 | +// TilingPrepare – collect compile-time hardware info | ||
| 245 | +// ============================================================ | ||
| 246 | +ge::graphStatus TilingPrepareForMatmulV2CompressDequant(gert::TilingParseContext *context) | ||
| 247 | +{ | ||
| 248 | + if (context == nullptr) { | ||
| 249 | + OP_LOGE("MatMulV2CompressDequant", "TilingParse context is nullptr."); | ||
| 250 | + return ge::GRAPH_FAILED; | ||
| 251 | + } | ||
| 252 | + OP_LOGD(context, "TilingPrepareForMatmulV2CompressDequant start."); | ||
| 253 | + | ||
| 254 | + fe::PlatFormInfos* platformInfo = context->GetPlatformInfo(); | ||
| 255 | + if (platformInfo == nullptr) { | ||
| 256 | + OP_LOGE("MatMulV2CompressDequant", "platformInfoPtr is null"); | ||
| 257 | + return ge::GRAPH_FAILED; | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + auto compileInfoPtr = context->GetCompiledInfo<MatmulV2CompressDequantCompileInfo>(); | ||
| 261 | + if (compileInfoPtr == nullptr) { | ||
| 262 | + OP_LOGE("MatMulV2CompressDequant", "compileInfoPtr is null"); | ||
| 263 | + return ge::GRAPH_FAILED; | ||
| 264 | + } | ||
| 265 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo); | ||
| 266 | + platformInfo->GetPlatformRes("version", "SoC_version", compileInfoPtr->socVersionStr); | ||
| 267 | + std::string val; | ||
| 268 | + std::string dataMoveL12Bt; | ||
| 269 | + platformInfo->GetPlatformRes("AICoreintrinsicDtypeMap", "Intrinsic_fix_pipe_l0c2out", val); | ||
| 270 | + platformInfo->GetPlatformRes("AICoreintrinsicDtypeMap", "Intrinsic_data_move_l12bt", dataMoveL12Bt); | ||
| 271 | + compileInfoPtr->supportL0c2out = !val.empty(); | ||
| 272 | + compileInfoPtr->supportL12BtBf16 = (dataMoveL12Bt.find("bf16") != std::string::npos); | ||
| 273 | + compileInfoPtr->workSpaceSize = ascendcPlatform.GetLibApiWorkSpaceSize(); | ||
| 274 | + compileInfoPtr->aivNum = ascendcPlatform.GetCoreNumAiv(); | ||
| 275 | + compileInfoPtr->aicNum = ascendcPlatform.GetCoreNumAic(); | ||
| 276 | + compileInfoPtr->socVersion = ascendcPlatform.GetSocVersion(); | ||
| 277 | + compileInfoPtr->npuArch = ascendcPlatform.GetCurNpuArch(); | ||
| 278 | + compileInfoPtr->btSize = compileInfoPtr->supportL0c2out ? 1024UL : 0UL; // 1024 is btSize | ||
| 279 | + compileInfoPtr->btSize = compileInfoPtr->supportL12BtBf16 ? 4096UL : compileInfoPtr->btSize; // 4096 is btSize | ||
| 280 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, compileInfoPtr->ubSize); | ||
| 281 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L1, compileInfoPtr->l1Size); | ||
| 282 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_A, compileInfoPtr->l0ASize); | ||
| 283 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_B, compileInfoPtr->l0BSize); | ||
| 284 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_C, compileInfoPtr->l0CSize); | ||
| 285 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L2, compileInfoPtr->l2Size); | ||
| 286 | + | ||
| 287 | + compileInfoPtr->isRegbase = Ops::NN::OpTiling::IsRegbaseSocVersion(context); | ||
| 288 | + | ||
| 289 | + OP_LOGD(context, "TilingPrepare end: aivNum=%lu ubSize=%lu l0CSize=%lu l2Size=%lu", | ||
| 290 | + compileInfoPtr->aivNum, compileInfoPtr->ubSize, compileInfoPtr->l0CSize, compileInfoPtr->l2Size); | ||
| 291 | + return ge::GRAPH_SUCCESS; | ||
| 292 | +} | ||
| 293 | + | ||
| 294 | +// ============================================================ | ||
| 295 | +// Registration | ||
| 296 | +// ============================================================ | ||
| 297 | +IMPL_OP_OPTILING(MatMulV2CompressDequant) | ||
| 298 | + .Tiling(TilingForMatmulV2CompressDequant) | ||
| 299 | + .TilingParse<MatmulV2CompressDequantCompileInfo>(TilingPrepareForMatmulV2CompressDequant); | ||
| 300 | + | ||
| 301 | +} // namespace optiling | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file matmul_v2_compress_dequant_tiling.h | ||
| 13 | + * \brief Tiling data and registration for matmul_v2_compress_dequant | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +namespace optiling { | ||
| 26 | + | ||
| 27 | +BEGIN_TILING_DATA_DEF(MatmulV2CompressDequantTilingData) | ||
| 28 | + TILING_DATA_FIELD_DEF(uint32_t, batchSize); | ||
| 29 | + TILING_DATA_FIELD_DEF(uint32_t, m); | ||
| 30 | + TILING_DATA_FIELD_DEF(uint32_t, k); | ||
| 31 | + TILING_DATA_FIELD_DEF(uint32_t, n); | ||
| 32 | + TILING_DATA_FIELD_DEF(uint32_t, m0); | ||
| 33 | + TILING_DATA_FIELD_DEF(uint32_t, k0); | ||
| 34 | + TILING_DATA_FIELD_DEF(uint32_t, n0); | ||
| 35 | + TILING_DATA_FIELD_DEF(uint32_t, mLoop); | ||
| 36 | + TILING_DATA_FIELD_DEF(uint32_t, kLoop); | ||
| 37 | + TILING_DATA_FIELD_DEF(uint32_t, nLoop); | ||
| 38 | + TILING_DATA_FIELD_DEF(uint32_t, coreLoop); | ||
| 39 | + TILING_DATA_FIELD_DEF(uint32_t, swizzlCount); | ||
| 40 | + TILING_DATA_FIELD_DEF(uint32_t, tilingK); | ||
| 41 | + TILING_DATA_FIELD_DEF(uint32_t, tilingN); | ||
| 42 | + TILING_DATA_FIELD_DEF(uint32_t, compressOverlapN); | ||
| 43 | + TILING_DATA_FIELD_DEF(uint32_t, tilingKey); | ||
| 44 | + TILING_DATA_FIELD_DEF(uint32_t, blockDimVal); | ||
| 45 | + TILING_DATA_FIELD_DEF(uint32_t, splitK); | ||
| 46 | +END_TILING_DATA_DEF; | ||
| 47 | + | ||
| 48 | +REGISTER_TILING_DATA_CLASS(MatMulV2CompressDequant, MatmulV2CompressDequantTilingData) | ||
| 49 | + | ||
| 50 | +struct MatmulV2CompressDequantCompileInfo { | ||
| 51 | + uint64_t aicNum{0UL}; | ||
| 52 | + uint64_t aivNum{0UL}; | ||
| 53 | + uint64_t ubSize = 0; | ||
| 54 | + uint64_t l1Size = 0; | ||
| 55 | + uint64_t l2Size = 0; | ||
| 56 | + uint64_t l0CSize = 0; | ||
| 57 | + uint64_t l0ASize{0UL}; | ||
| 58 | + uint64_t l0BSize{0UL}; | ||
| 59 | + uint64_t btSize{0UL}; | ||
| 60 | + float cubeFreq{0}; | ||
| 61 | + NpuArch npuArch; | ||
| 62 | + platform_ascendc::SocVersion socVersion; | ||
| 63 | + std::string socVersionStr = ""; | ||
| 64 | + bool supportL0c2out = false; | ||
| 65 | + bool supportL12BtBf16 = false; | ||
| 66 | + uint64_t workSpaceSize = 0; | ||
| 67 | + bool isRegbase = false; | ||
| 68 | +}; | ||
| 69 | + | ||
| 70 | +ge::graphStatus TilingForMatmulV2CompressDequant(gert::TilingContext *context); | ||
| 71 | + | ||
| 72 | +} // namespace optiling | ||
| 73 | + | ||
| 74 | + | ||
| @@ -0,0 +1,305 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file aclnn_matmul_compress_dequant.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +using namespace op; | ||
| 34 | + | ||
| 35 | +extern "C" { | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | +static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LIST = {DataType::DT_INT8}; | ||
| 42 | +static const std::initializer_list<op::DataType> BIAS_DTYPE_SUPPORT_LIST = {DataType::DT_INT32}; | ||
| 43 | +static const std::initializer_list<op::DataType> DEQ_SCALE_DTYPE_SUPPORT_LIST = {DataType::DT_UINT64}; | ||
| 44 | +static const std::initializer_list<op::DataType> OUT_DTYPE_SUPPORT_LIST = {DataType::DT_FLOAT16}; | ||
| 45 | + | ||
| 46 | +static const std::string ALG_WEIGHT_UNZIP = "weight_unzip"; | ||
| 47 | +static const std::string ALG_UNKNOWN = "unknown"; | ||
| 48 | + | ||
| 49 | +static op::FVector<int64_t> GetShape(const aclTensor* tensor) | ||
| 50 | +{ | ||
| 51 | + op::FVector<int64_t> shape; | ||
| 52 | + if (tensor == nullptr) { | ||
| 53 | + shape.push_back(1); | ||
| 54 | + OP_LOGW("The input tensor of Func GetShape is nullptr"); | ||
| 55 | + return shape; | ||
| 56 | + } | ||
| 57 | + if (tensor->GetViewShape().GetDimNum() == 0U) { | ||
| 58 | + shape.push_back(1); | ||
| 59 | + } else { | ||
| 60 | + size_t dimNum = tensor->GetViewShape().GetDimNum(); | ||
| 61 | + for (size_t idx = 0U; idx < dimNum; idx++) { | ||
| 62 | + int64_t tmpVal = tensor->GetViewShape().GetDim(idx); | ||
| 63 | + shape.push_back(tmpVal); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + return shape; | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | +enum UnzipMode { UNKNOWN = 0, WEIGHT_UNZIP = 1 }; | ||
| 70 | + | ||
| 71 | +inline static const std::string& GetAlgStr(int algMode) | ||
| 72 | +{ | ||
| 73 | + if (algMode == UnzipMode::WEIGHT_UNZIP) { | ||
| 74 | + return ALG_WEIGHT_UNZIP; | ||
| 75 | + } | ||
| 76 | + return ALG_UNKNOWN; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +struct MatmulUnzipInput { | ||
| 80 | + const aclTensor* x1; | ||
| 81 | + const aclTensor* x2; | ||
| 82 | + const aclTensor* compressIndex; | ||
| 83 | + const aclTensor* bias; | ||
| 84 | + const aclTensor* deqScale; | ||
| 85 | + const aclTensor* offsetW; | ||
| 86 | +}; | ||
| 87 | + | ||
| 88 | +inline static bool CheckNotNull(MatmulUnzipInput matmulUnzipInput, const aclIntArray* compressInfo, | ||
| 89 | + const aclTensor* out) | ||
| 90 | +{ | ||
| 91 | + OP_CHECK_NULL(matmulUnzipInput.x1, return false); | ||
| 92 | + OP_CHECK_NULL(matmulUnzipInput.x2, return false); | ||
| 93 | + OP_CHECK_NULL(matmulUnzipInput.compressIndex, return false); | ||
| 94 | + OP_CHECK_NULL(matmulUnzipInput.bias, return false); | ||
| 95 | + OP_CHECK_NULL(matmulUnzipInput.deqScale, return false); | ||
| 96 | + OP_CHECK_NULL(compressInfo, return false); | ||
| 97 | + OP_CHECK_NULL(out, return false); | ||
| 98 | + return true; | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +inline static bool CheckDtypeValid(MatmulUnzipInput matmulUnzipInput, const aclTensor* out) | ||
| 102 | +{ | ||
| 103 | + OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.x1, DTYPE_SUPPORT_LIST, return false); | ||
| 104 | + OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.x2, DTYPE_SUPPORT_LIST, return false); | ||
| 105 | + OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.compressIndex, DTYPE_SUPPORT_LIST, return false); | ||
| 106 | + OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.bias, BIAS_DTYPE_SUPPORT_LIST, return false); | ||
| 107 | + OP_CHECK_DTYPE_NOT_SUPPORT(matmulUnzipInput.deqScale, DEQ_SCALE_DTYPE_SUPPORT_LIST, return false); | ||
| 108 | + OP_CHECK_DTYPE_NOT_SUPPORT(out, OUT_DTYPE_SUPPORT_LIST, return false); | ||
| 109 | + return true; | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | +static bool CheckShapeValid(const aclTensor* x1, const aclTensor* x2, const aclIntArray* compressInfo) | ||
| 113 | +{ | ||
| 114 | + op::Shape x1Shape = x1->GetViewShape(); | ||
| 115 | + op::Shape x2Shape = x2->GetViewShape(); | ||
| 116 | + auto dimTensor1 = x1Shape.GetDimNum(); | ||
| 117 | + auto dimTensor2 = x2Shape.GetDimNum(); | ||
| 118 | + int64_t x1KDim = 0; | ||
| 119 | + int64_t x2KDim = 0; | ||
| 120 | + | ||
| 121 | + if (dimTensor1 != 2 || dimTensor2 != 1) { // ND format dims > 2 for x1 | ||
| 122 | + OP_LOGE( | ||
| 123 | + ACLNN_ERR_PARAM_INVALID, "MatmulUnzip not support x1 shape %s, x2 shape %s", | ||
| 124 | + op::ToString(x1Shape).GetString(), op::ToString(x2Shape).GetString()); | ||
| 125 | + return false; | ||
| 126 | + } else { | ||
| 127 | + x1KDim = x1Shape.GetDim(dimTensor1 - 1); | ||
| 128 | + x2KDim = (*compressInfo)[K_DIMENSION_INDEX]; | ||
| 129 | + if (x1KDim != x2KDim) { | ||
| 130 | + OP_LOGE( | ||
| 131 | + ACLNN_ERR_PARAM_INVALID, "The k-axis of the two inputs are different %s, %s", | ||
| 132 | + op::ToString(x1Shape).GetString(), op::ToString(x2Shape).GetString()); | ||
| 133 | + return false; | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + return true; | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +inline static aclnnStatus CheckParam(MatmulUnzipInput matmulUnzipInput, const aclIntArray* compressInfo, | ||
| 141 | + const aclTensor* out) | ||
| 142 | +{ | ||
| 143 | + // 1. 检查参数是否为空指针 | ||
| 144 | + CHECK_RET(CheckNotNull(matmulUnzipInput, compressInfo, out), ACLNN_ERR_PARAM_NULLPTR); | ||
| 145 | + // 2. 检查输入的数据类型是否在API支持的数据类型范围之内,需要根据api定义校验 | ||
| 146 | + CHECK_RET(CheckDtypeValid(matmulUnzipInput, out), ACLNN_ERR_PARAM_INVALID); | ||
| 147 | + // 3. 检查Shape是否支持 | ||
| 148 | + CHECK_RET(CheckShapeValid(matmulUnzipInput.x1, matmulUnzipInput.x2, compressInfo), ACLNN_ERR_PARAM_INVALID); | ||
| 149 | + | ||
| 150 | + return ACLNN_SUCCESS; | ||
| 151 | +} | ||
| 152 | + | ||
| 153 | +static const aclTensor* ProcessEmptyTensor(const aclTensor* x1, const aclTensor* out, aclOpExecutor* executor) | ||
| 154 | +{ | ||
| 155 | + // 获取shape信息 | ||
| 156 | + op::Shape outShape = out->GetViewShape(); | ||
| 157 | + auto output = executor->AllocTensor(outShape, x1->GetDataType()); | ||
| 158 | + if (output->IsEmpty()) { | ||
| 159 | + OP_LOGI("Returning an empty tensor without actually doing calculation"); | ||
| 160 | + return output; | ||
| 161 | + } | ||
| 162 | + FVector<int64_t> fillShape = GetShape(output); | ||
| 163 | + const aclTensor* dims = executor->ConvertToTensor(fillShape.data(), fillShape.size(), op::DataType::DT_INT64); | ||
| 164 | + aclIntArray* shapeArray = executor->AllocIntArray(fillShape.data(), fillShape.size()); | ||
| 165 | + const aclScalar* valueScalar = executor->AllocScalar(0); | ||
| 166 | + const aclTensor* valueTensor = executor->ConvertToTensor(valueScalar, out->GetDataType()); | ||
| 167 | + auto fillTensor = l0op::Fill(dims, valueTensor, shapeArray, executor); | ||
| 168 | + return fillTensor; | ||
| 169 | +} | ||
| 170 | + | ||
| 171 | +inline static const aclTensor* TensorReformat(const aclTensor* x, const op::Format& format, aclOpExecutor* executor) | ||
| 172 | +{ | ||
| 173 | + auto formatTensor = executor == nullptr ? const_cast<aclTensor*>(x) : | ||
| 174 | + executor->CreateView(x, x->GetViewShape(), x->GetViewOffset()); | ||
| 175 | + formatTensor->SetViewFormat(format); | ||
| 176 | + formatTensor->SetOriginalFormat(format); | ||
| 177 | + formatTensor->SetStorageFormat(format); | ||
| 178 | + return formatTensor; | ||
| 179 | +} | ||
| 180 | + | ||
| 181 | +static aclnnStatus InputsContiguousAndTransFormat(const aclTensor* tensor, const aclTensor*& reformatedTensor, | ||
| 182 | + const std::string& tensorName, aclOpExecutor* executor) | ||
| 183 | +{ | ||
| 184 | + if (tensor == nullptr) { | ||
| 185 | + return ACLNN_SUCCESS; | ||
| 186 | + } | ||
| 187 | + op::Format tensorFormat = tensor->GetStorageFormat(); | ||
| 188 | + if (tensorFormat != Format::FORMAT_FRACTAL_NZ) { | ||
| 189 | + reformatedTensor = l0op::Contiguous(tensor, executor); | ||
| 190 | + CHECK_COND(reformatedTensor != nullptr, ACLNN_ERR_INNER_NULLPTR, "%s Contiguous failed.", tensorName.c_str()); | ||
| 191 | + | ||
| 192 | + bool is310P = GetCurrentPlatformInfo().GetSocVersion() == SocVersion::ASCEND310P; | ||
| 193 | + // only in 310P, tensor should be transdata to NZ format | ||
| 194 | + if (!is310P) { | ||
| 195 | + return ACLNN_SUCCESS; | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + reformatedTensor = l0op::TransData(reformatedTensor, Format::FORMAT_FRACTAL_NZ, 1, executor); | ||
| 199 | + CHECK_COND(reformatedTensor != nullptr, ACLNN_ERR_INNER_NULLPTR, "%s TransData failed.", tensorName.c_str()); | ||
| 200 | + return ACLNN_SUCCESS; | ||
| 201 | + } | ||
| 202 | + reformatedTensor = tensor; | ||
| 203 | + return ACLNN_SUCCESS; | ||
| 204 | +} | ||
| 205 | + | ||
| 206 | +static const aclTensor* BuildMatMulUnzipGraph(MatmulUnzipInput matmulUnzipInput, const int offsetX, | ||
| 207 | + const aclIntArray* compressInfo, aclTensor* out, | ||
| 208 | + aclOpExecutor* executor) | ||
| 209 | +{ | ||
| 210 | + /* | ||
| 211 | + * x1 x2 | ||
| 212 | + * | | | ||
| 213 | + * x1FractalNZ x2ReformatFractalZ | ||
| 214 | + * | | | ||
| 215 | + * \ / | ||
| 216 | + * matmulv2_compress_unzip -- compressIndex, bias, deqScale(format?), offsetW, offsetX, compressInfo | ||
| 217 | + * | | ||
| 218 | + * out | ||
| 219 | + * | | ||
| 220 | + * outND | ||
| 221 | + */ | ||
| 222 | + | ||
| 223 | + // 空tensor 处理 | ||
| 224 | + if (matmulUnzipInput.x1->IsEmpty() || matmulUnzipInput.x2->IsEmpty()) { | ||
| 225 | + auto emptyOut = ProcessEmptyTensor(matmulUnzipInput.x1, out, executor); | ||
| 226 | + CHECK_RET(emptyOut != nullptr, nullptr); | ||
| 227 | + return emptyOut; | ||
| 228 | + } | ||
| 229 | + const aclTensor* reformatedX = nullptr; | ||
| 230 | + (void)InputsContiguousAndTransFormat(matmulUnzipInput.x1, reformatedX, "x1", executor); | ||
V
建议改为:
![]() ![]() wmg1 5月19日 评论: 5月19日 评论: | |||
| 231 | + matmulUnzipInput.bias = l0op::Contiguous(matmulUnzipInput.bias, executor); | ||
| 232 | + CHECK_RET(matmulUnzipInput.bias != nullptr, nullptr); | ||
| 233 | + const aclTensor* deqScale5HD = matmulUnzipInput.deqScale; | ||
| 234 | + if (matmulUnzipInput.deqScale->Numel() % DEQUANT_SCALE_ALIGN_SIZE == 0) { | ||
| 235 | + deqScale5HD = TensorReformat(matmulUnzipInput.deqScale, op::Format::FORMAT_NC1HWC0, executor); | ||
| 236 | + } else { | ||
| 237 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Dequant Scale is invalid Data."); | ||
| 238 | + return ProcessEmptyTensor(matmulUnzipInput.x1, out, executor); | ||
| 239 | + } | ||
| 240 | + const aclTensor* x2ReFormatFractalZ = TensorReformat(matmulUnzipInput.x2, op::Format::FORMAT_FRACTAL_Z, executor); | ||
| 241 | + const aclTensor* matmulOut = l0op::MatMulCompressDequant( | ||
| 242 | + reformatedX, x2ReFormatFractalZ, matmulUnzipInput.compressIndex, deqScale5HD, matmulUnzipInput.bias, nullptr, | ||
| 243 | + false, false, compressInfo, offsetX, GetAlgStr(UnzipMode::WEIGHT_UNZIP), executor); | ||
| 244 | + CHECK_RET(matmulOut != nullptr, nullptr); | ||
| 245 | + // TransData out format from NZ to ND | ||
| 246 | + auto matmulOutND = l0op::TransData(matmulOut, op::Format::FORMAT_ND, 1, executor); | ||
| 247 | + CHECK_RET(matmulOutND != nullptr, nullptr); | ||
| 248 | + | ||
| 249 | + return matmulOutND; | ||
| 250 | +} | ||
| 251 | + | ||
| 252 | +aclnnStatus aclnnMatmulCompressDequantGetWorkspaceSize(const aclTensor* x1, const aclTensor* x2, | ||
| 253 | + const aclTensor* compressIndex, const aclTensor* bias, | ||
| 254 | + const aclTensor* deqScale, const aclTensor* offsetW, | ||
| 255 | + int offsetX, const aclIntArray* compressInfo, aclTensor* out, | ||
| 256 | + uint64_t* workspaceSize, aclOpExecutor** executor) | ||
| 257 | +{ | ||
| 258 | + L2_DFX_PHASE_1( | ||
| 259 | + aclnnMatmulCompressDequant, DFX_IN(x1, x2, compressIndex, bias, deqScale, offsetX, compressInfo), DFX_OUT(out)); | ||
| 260 | + // 固定写法,创建OpExecutor | ||
| 261 | + auto uniqueExecutor = CREATE_EXECUTOR(); | ||
| 262 | + CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | ||
| 263 | + // 入参初始化 | ||
| 264 | + MatmulUnzipInput matmulUnzipInput; | ||
| 265 | + matmulUnzipInput.x1 = x1; | ||
| 266 | + matmulUnzipInput.x2 = x2; | ||
| 267 | + matmulUnzipInput.compressIndex = compressIndex; | ||
| 268 | + matmulUnzipInput.bias = bias; | ||
| 269 | + matmulUnzipInput.deqScale = deqScale; | ||
| 270 | + matmulUnzipInput.offsetW = offsetW; | ||
| 271 | + | ||
| 272 | + // 入参检查 | ||
| 273 | + auto ret = CheckParam(matmulUnzipInput, compressInfo, out); | ||
| 274 | + CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 275 | + | ||
| 276 | + // 构建matmul_unzip计算图 | ||
| 277 | + auto matmulOut = BuildMatMulUnzipGraph(matmulUnzipInput, offsetX, compressInfo, out, uniqueExecutor.get()); | ||
| 278 | + CHECK_RET(matmulOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 279 | + if (matmulOut->IsEmpty()) { | ||
| 280 | + // 当输出为空tensor的场景,空tensor处理 | ||
| 281 | + *workspaceSize = 0; | ||
| 282 | + uniqueExecutor.ReleaseTo(executor); | ||
| 283 | + return ACLNN_SUCCESS; | ||
| 284 | + } | ||
| 285 | + | ||
| 286 | + auto viewCopyResult = l0op::ViewCopy(matmulOut, out, uniqueExecutor.get()); | ||
| 287 | + CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 288 | + | ||
| 289 | + // 获取workspace | ||
| 290 | + *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 291 | + uniqueExecutor.ReleaseTo(executor); | ||
| 292 | + return ACLNN_SUCCESS; | ||
| 293 | +} | ||
| 294 | + | ||
| 295 | +aclnnStatus aclnnMatmulCompressDequant( | ||
| 296 | + void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) | ||
| 297 | +{ | ||
| 298 | + L2_DFX_PHASE_2(aclnnMatmulCompressDequant); | ||
| 299 | + // 固定写法,调用框架能力,完成计算 | ||
| 300 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 301 | +} | ||
| 302 | + | ||
| 303 | + | ||
| 304 | +} | ||
| 305 | + | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +extern "C" { | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * @brief aclnnMatmulCompressDequant的第一段接口,根据具体的计算流程,计算workspace大小。 | ||
| 22 | + * @domain aclnn_ops_infer | ||
| 23 | + */ | ||
| 24 | +ACLNN_API aclnnStatus aclnnMatmulCompressDequantGetWorkspaceSize(const aclTensor* x1, const aclTensor* x2, | ||
| 25 | + const aclTensor* compressIndex, const aclTensor* bias, | ||
| 26 | + const aclTensor* deqScale, const aclTensor* offsetW, | ||
| 27 | + int offsetX, const aclIntArray* compressInfo, | ||
| 28 | + aclTensor* out, uint64_t* workspaceSize, | ||
| 29 | + aclOpExecutor** executor); | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * @brief aclnnMatmulCompressDequant的第二段接口,用于执行计算。 | ||
| 33 | + */ | ||
| 34 | +ACLNN_API aclnnStatus aclnnMatmulCompressDequant(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, | ||
| 35 | + aclrtStream stream); | ||
| 36 | + | ||
| 37 | + | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ||
| @@ -0,0 +1,44 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +using namespace op; | ||
| 20 | + | ||
| 21 | +namespace l0op { | ||
| 22 | + | ||
| 23 | +OP_TYPE_REGISTER(MatMulV2CompressDequant); | ||
| 24 | +// 用大小写区分是否可以区分两个不同的kernel | ||
| 25 | +const aclTensor *MatMulCompressDequant(const aclTensor *x1, const aclTensor *x2, const aclTensor *compressIndex, | ||
| 26 | + const aclTensor *deqScale, const aclTensor *bias, const aclTensor *offsetW, | ||
| 27 | + const bool transposeX1, const bool transposeX2, const aclIntArray *compressInfo, | ||
| 28 | + const int offsetX, const std::string &algStr, aclOpExecutor *executor) { | ||
| 29 | + L0_DFX(MatMulCompressDequant, x1, x2, compressIndex, deqScale, bias, offsetW, transposeX1, transposeX2, | ||
| 30 | + compressInfo, offsetX, algStr); | ||
| 31 | + auto mmCompressDequantOut = executor->AllocTensor(DataType::DT_FLOAT16, Format::FORMAT_FRACTAL_NZ, Format::FORMAT_ND); | ||
| 32 | + // 是否可以复用tbe的infershape | ||
| 33 | + auto ret = INFER_SHAPE(MatMulV2CompressDequant, OP_INPUT(x1, x2, compressIndex, deqScale, bias, offsetW), | ||
| 34 | + OP_OUTPUT(mmCompressDequantOut), OP_ATTR(transposeX1, transposeX2, compressInfo, offsetX, algStr)); | ||
| 35 | + OP_CHECK_INFERSHAPE(ret != ACLNN_SUCCESS, return nullptr, "MatMulCompressDequant InferShape failed."); | ||
| 36 | + // 使用新的MatmulV2CompressDequant内核 | ||
| 37 | + ret = ADD_TO_LAUNCHER_LIST_AICORE(MatMulV2CompressDequant, OP_INPUT(x1, x2, compressIndex, deqScale, bias, offsetW), | ||
| 38 | + OP_OUTPUT(mmCompressDequantOut), | ||
| 39 | + OP_ATTR(transposeX1, transposeX2, compressInfo, offsetX, algStr)); | ||
| 40 | + OP_CHECK_ADD_TO_LAUNCHER_LIST_AICORE(ret != ACLNN_SUCCESS, return nullptr, | ||
| 41 | + "MatMulCompressDequant ADD_TO_LAUNCHER_LIST_AICORE failed."); | ||
| 42 | + return mmCompressDequantOut; | ||
| 43 | +}; | ||
| 44 | +} // namespace l0op | ||
| @@ -0,0 +1,25 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +namespace l0op { | ||
| 16 | + | ||
| 17 | +const aclTensor *MatMulCompressDequant(const aclTensor *x1, const aclTensor *x2, const aclTensor *compressIndex, | ||
| 18 | + const aclTensor *deqScale, const aclTensor *bias, const aclTensor *offsetW, | ||
| 19 | + const bool transposeX1, const bool transposeX2, const aclIntArray *compressInfo, | ||
| 20 | + const int offsetX, const std::string &algStr, aclOpExecutor *executor); | ||
| 21 | + | ||
| 22 | +} // namespace l0op | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| @@ -0,0 +1,254 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file pp_matmul_common_tiling.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace optiling { | ||
| 25 | +namespace pp_matmul { | ||
| 26 | +namespace matmulCompressDequant { | ||
| 27 | + | ||
| 28 | +constexpr uint64_t FP16_SIZE = 2; | ||
| 29 | +constexpr uint64_t FP32_SIZE = 4; | ||
| 30 | +constexpr uint64_t BLOCK_SIZE = 16; | ||
| 31 | +constexpr uint64_t BLOCK_SIZE_INT8_K = 32; | ||
| 32 | +constexpr uint64_t BASE_BLOCK_STEP = 2; | ||
| 33 | +constexpr uint64_t AXES_ALIGN_SIZE = 512; | ||
| 34 | +constexpr uint64_t AXES_ALIGN_SIZE_INT8 = 256; | ||
| 35 | +constexpr uint64_t ND_SHAPE_SIZE = 2; | ||
| 36 | +constexpr uint64_t NZ_SHAPE_SIZE = 4; | ||
| 37 | +constexpr uint64_t CUBE_BLOCK_SIZE = 256; | ||
| 38 | +constexpr uint64_t CUBE_BLOCK_SIZE_INT8 = 512; | ||
| 39 | +constexpr uint64_t L1AB_PINGPONG_BUFFER_SIZE = 262144; | ||
| 40 | +constexpr uint64_t L0AB_PINGPONG_BUFFER_SIZE_INT8 = 262144; // 131072 * 2 = 256 KB | ||
| 41 | +constexpr uint64_t L0AB_PINGPONG_BUFFER_SIZE_FP16 = 131072; // 128 KB | ||
| 42 | +constexpr uint64_t L1AB_PINGPONG_BUFFER_SIZE_INT8_SPARSE = 163840; // 160 * 1024 | ||
| 43 | +constexpr uint64_t UB_LIMIT_SIZE_910A = 131072; // 128 * 1024 | ||
| 44 | + | ||
| 45 | +template <uint64_t DIV> | ||
| 46 | +inline uint64_t CeilDiv(uint64_t num) | ||
| 47 | +{ | ||
| 48 | + if (DIV == 0UL || num + DIV - 1UL < num) { | ||
| 49 | + return num; | ||
| 50 | + } | ||
| 51 | + return (num + DIV - 1UL) / DIV; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +inline uint64_t CeilDiv(uint64_t dividend, uint64_t divisor) | ||
| 55 | +{ | ||
| 56 | + if (divisor == 0UL || dividend + divisor - 1UL < dividend) { | ||
| 57 | + return dividend; | ||
| 58 | + } | ||
| 59 | + return (dividend + divisor - 1UL) / divisor; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +template <uint64_t RND> | ||
| 63 | +inline uint64_t Round(uint64_t num) | ||
| 64 | +{ | ||
| 65 | + if (RND == 0UL || num + RND - 1UL < num) { | ||
| 66 | + return num; | ||
| 67 | + } | ||
| 68 | + return (num + RND - 1UL) / RND * RND; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +inline uint64_t RoundUp(uint64_t num, uint64_t rnd) | ||
| 72 | +{ | ||
| 73 | + if (rnd == 0UL || num + rnd - 1UL < num) { | ||
| 74 | + return num; | ||
| 75 | + } | ||
| 76 | + return (num + rnd - 1UL) / rnd * rnd; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +inline int64_t RoundUp(int64_t num, int64_t rnd) | ||
| 80 | +{ | ||
| 81 | + if (rnd == 0UL || static_cast<int64_t>(num + rnd - 1) < num) { | ||
| 82 | + return num; | ||
| 83 | + } | ||
| 84 | + return static_cast<int64_t>((num + rnd - 1) / rnd * rnd); | ||
| 85 | +} | ||
| 86 | + | ||
| 87 | +inline uint64_t RoundDown(uint64_t num, uint64_t rnd) | ||
| 88 | +{ | ||
| 89 | + if (rnd == 0UL) { | ||
| 90 | + return 0UL; | ||
| 91 | + } | ||
| 92 | + return num / rnd * rnd; | ||
| 93 | +} | ||
| 94 | + | ||
| 95 | +template <typename T1, typename T2> | ||
| 96 | +T2 CalcTailSize(T1 num1, T2 num2) | ||
| 97 | +{ | ||
| 98 | + if (num2 == 0) { | ||
| 99 | + return 0; | ||
| 100 | + } | ||
| 101 | + T1 mod = num1 % static_cast<T1>(num2); | ||
| 102 | + return mod; | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +inline uint64_t GetN0TilingLimit(bool compressFlag, uint64_t tilingN, const platform_ascendc::SocVersion &platformType) | ||
| 106 | +{ | ||
| 107 | + if (compressFlag) { | ||
| 108 | + return std::min(tilingN * BLOCK_SIZE, AXES_ALIGN_SIZE_INT8); | ||
| 109 | + } else { | ||
| 110 | + return (platformType == platform_ascendc::SocVersion::ASCEND310P | ||
| 111 | + || platformType == platform_ascendc::SocVersion::ASCEND910) ? AXES_ALIGN_SIZE : AXES_ALIGN_SIZE_INT8; | ||
| 112 | + } | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +template <typename OpShareType> | ||
| 116 | +inline uint64_t GetN0TilingInit(const OpShareType &opShape, bool compressFlag, uint64_t tilingN) | ||
| 117 | +{ | ||
| 118 | + const uint64_t RND = 16UL; | ||
| 119 | + if (compressFlag) { | ||
| 120 | + if (tilingN * BLOCK_SIZE > opShape.n) { | ||
| 121 | + return Round<RND>(opShape.n); | ||
| 122 | + } else { | ||
| 123 | + return tilingN * BLOCK_SIZE; | ||
| 124 | + } | ||
| 125 | + } else { | ||
| 126 | + return BLOCK_SIZE; | ||
| 127 | + } | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +template <bool PRI_FLAG> | ||
| 131 | +inline bool IsExceedTilingLimit(uint64_t axes0, uint64_t priAxes0, | ||
| 132 | + uint64_t n0TilingLimit, platform_ascendc::SocVersion platformType, | ||
| 133 | + uint64_t basicBlockSize) | ||
| 134 | +{ | ||
| 135 | + return (PRI_FLAG && axes0 > n0TilingLimit) || (!PRI_FLAG && priAxes0 > n0TilingLimit) || | ||
| 136 | + (platformType == platform_ascendc::SocVersion::ASCEND910 && basicBlockSize > UB_LIMIT_SIZE_910A); | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +template <bool PRI_FLAG, typename OpShareType> | ||
| 140 | +inline void SetOpShapeAxesInfo(OpShareType &opShape, uint64_t priAxes0, uint64_t axes0) | ||
| 141 | +{ | ||
| 142 | + opShape.m0 = PRI_FLAG ? priAxes0 : axes0; | ||
| 143 | + opShape.n0 = PRI_FLAG ? axes0 : priAxes0; | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +template <typename HardwareType, typename OpShapeType, typename MatMulInfoType> | ||
| 147 | +inline float CostFunc(const HardwareType &hwInfor, OpShapeType &shape, const MatMulInfoType &mmInfo) | ||
| 148 | +{ | ||
| 149 | + float aCoef = 1; | ||
| 150 | + float bCoef = 1; | ||
| 151 | + float bwCoef = static_cast<float>(hwInfor.l2BandWidth) / static_cast<float>(hwInfor.hbmBandWidth); | ||
| 152 | + uint64_t mLoop = CeilDiv(shape.m, shape.m0); | ||
| 153 | + uint64_t nLoop = CeilDiv(shape.n, shape.n0); | ||
| 154 | + if (mLoop == 0UL || nLoop == 0UL) { | ||
| 155 | + return 1; | ||
| 156 | + } | ||
| 157 | + uint64_t coreNeed = shape.batchSize * mLoop * nLoop; | ||
| 158 | + uint64_t blockDim = std::min(coreNeed, hwInfor.coreNum); | ||
| 159 | + uint64_t mOnce = blockDim < nLoop ? shape.m0 : blockDim / nLoop * shape.m0; | ||
| 160 | + uint64_t nOnce = blockDim < nLoop ? hwInfor.coreNum * shape.n0 : shape.n; | ||
| 161 | + (void)mmInfo; | ||
| 162 | + if (mOnce * shape.k * 2 > hwInfor.l2Size) { | ||
| 163 | + aCoef = bwCoef; | ||
| 164 | + } | ||
| 165 | + if (nOnce * shape.k * 2 > hwInfor.l2Size) { | ||
| 166 | + bCoef = bwCoef; | ||
| 167 | + } | ||
| 168 | + return 1 / (aCoef * static_cast<float>(shape.n0)) + 1 / (bCoef * static_cast<float>(shape.m0)); | ||
| 169 | +} | ||
| 170 | + | ||
| 171 | +// OpShareType is OpShape, TilingType is PpTilingData, HardwareType is HardwareType, MatMulInfoType is MatMulInfo | ||
| 172 | +template <bool PRI_FLAG, typename OpShareType, typename TilingType, typename HardwareType, typename MatMulInfoType> | ||
| 173 | +void TilingFunc(OpShareType &opShape, TilingType &tilingParam, const HardwareType &hwInfor, | ||
| 174 | + const MatMulInfoType &mmInfo, bool compressFlag = false, const uint64_t tilingN = 1) | ||
| 175 | +{ | ||
| 176 | + float costMin = 1; | ||
| 177 | + const float CONST_2 = 2.0; | ||
| 178 | + const uint64_t CONST_16 = 16UL; | ||
| 179 | + uint64_t roundBase = | ||
| 180 | + static_cast<uint64_t>(pow(2, ceil(log(CeilDiv(PRI_FLAG ? opShape.n : opShape.m, CONST_16)))) * CONST_16); | ||
| 181 | + uint64_t priAxes = RoundUp(PRI_FLAG ? opShape.m : opShape.n, CONST_16); | ||
| 182 | + uint64_t axes = RoundUp(PRI_FLAG ? opShape.n : opShape.m, roundBase); | ||
| 183 | + float axes0Max = static_cast<float>(AXES_ALIGN_SIZE) / mmInfo.inDtype; | ||
| 184 | + auto platformType = hwInfor.socVersion; | ||
| 185 | + if (mmInfo.isInt8 && (platformType == platform_ascendc::SocVersion::ASCEND310P || | ||
| 186 | + platformType == platform_ascendc::SocVersion::ASCEND910)) { | ||
| 187 | + axes0Max /= CONST_2; | ||
| 188 | + } | ||
| 189 | + uint64_t n0TilingInit = GetN0TilingInit(opShape, compressFlag, tilingN); | ||
| 190 | + uint64_t n0TilingLimit = GetN0TilingLimit(compressFlag, tilingN, platformType); | ||
| 191 | + uint64_t priAxes0Init = PRI_FLAG ? BLOCK_SIZE : n0TilingInit; | ||
| 192 | + uint64_t axes0Init = PRI_FLAG ? n0TilingInit : BLOCK_SIZE; | ||
| 193 | + bool isAscend310P = platformType == platform_ascendc::SocVersion::ASCEND310P; | ||
| 194 | + for (uint64_t priAxes0 = priAxes0Init; priAxes0 <= priAxes && priAxes0 <= axes0Max; priAxes0 *= BASE_BLOCK_STEP) { | ||
| 195 | + for (uint64_t axes0 = axes0Init; axes0 <= axes && axes0 <= axes0Max; axes0 *= BASE_BLOCK_STEP) { | ||
| 196 | + uint64_t basicBlockSize = priAxes0 * axes0 * FP32_SIZE; | ||
| 197 | + if (basicBlockSize > hwInfor.l0cSize) { | ||
| 198 | + continue; | ||
| 199 | + } | ||
| 200 | + if (mmInfo.isInt8 && | ||
| 201 | + IsExceedTilingLimit<PRI_FLAG>(axes0, priAxes0, n0TilingLimit, platformType, basicBlockSize)) { | ||
| 202 | + continue; | ||
| 203 | + } | ||
| 204 | + SetOpShapeAxesInfo<PRI_FLAG>(opShape, priAxes0, axes0); | ||
| 205 | + float cost = CostFunc<HardwareType, OpShareType, MatMulInfoType>(hwInfor, opShape, mmInfo); | ||
| 206 | + if (cost >= costMin) { | ||
| 207 | + continue; | ||
| 208 | + } | ||
| 209 | + costMin = cost; | ||
| 210 | + tilingParam.SetBaseOp(hwInfor.coreNum, hwInfor.l0cSize, opShape.m0, opShape.n0, mmInfo, isAscend310P); | ||
| 211 | + } | ||
| 212 | + } | ||
| 213 | +} | ||
| 214 | + | ||
| 215 | +template <typename PpTilingDataType> | ||
| 216 | +uint64_t Swizzl(PpTilingDataType &tilingData) | ||
| 217 | +{ | ||
| 218 | + uint64_t swizzlDirect = 0UL; | ||
| 219 | + uint64_t swizzlCount = 1UL; | ||
| 220 | + float m0 = tilingData.opShape.m0; | ||
| 221 | + float n0 = tilingData.opShape.n0; | ||
| 222 | + float m = tilingData.opShape.m; | ||
| 223 | + float k = tilingData.opShape.k; | ||
| 224 | + float n = tilingData.opShape.n; | ||
| 225 | + float mincost = m * k + k * n; | ||
| 226 | + | ||
| 227 | + for (uint32_t i = 1; i <= tilingData.blockDim; ++i) { | ||
| 228 | + int c = static_cast<int32_t>((tilingData.blockDim + i - 1) / i); | ||
| 229 | + float cost; | ||
| 230 | + // B0 + A < A0 + B | ||
| 231 | + if (i * n0 + m < m0 * c + n) { | ||
| 232 | + swizzlDirect = 1UL; // Nz | ||
| 233 | + cost = n0 * i + m0 * c; | ||
| 234 | + if (cost <= mincost) { | ||
| 235 | + mincost = cost; | ||
| 236 | + swizzlCount = i; | ||
| 237 | + } | ||
| 238 | + } else { | ||
| 239 | + swizzlDirect = 0UL; // Zn | ||
| 240 | + cost = m0 * i + n0 * c; | ||
| 241 | + if (cost < mincost) { | ||
| 242 | + mincost = cost; | ||
| 243 | + swizzlCount = i; | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | + } | ||
| 247 | + tilingData.swizzlDirect = swizzlDirect; | ||
| 248 | + tilingData.swizzlCount = swizzlCount; | ||
| 249 | + return swizzlDirect; | ||
| 250 | +} | ||
| 251 | +} // namespace matmulCompressDequant | ||
| 252 | +} // namespace pp_matmul | ||
| 253 | +} // namespace optiling | ||
| 254 | + | ||
| @@ -0,0 +1,193 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file pp_matmul_default.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +namespace { | ||
| 28 | +constexpr uint64_t L1_DESCALE_BUFFER_SIZE_MAX = 6144; | ||
| 29 | +constexpr uint64_t CONST_3 = 3; | ||
| 30 | +constexpr uint64_t CONST_4 = 4; | ||
| 31 | +constexpr uint64_t CONST_16 = 16; | ||
| 32 | +constexpr uint64_t CONST_32 = 32; | ||
| 33 | +constexpr uint64_t CONST_256 = 256; | ||
| 34 | +constexpr uint64_t CONST_512 = 512; | ||
| 35 | + | ||
| 36 | +constexpr size_t DIM_2 = 2; | ||
| 37 | +constexpr size_t DIM_3 = 3; | ||
| 38 | +constexpr size_t DIM_4 = 4; | ||
| 39 | +constexpr size_t COMPUTE_TYPE_IDX_CANN = 3; | ||
| 40 | +constexpr size_t COMPUTE_TYPE_IDX_ATB = 10; | ||
| 41 | +constexpr size_t EINSUM_MODE = 4; | ||
| 42 | + | ||
| 43 | +constexpr uint32_t DTYPE_BIT_COUNT = 2; | ||
| 44 | +constexpr uint32_t FORMAT_BIT_COUNT = 1; | ||
| 45 | +constexpr uint32_t COMPUTE_TYPE_BIT_COUNT = 3; | ||
| 46 | +constexpr uint32_t MAX_ATTRS_NUM = 4; | ||
| 47 | +constexpr uint32_t EN_SHUFFFLE_IDX_ATB = 7; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +namespace optiling { | ||
| 51 | +namespace pp_matmul { | ||
| 52 | +namespace matmulCompressDequant { | ||
| 53 | + | ||
| 54 | +class PpMatMulDefault | ||
| 55 | +{ | ||
| 56 | +public: | ||
| 57 | + explicit PpMatMulDefault(gert::TilingContext* context) : context_(context) {} | ||
| 58 | + virtual ~PpMatMulDefault() = default; | ||
| 59 | + | ||
| 60 | + void GetHardwareInfo(); | ||
| 61 | + bool GetMatMulTilingData(); | ||
| 62 | + void PrintTiling(); | ||
| 63 | + gert::TilingContext *context_ = nullptr; | ||
| 64 | + MatMulInfo matMulInfo_; | ||
| 65 | + PpMatmulDefaultTilingData ppMatmulDefaultTilingData_{}; | ||
| 66 | + HardwareInfo hardwareInfo_; | ||
| 67 | + uint64_t kernelKey_; | ||
| 68 | +}; | ||
| 69 | + | ||
| 70 | + | ||
| 71 | +void PpMatmulDefaultTilingData::SetBaseShape(uint64_t batchSize, uint64_t m, uint64_t k, uint64_t n) | ||
| 72 | +{ | ||
| 73 | + opShape.batchSize = batchSize; | ||
| 74 | + opShape.m = m; | ||
| 75 | + opShape.k = k; | ||
| 76 | + opShape.n = n; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +void PpMatmulDefaultTilingData::SetBaseOp(uint64_t coreNum, uint64_t l0cSize, uint64_t mBase, uint64_t nBase, | ||
| 80 | + const MatMulInfo &mmInfo, bool isAscend310P) | ||
| 81 | +{ | ||
| 82 | + opShape.m0 = mBase; | ||
| 83 | + opShape.n0 = nBase; | ||
| 84 | + mLoop = CeilDiv(opShape.m, opShape.m0); | ||
| 85 | + nLoop = CeilDiv(opShape.n, opShape.n0); | ||
| 86 | + coreLoop = opShape.batchSize * mLoop * nLoop; | ||
| 87 | + if (!isAscend310P && mLoop == 1UL && mmInfo.transB && static_cast<uint64_t>(CalcTailSize(coreLoop,coreNum)) < | ||
| 88 | + static_cast<uint64_t>(coreNum / CONST_4) * CONST_3) { | ||
| 89 | + mBase = RoundUp(opShape.m, CONST_16); | ||
| 90 | + opShape.m0 = mBase; | ||
| 91 | + uint64_t maxN0 = l0cSize / (mBase * sizeof(float)); | ||
| 92 | + uint64_t x = CeilDiv(opShape.n, coreNum); | ||
| 93 | + uint64_t y = CeilDiv(x, maxN0); | ||
| 94 | + nBase = RoundUp(CeilDiv(x, y), CONST_16); | ||
| 95 | + uint64_t rqdL0CSize = mBase * nBase * sizeof(float); | ||
| 96 | + if (rqdL0CSize < l0cSize && | ||
| 97 | + (mBase + nBase) * CONST_256 * sizeof(uint16_t) < L1AB_PINGPONG_BUFFER_SIZE) { | ||
| 98 | + opShape.n0 = nBase; | ||
| 99 | + nLoop = CeilDiv(opShape.n, opShape.n0); | ||
| 100 | + coreLoop = opShape.batchSize * nLoop; | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + blockDim = std::min(coreLoop, coreNum); | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +void PpMatmulDefaultTilingData::End(const MatMulInfo &mmInfo, bool isAscend310P) | ||
| 107 | +{ | ||
| 108 | + uint64_t shapeSum = opShape.m0 + opShape.n0; | ||
| 109 | + if (!isAscend310P) { | ||
| 110 | + uint64_t k0Max = shapeSum == 0UL | ||
| 111 | + ? L1AB_PINGPONG_BUFFER_SIZE | ||
| 112 | + : static_cast<uint64_t>(static_cast<float>(L1AB_PINGPONG_BUFFER_SIZE) | ||
| 113 | + / (shapeSum * mmInfo.inDtype)); | ||
| 114 | + opShape.k0 = k0Max < CUBE_BLOCK_SIZE ? RoundDown(k0Max, BLOCK_SIZE) : RoundDown(k0Max, CUBE_BLOCK_SIZE); | ||
| 115 | + if (opShape.k0 > CONST_512) { | ||
| 116 | + opShape.k0 = RoundDown(opShape.k0, CONST_512); | ||
| 117 | + } | ||
| 118 | + } else { | ||
| 119 | + uint32_t k0Max = (shapeSum == 0UL) ? UB_LIMIT_SIZE_910A : (UB_LIMIT_SIZE_910A / shapeSum); | ||
| 120 | + opShape.k0 = k0Max < CUBE_BLOCK_SIZE ? k0Max / BLOCK_SIZE * BLOCK_SIZE : \ | ||
| 121 | + k0Max / CUBE_BLOCK_SIZE * CUBE_BLOCK_SIZE; // k0Max less than 256, matrix 16 | ||
| 122 | + } | ||
| 123 | + // 删除 | ||
| 124 | + opShape.k0 = 512; | ||
| 125 | + kLoop = CeilDiv(opShape.k, opShape.k0); | ||
| 126 | +} | ||
| 127 | + | ||
| 128 | + | ||
| 129 | +void PpMatMulDefault::GetHardwareInfo() | ||
| 130 | +{ | ||
| 131 | + auto platformInfo = context_->GetPlatformInfo(); | ||
| 132 | + if (platformInfo == nullptr) { | ||
| 133 | + OP_LOGE("[PpMatMul]", "platformInfo is nullptr"); | ||
| 134 | + return; | ||
| 135 | + } | ||
| 136 | + HardwareInfo hardwareInfo; | ||
| 137 | + | ||
| 138 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo); | ||
| 139 | + platformInfo->GetPlatformRes("version", "SoC_version", hardwareInfo.socVersionStr); | ||
| 140 | + | ||
| 141 | + hardwareInfo.coreNum = static_cast<uint64_t>(ascendcPlatform.GetCoreNumAic()); | ||
| 142 | + hardwareInfo.socVersion = ascendcPlatform.GetSocVersion(); | ||
| 143 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L2, hardwareInfo.l2Size); | ||
| 144 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L1, hardwareInfo.l1Size); | ||
| 145 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_A, hardwareInfo.l0aSize); | ||
| 146 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_B, hardwareInfo.l0bSize); | ||
| 147 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::L0_C, hardwareInfo.l0cSize); | ||
| 148 | + hardwareInfo_ = hardwareInfo; | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | + | ||
| 152 | +bool PpMatMulDefault::GetMatMulTilingData() | ||
| 153 | +{ | ||
| 154 | + ppMatmulDefaultTilingData_.SetBaseShape(matMulInfo_.batchSize, matMulInfo_.m, matMulInfo_.k, matMulInfo_.n); | ||
| 155 | + OpShape opShape = ppMatmulDefaultTilingData_.opShape; | ||
| 156 | + if (opShape.m < opShape.n) { | ||
| 157 | + TilingFunc<false, OpShape, PpMatmulDefaultTilingData, HardwareInfo, MatMulInfo>(opShape, | ||
| 158 | + ppMatmulDefaultTilingData_, hardwareInfo_, matMulInfo_, true, 8); | ||
| 159 | + } else { | ||
| 160 | + TilingFunc<true, OpShape, PpMatmulDefaultTilingData, HardwareInfo, MatMulInfo>(opShape, | ||
| 161 | + ppMatmulDefaultTilingData_, hardwareInfo_, matMulInfo_, true, 8); | ||
| 162 | + } | ||
| 163 | + Swizzl<PpMatmulDefaultTilingData>(ppMatmulDefaultTilingData_); | ||
| 164 | + ppMatmulDefaultTilingData_.End(matMulInfo_, hardwareInfo_.socVersion == platform_ascendc::SocVersion::ASCEND310P); | ||
| 165 | + return true; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | + | ||
| 169 | +void PpMatMulDefault::PrintTiling() | ||
| 170 | +{ | ||
| 171 | + OP_LOGD(context_->GetNodeName(), "PpMatMul batchSize: %ld.", ppMatmulDefaultTilingData_.opShape.batchSize); | ||
| 172 | + OP_LOGD(context_->GetNodeName(), "PpMatMul m: %ld.", ppMatmulDefaultTilingData_.opShape.m); | ||
| 173 | + OP_LOGD(context_->GetNodeName(), "PpMatMul k: %ld.", ppMatmulDefaultTilingData_.opShape.k); | ||
| 174 | + OP_LOGD(context_->GetNodeName(), "PpMatMul n: %ld.", ppMatmulDefaultTilingData_.opShape.n); | ||
| 175 | + OP_LOGD(context_->GetNodeName(), "PpMatMul m0: %ld.", ppMatmulDefaultTilingData_.opShape.m0); | ||
| 176 | + OP_LOGD(context_->GetNodeName(), "PpMatMul k0: %ld.", ppMatmulDefaultTilingData_.opShape.k0); | ||
| 177 | + OP_LOGD(context_->GetNodeName(), "PpMatMul n0: %ld.", ppMatmulDefaultTilingData_.opShape.n0); | ||
| 178 | + OP_LOGD(context_->GetNodeName(), "PpMatMul mLoop: %ld.", ppMatmulDefaultTilingData_.mLoop); | ||
| 179 | + OP_LOGD(context_->GetNodeName(), "PpMatMul kLoop: %ld.", ppMatmulDefaultTilingData_.kLoop); | ||
| 180 | + OP_LOGD(context_->GetNodeName(), "PpMatMul nLoop: %ld.", ppMatmulDefaultTilingData_.nLoop); | ||
| 181 | + OP_LOGD(context_->GetNodeName(), "PpMatMul coreLoop: %ld.", ppMatmulDefaultTilingData_.coreLoop); | ||
| 182 | + OP_LOGD(context_->GetNodeName(), "PpMatMul swizzlCount: %ld.", ppMatmulDefaultTilingData_.swizzlCount); | ||
| 183 | + OP_LOGD(context_->GetNodeName(), "PpMatMul tilingKey: %d.", ppMatmulDefaultTilingData_.tilingKey); | ||
| 184 | + OP_LOGD(context_->GetNodeName(), "PpMatMul blockDim: %ld.", ppMatmulDefaultTilingData_.blockDim); | ||
| 185 | + OP_LOGD(context_->GetNodeName(), "PpMatMul swizzlDirect: %ld.", ppMatmulDefaultTilingData_.swizzlDirect); | ||
| 186 | + OP_LOGD(context_->GetNodeName(), "PpMatMul splitk: %ld.", ppMatmulDefaultTilingData_.splitk); | ||
| 187 | + OP_LOGD(context_->GetNodeName(), "PpMatMul enShuffleK: %ld.", ppMatmulDefaultTilingData_.enShuffleK); | ||
| 188 | +} | ||
| 189 | + | ||
| 190 | +} | ||
| 191 | +} | ||
| 192 | +} | ||
| 193 | + | ||
| @@ -0,0 +1,90 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file pp_matmul_info.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace optiling { | ||
| 25 | +namespace pp_matmul { | ||
| 26 | +namespace matmulCompressDequant { | ||
| 27 | +struct MatMulInfo { | ||
| 28 | + uint64_t batchSize{0}; | ||
| 29 | + uint64_t m{0}; // 实际输入的 m | ||
| 30 | + uint64_t n{0}; // 实际输入的 n | ||
| 31 | + uint64_t k{0}; // 实际输入的 k | ||
| 32 | + ge::DataType dtypeA = ge::DT_FLOAT16; | ||
| 33 | + ge::DataType dtypeB = ge::DT_FLOAT16; | ||
| 34 | + ge::DataType dtypeC = ge::DT_FLOAT16; | ||
| 35 | + ge::Format formatA = ge::FORMAT_ND; | ||
| 36 | + ge::Format formatB = ge::FORMAT_ND; | ||
| 37 | + ge::Format formatC = ge::FORMAT_ND; | ||
| 38 | + uint64_t transA{0}; | ||
| 39 | + uint64_t transB{0}; | ||
| 40 | + bool biasFlag{0}; // false: 0, true: 1 | ||
| 41 | + bool isInt8{0}; // 是否shi int8融合 | ||
| 42 | + float inDtype{0}; | ||
| 43 | + float outDtype{0}; | ||
| 44 | +}; | ||
| 45 | + | ||
| 46 | +struct HardwareInfo { | ||
| 47 | + uint64_t coreNum{0}; | ||
| 48 | + uint64_t l2Size{0}; | ||
| 49 | + uint64_t l1Size{0}; | ||
| 50 | + uint64_t l0aSize{0}; | ||
| 51 | + uint64_t l0bSize{0}; | ||
| 52 | + uint64_t l0cSize{0}; | ||
| 53 | + uint64_t hbmBandWidth{1}; | ||
| 54 | + uint64_t l2BandWidth{5}; // 5x faster than hbm. | ||
| 55 | + platform_ascendc::SocVersion socVersion = platform_ascendc::SocVersion::ASCEND910B; | ||
| 56 | + std::string socVersionStr = ""; | ||
| 57 | +}; | ||
| 58 | + | ||
| 59 | +struct OpShape { | ||
| 60 | + uint64_t batchSize{0}; | ||
| 61 | + uint64_t m{0}; | ||
| 62 | + uint64_t k{0}; | ||
| 63 | + uint64_t n{0}; | ||
| 64 | + uint64_t m0{0}; | ||
| 65 | + uint64_t k0{0}; | ||
| 66 | + uint64_t n0{0}; | ||
| 67 | +}; | ||
| 68 | + | ||
| 69 | +struct PpMatmulDefaultTilingData { | ||
| 70 | + OpShape opShape{}; | ||
| 71 | + uint64_t mLoop{1}; | ||
| 72 | + uint64_t kLoop{1}; | ||
| 73 | + uint64_t nLoop{1}; | ||
| 74 | + uint64_t coreLoop{1}; | ||
| 75 | + uint64_t swizzlCount{1}; | ||
| 76 | + uint32_t tilingKey{0}; | ||
| 77 | + uint64_t blockDim{1}; | ||
| 78 | + uint64_t swizzlDirect{0}; | ||
| 79 | + uint64_t splitk{0}; | ||
| 80 | + uint64_t enShuffleK{0}; | ||
| 81 | + | ||
| 82 | + void SetBaseShape(uint64_t batchSize, uint64_t m, uint64_t k, uint64_t n); | ||
| 83 | + void SetBaseOp(uint64_t coreNum, uint64_t l0cSize, uint64_t mBase, uint64_t nBase, | ||
| 84 | + const MatMulInfo &mmInfo, bool isAscend310P); | ||
| 85 | + void End(const MatMulInfo &mmInfo, bool isAscend310P); | ||
| 86 | +}; | ||
| 87 | +} // namespace matmulCompressDequant | ||
| 88 | +} // namespace pp_matmul | ||
| 89 | +} // namespace optiling | ||
| 90 | + | ||
| @@ -0,0 +1,23 @@ | |||
| 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 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| @@ -0,0 +1,112 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +template <uint32_t ALIGN, typename T = uint32_t> | ||
| 25 | +inline __aicore__ T RoundUp(const T val) | ||
| 26 | +{ | ||
| 27 | + static_assert(ALIGN != 0, "align must not be zero"); | ||
| 28 | + static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type"); | ||
| 29 | + T align = ALIGN; | ||
| 30 | + if (val + align - 1 < val) { | ||
| 31 | + return val; | ||
| 32 | + } | ||
| 33 | + return (val + align - 1) / align * align; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +template <typename T> | ||
| 37 | +inline __aicore__ T RoundUp(const T val, const T align) | ||
| 38 | +{ | ||
| 39 | + static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type"); | ||
| 40 | + if (align == 0 || val + align - 1 < val) { | ||
| 41 | + return val; | ||
| 42 | + } | ||
| 43 | + return (val + align - 1) / align * align; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +template <uint32_t DIVISOR, typename T = uint32_t> | ||
| 47 | +inline __aicore__ T CeilDiv(const T dividend) | ||
| 48 | +{ | ||
| 49 | + static_assert(DIVISOR != 0, "align must not be zero"); | ||
| 50 | + static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type"); | ||
| 51 | + T divisor = DIVISOR; | ||
| 52 | + if (dividend + divisor - 1 < dividend) { | ||
| 53 | + return dividend; | ||
| 54 | + } | ||
| 55 | + return (dividend + divisor - 1) / divisor; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +template <typename T> | ||
| 59 | +constexpr T T_MAX = std::numeric_limits<T>::max(); | ||
| 60 | + | ||
| 61 | +template <typename T> | ||
| 62 | +inline __aicore__ T CeilDiv(const T dividend, const T divisor) | ||
| 63 | +{ | ||
| 64 | + static_assert(std::is_arithmetic<T>::value, "T must be an arithmetic type"); | ||
| 65 | + if (divisor == 0 || dividend + divisor - 1 < dividend) { | ||
| 66 | + return T_MAX<T>; | ||
| 67 | + } | ||
| 68 | + return (dividend + divisor - 1) / divisor; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +template <typename T> | ||
| 72 | +__aicore__ inline T Min(const T lhs, const T rhs) | ||
| 73 | +{ | ||
| 74 | + return lhs < rhs ? lhs : rhs; | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint32_t BlockSize() | ||
| 78 | +{ | ||
| 79 | + return 32 / sizeof(Dtype); | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint32_t MatrixSize() | ||
| 83 | +{ | ||
| 84 | + return 512 / sizeof(Dtype); | ||
| 85 | +} | ||
| 86 | + | ||
| 87 | +template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t BlockSizeRoundUp(uint64_t num) | ||
| 88 | +{ | ||
| 89 | + return (num + BlockSize<Dtype>() - 1) / BlockSize<Dtype>() * BlockSize<Dtype>(); | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t NumBlocksRoundUp(uint64_t num) | ||
| 93 | +{ | ||
| 94 | + return (num + BlockSize<Dtype>() - 1) / BlockSize<Dtype>(); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t MatrixSizeRoundUp(uint64_t num) | ||
| 98 | +{ | ||
| 99 | + return (num + MatrixSize<Dtype>() - 1) / MatrixSize<Dtype>() * MatrixSize<Dtype>(); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t NumMatrixsRoundUp(uint64_t num) | ||
| 103 | +{ | ||
| 104 | + return (num + MatrixSize<Dtype>() - 1) / MatrixSize<Dtype>(); | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +template <typename Dtype> __aicore__ __attribute__((always_inline)) inline uint64_t L0HalfSize() | ||
| 108 | +{ | ||
| 109 | + return 32 * 1024 / sizeof(Dtype); | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | + | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | +enum class ArchType { ASCEND_V220, ASCEND_V200, ASCEND_M200 }; | ||
| 14 | + | ||
| 15 | +template <ArchType ArchTag> | ||
| 16 | +struct HardwareInfo { | ||
| 17 | + static uint32_t const l2BW = 5; | ||
| 18 | + static uint32_t const hbmBW = 1; | ||
| 19 | + static uint32_t const supportMix = 0; | ||
| 20 | + static uint32_t const l1Size = 512 * 1024; | ||
| 21 | + static uint32_t const l0ASize = 64 * 1024; | ||
| 22 | + static uint32_t const l0BSize = 64 * 1024; | ||
| 23 | + static uint32_t const l0CSize = 128 * 1024; | ||
| 24 | + static uint32_t const l2Size = 192 * 1024 * 1024; | ||
| 25 | + static uint32_t const biasSize = 1024; | ||
| 26 | + static uint32_t const fixBufSize = 7 * 1024; | ||
| 27 | + static uint32_t const ubSize = 192 * 1024; | ||
| 28 | + static uint32_t const fractalSize = 512; | ||
| 29 | + static uint32_t const l1l0BlockSize = 32; | ||
| 30 | + static uint32_t const btBlockSize = 64; | ||
| 31 | + static uint32_t const fbBlockSize = 128; | ||
| 32 | +}; | ||
| 33 | + | ||
| 34 | + | ||
| @@ -0,0 +1,116 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +///////////////////////////////////////////////////// | ||
| 20 | +// gm_to_l1 | ||
| 21 | +///////////////////////////////////////////////////// | ||
| 22 | +template <ArchType ArchTag, typename DataType, DataFormat FormatInGM, DataFormat FormatInL1> | ||
| 23 | +struct gm_to_l1 { | ||
| 24 | + __aicore__ gm_to_l1(AscendC::LocalTensor<DataType> l1Tensor, | ||
| 25 | + AscendC::GlobalTensor<DataType> gmTensor, | ||
| 26 | + uint32_t nTileActual, | ||
| 27 | + uint32_t nTileCeil, | ||
| 28 | + uint32_t nVal, | ||
| 29 | + uint32_t dTileActual, | ||
| 30 | + uint32_t dTileCeil, | ||
| 31 | + uint32_t dVal) {}; | ||
| 32 | +}; | ||
| 33 | + | ||
| 34 | +///////////////////////////////////////////////////// | ||
| 35 | +// l1_to_l0_a | ||
| 36 | +///////////////////////////////////////////////////// | ||
| 37 | +template <ArchType ArchTag, typename DataType, bool IsTransPose, DataFormat DFmtIn, DataFormat DFmtOut> | ||
| 38 | +struct l1_to_l0_a { | ||
| 39 | + __aicore__ l1_to_l0_a(AscendC::LocalTensor<DataType> l0Tensor, | ||
| 40 | + AscendC::LocalTensor<DataType> l1Tensor, | ||
| 41 | + uint32_t mTileCeil, | ||
| 42 | + uint32_t kPartCeil, | ||
| 43 | + uint32_t mSrcStride, | ||
| 44 | + uint32_t kSrcStride, | ||
| 45 | + uint32_t mDstStride, | ||
| 46 | + uint32_t kDstStride) {}; | ||
| 47 | +}; | ||
| 48 | + | ||
| 49 | +///////////////////////////////////////////////////// | ||
| 50 | +// l1_to_l0_b | ||
| 51 | +///////////////////////////////////////////////////// | ||
| 52 | +template <ArchType ArchTag, typename DataType, bool IsTransPose, DataFormat DFmtIn, DataFormat DFmtOut> | ||
| 53 | +struct l1_to_l0_b { | ||
| 54 | + __aicore__ l1_to_l0_b(AscendC::LocalTensor<DataType> l0Tensor, | ||
| 55 | + AscendC::LocalTensor<DataType> l1Tensor, | ||
| 56 | + uint32_t nTileCeil, | ||
| 57 | + uint32_t kPartCeil, | ||
| 58 | + uint32_t nSrcStride, | ||
| 59 | + uint32_t kSrcStride, | ||
| 60 | + uint32_t nDstStride, | ||
| 61 | + uint32_t kDstStride) {}; | ||
| 62 | +}; | ||
| 63 | + | ||
| 64 | +///////////////////////////////////////////////////// | ||
| 65 | +// l0c_to_gm | ||
| 66 | +///////////////////////////////////////////////////// | ||
| 67 | +template <ArchType ArchTag, DataFormat OutFormatType, typename OutDataType, typename L0CDataType> | ||
| 68 | +struct l0c_to_gm { | ||
| 69 | + __aicore__ l0c_to_gm(AscendC::GlobalTensor<OutDataType> gmTensor, | ||
| 70 | + AscendC::LocalTensor<L0CDataType> l0cTensor, | ||
| 71 | + uint32_t mTileActual, | ||
| 72 | + uint32_t nTileActual, | ||
| 73 | + uint32_t mTileCeil, | ||
| 74 | + uint32_t nActual, | ||
| 75 | + uint8_t unitFlag = 0) {}; | ||
| 76 | +}; | ||
| 77 | + | ||
| 78 | +///////////////////////////////////////////////////// | ||
| 79 | +// l0c_to_l1 | ||
| 80 | +///////////////////////////////////////////////////// | ||
| 81 | +template <ArchType ArchTag, DataFormat LayoutOut, typename ElementOut, typename ElementIn> | ||
| 82 | +struct l0c_to_l1 { | ||
| 83 | + __aicore__ l0c_to_l1(AscendC::LocalTensor<ElementOut> l1Tensor, | ||
| 84 | + AscendC::LocalTensor<ElementIn> l0cTensor, | ||
| 85 | + AscendC::LocalTensor<uint64_t> deqTensor, | ||
| 86 | + uint32_t mTileActual, | ||
| 87 | + uint32_t nTileActual, | ||
| 88 | + uint32_t mTileCeil, | ||
| 89 | + uint32_t nActual) {}; | ||
| 90 | +}; | ||
| 91 | + | ||
| 92 | +template <ArchType ArchTag, typename DataType> | ||
| 93 | +struct l1_to_bt { | ||
| 94 | + __aicore__ l1_to_bt(uint64_t dst, | ||
| 95 | + const AscendC::LocalTensor<DataType> &src, | ||
| 96 | + uint16_t convControl, | ||
| 97 | + uint16_t nBurst, | ||
| 98 | + uint16_t lenBurst, | ||
| 99 | + uint16_t srcGap, | ||
| 100 | + uint16_t dstGap) {}; | ||
| 101 | +}; | ||
| 102 | + | ||
| 103 | +template <ArchType ArchTag, typename DataType> | ||
| 104 | +struct l1_to_fb { | ||
| 105 | + __aicore__ l1_to_fb(AscendC::LocalTensor<DataType> &dst, | ||
| 106 | + AscendC::LocalTensor<DataType> &src, | ||
| 107 | + uint16_t burstNum, | ||
| 108 | + uint16_t burstLen, | ||
| 109 | + uint16_t srcGap, | ||
| 110 | + uint16_t dstGap) {}; | ||
| 111 | +}; | ||
| 112 | + | ||
| 113 | + | ||
| 114 | + | ||
| 115 | + | ||
| 116 | + | ||
| @@ -0,0 +1,16 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +enum class DataFormat { ND = 0, NZ, ZN, ZZ, NN, VECTOR }; | ||
| 15 | + | ||
| 16 | + | ||
| @@ -0,0 +1,82 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +enum class BufferType { ASCEND_UB, ASCEND_CB, ASCEND_L0A, ASCEND_L0B, ASCEND_L0C, ASCEND_MAX }; | ||
| 18 | + | ||
| 19 | +template <BufferType BufferType_> | ||
| 20 | +__aicore__ constexpr AscendC::TPosition GetPosition() | ||
| 21 | +{ | ||
| 22 | + if constexpr (BufferType_ == BufferType::ASCEND_UB) { | ||
| 23 | + return AscendC::TPosition::VECIN; | ||
| 24 | + } else if constexpr (BufferType_ == BufferType::ASCEND_CB) { | ||
| 25 | + return AscendC::TPosition::A1; | ||
| 26 | + } else if constexpr (BufferType_ == BufferType::ASCEND_L0A) { | ||
| 27 | + return AscendC::TPosition::A2; | ||
| 28 | + } else if constexpr (BufferType_ == BufferType::ASCEND_L0B) { | ||
| 29 | + return AscendC::TPosition::B2; | ||
| 30 | + } else if constexpr (BufferType_ == BufferType::ASCEND_L0C) { | ||
| 31 | + return AscendC::TPosition::CO1; | ||
| 32 | + } | ||
| 33 | + return AscendC::TPosition::GM; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +template <ArchType ArchTag> | ||
| 37 | +struct AsdopsBuffer { | ||
| 38 | +public: | ||
| 39 | + __aicore__ AsdopsBuffer() | ||
| 40 | + { | ||
| 41 | + constexpr uint32_t bufferSize[(uint32_t)BufferType::ASCEND_MAX] = {HardwareInfo<ArchTag>::ubSize, | ||
| 42 | + HardwareInfo<ArchTag>::l1Size, | ||
| 43 | + HardwareInfo<ArchTag>::l0ASize, | ||
| 44 | + HardwareInfo<ArchTag>::l0BSize, | ||
| 45 | + HardwareInfo<ArchTag>::l0CSize}; | ||
| 46 | + | ||
| 47 | + tensor[(uint32_t)BufferType::ASCEND_UB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_UB]); | ||
| 48 | + tensor[(uint32_t)BufferType::ASCEND_UB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::VECIN); | ||
| 49 | + | ||
| 50 | + tensor[(uint32_t)BufferType::ASCEND_CB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_CB]); | ||
| 51 | + tensor[(uint32_t)BufferType::ASCEND_CB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A1); | ||
| 52 | + tensor[(uint32_t)BufferType::ASCEND_L0A].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0A]); | ||
| 53 | + tensor[(uint32_t)BufferType::ASCEND_L0A].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A2); | ||
| 54 | + tensor[(uint32_t)BufferType::ASCEND_L0B].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0B]); | ||
| 55 | + tensor[(uint32_t)BufferType::ASCEND_L0B].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::B2); | ||
| 56 | + tensor[(uint32_t)BufferType::ASCEND_L0C].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0C]); | ||
| 57 | + tensor[(uint32_t)BufferType::ASCEND_L0C].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::CO1); | ||
| 58 | + | ||
| 59 | + tensor[(uint32_t)BufferType::ASCEND_UB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_UB]); | ||
| 60 | + tensor[(uint32_t)BufferType::ASCEND_UB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::VECIN); | ||
| 61 | + tensor[(uint32_t)BufferType::ASCEND_CB].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_CB]); | ||
| 62 | + tensor[(uint32_t)BufferType::ASCEND_CB].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A1); | ||
| 63 | + tensor[(uint32_t)BufferType::ASCEND_L0A].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0A]); | ||
| 64 | + tensor[(uint32_t)BufferType::ASCEND_L0A].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::A2); | ||
| 65 | + tensor[(uint32_t)BufferType::ASCEND_L0B].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0B]); | ||
| 66 | + tensor[(uint32_t)BufferType::ASCEND_L0B].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::B2); | ||
| 67 | + tensor[(uint32_t)BufferType::ASCEND_L0C].InitBuffer(0, bufferSize[(uint32_t)BufferType::ASCEND_L0C]); | ||
| 68 | + tensor[(uint32_t)BufferType::ASCEND_L0C].address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::CO1); | ||
| 69 | + | ||
| 70 | + }; | ||
| 71 | + | ||
| 72 | + template <BufferType BufferType_, typename DstDataType = half> | ||
| 73 | + __aicore__ AscendC::LocalTensor<DstDataType> GetBuffer(const uint32_t offset) const | ||
| 74 | + { | ||
| 75 | + return tensor[(uint32_t)BufferType_][offset].template ReinterpretCast<DstDataType>(); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | +public: | ||
| 79 | + AscendC::LocalTensor<uint8_t> tensor[(uint32_t)BufferType::ASCEND_MAX]; | ||
| 80 | +}; | ||
| 81 | + | ||
| 82 | + | ||
| @@ -0,0 +1,87 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +template <ArchType ArchTag, typename ElementA, typename ElementB, typename AccDTypeC, bool IsTransposeA> | ||
| 17 | +struct mmad { | ||
| 18 | + __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor, | ||
| 19 | + AscendC::LocalTensor<ElementA> l0aTensor, | ||
| 20 | + AscendC::LocalTensor<ElementB> l0bTensor, | ||
| 21 | + uint32_t mTileActual, | ||
| 22 | + uint32_t nTileActual, | ||
| 23 | + uint32_t kPartActual, | ||
| 24 | + bool initC, | ||
| 25 | + uint8_t unitFlag = 0) {}; | ||
| 26 | + | ||
| 27 | + __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor, | ||
| 28 | + AscendC::LocalTensor<ElementA> l0aTensor, | ||
| 29 | + AscendC::LocalTensor<ElementB> l0bTensor, | ||
| 30 | + uint64_t biasBt, | ||
| 31 | + uint32_t mTileActual, | ||
| 32 | + uint32_t nTileActual, | ||
| 33 | + uint32_t kPartActual, | ||
| 34 | + bool initC, | ||
| 35 | + uint8_t unitFlag = 0) {}; | ||
| 36 | +}; | ||
| 37 | + | ||
| 38 | +// Partial specialization for V220, int8_t, not_vector_A, not TransposeA | ||
| 39 | +template <ArchType ArchTag, typename AccDTypeC, typename ElementA, typename ElementB> | ||
| 40 | +struct mmad<ArchTag, ElementA, ElementB, AccDTypeC, false> { | ||
| 41 | + __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor, | ||
| 42 | + AscendC::LocalTensor<ElementA> l0aTensor, | ||
| 43 | + AscendC::LocalTensor<ElementB> l0bTensor, | ||
| 44 | + uint32_t mTileActual, | ||
| 45 | + uint32_t nTileActual, | ||
| 46 | + uint32_t kPartActual, | ||
| 47 | + bool initC, | ||
| 48 | + uint8_t unitFlag = 0) | ||
| 49 | + { | ||
| 50 | + AscendC::Mmad(l0cTensor, // C | ||
| 51 | + l0aTensor, // A | ||
| 52 | + l0bTensor, // B | ||
| 53 | + AscendC::MmadParams(mTileActual, // m | ||
| 54 | + nTileActual, // n | ||
| 55 | + kPartActual, // k | ||
| 56 | + unitFlag, // unitFlag | ||
| 57 | + false, // cmatrixSource | ||
| 58 | + initC)); // cmatrixInitVal | ||
| 59 | + }; | ||
| 60 | + | ||
| 61 | + __aicore__ mmad(AscendC::LocalTensor<AccDTypeC> l0cTensor, | ||
| 62 | + AscendC::LocalTensor<ElementA> l0aTensor, | ||
| 63 | + AscendC::LocalTensor<ElementB> l0bTensor, | ||
| 64 | + uint64_t biasBt, | ||
| 65 | + uint32_t mTileActual, | ||
| 66 | + uint32_t nTileActual, | ||
| 67 | + uint32_t kPartActual, | ||
| 68 | + bool initC, | ||
| 69 | + uint8_t unitFlag = 0) | ||
| 70 | + { | ||
| 71 | + AscendC::LocalTensor<AccDTypeC> biasTensor; | ||
| 72 | + biasTensor.InitBuffer(biasBt, nTileActual); | ||
| 73 | + biasTensor.address_.logicPos = static_cast<uint8_t>(AscendC::TPosition::C2); | ||
| 74 | + AscendC::Mmad(l0cTensor, // C | ||
| 75 | + l0aTensor, // A | ||
| 76 | + l0bTensor, // B | ||
| 77 | + biasTensor, // bt | ||
| 78 | + AscendC::MmadParams(mTileActual, // m | ||
| 79 | + nTileActual, // n | ||
| 80 | + kPartActual, // k | ||
| 81 | + unitFlag, // unitFlag | ||
| 82 | + true, // cmatrixSource | ||
| 83 | + false)); // cmatrixInitVal | ||
| 84 | + }; | ||
| 85 | +}; | ||
| 86 | + | ||
| 87 | + | ||


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