已合并
Add AdaptiveMaxPool2d #1670
huohuo_wangyan创建于 2月9日
Add AdaptiveMaxPool2d #1670
已合并
共 24 个文件变更+3050-337
| @@ -0,0 +1,11 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify. | ||
| 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 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 | +add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE adaptive_max_pool2d ACLNNTYPE aclnn_exclude DEPENDENCIES max_pool3d_with_argmax_v2 adaptive_max_pool3d) | ||
| @@ -0,0 +1,107 @@ | |||
| 1 | +# AdaptiveMaxPool2d | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +| 产品 | 是否支持 | | ||
| 6 | +| ---- | :----:| | ||
| 7 | +|Ascend 950PR/Ascend 950DT|√| | ||
| 8 | +|Atlas A3 训练系列产品/Atlas A3 推理系列产品|x| | ||
| 9 | +|Atlas A2 训练系列产品/Atlas A2 推理系列产品|x| | ||
| 10 | +|Atlas 200I/500 A2推理产品|×| | ||
| 11 | +|Atlas 推理系列产品|×| | ||
| 12 | +|Atlas 训练系列产品|×| | ||
| 13 | +|Kirin X90 处理器系列产品|x| | ||
| 14 | +|Kirin 9030 处理器系列产品|x| | ||
| 15 | + | ||
| 16 | +## 功能说明 | ||
| 17 | + | ||
| 18 | +- 算子功能:根据输入的output_size计算每次kernel的大小,对输入x进行3维最大池化操作,输出池化后的值y和索引indices。 | ||
| 19 | + | ||
| 20 | +- 计算公式: | ||
| 21 | + y tensor中对于DHW轴上每个位置为$(l,m,n)$的元素来说,其计算公式为: | ||
| 22 | + $$ | ||
| 23 | + H^{m}_{left} = floor((m*H)/H_o) | ||
| 24 | + $$ | ||
| 25 | + | ||
| 26 | + $$ | ||
| 27 | + H^{m}_{right} = ceil(((m+1)*H)/H_o) | ||
| 28 | + $$ | ||
| 29 | + | ||
| 30 | + $$ | ||
| 31 | + W^{n}_{left} = floor((n*W)/W_o) | ||
| 32 | + $$ | ||
| 33 | + | ||
| 34 | + $$ | ||
| 35 | + W^{n}_{right} = ceil(((n+1)*W)/W_o) | ||
| 36 | + $$ | ||
| 37 | + | ||
| 38 | + $$ | ||
| 39 | + y(N,C,m,n)=\underset {j\in [H^m_{left},H^m_{right}], k \in [W^n_{left},W^n_{right}] }{max} input(N,C,j,k) | ||
| 40 | + $$ | ||
| 41 | + | ||
| 42 | + $$ | ||
| 43 | + indices(N,C,m,n)=\underset {j\in [H^m_{left},H^m_{right}], k \in [W^n_{left},W^n_{right}] }{argmax} input(N,C,j,k) | ||
| 44 | + $$ | ||
| 45 | + | ||
| 46 | +## 参数说明 | ||
| 47 | + | ||
| 48 | +<table style="undefined;table-layout: fixed; width: 1250px"><colgroup> | ||
| 49 | + <col style="width: 150px"> | ||
| 50 | + <col style="width: 150px"> | ||
| 51 | + <col style="width: 500px"> | ||
| 52 | + <col style="width: 250px"> | ||
| 53 | + <col style="width: 200px"> | ||
| 54 | + </colgroup> | ||
| 55 | + <thead> | ||
| 56 | + <tr> | ||
| 57 | + <th>参数名</th> | ||
| 58 | + <th>输入/输出/属性</th> | ||
| 59 | + <th>描述</th> | ||
| 60 | + <th>数据类型</th> | ||
| 61 | + <th>数据格式</th> | ||
| 62 | + </tr></thead> | ||
| 63 | + <tbody> | ||
| 64 | + <tr> | ||
| 65 | + <td>x</td> | ||
| 66 | + <td>输入</td> | ||
| 67 | + <td>待进行AdaptiveMaxPool2d计算的入参。H轴W轴2个维度的乘积不能大于int32的最大表示。数据类型与出参`y`的保持一致。</td> | ||
| 68 | + <td>FLOAT、FLOAT16、BFLOAT16</td> | ||
| 69 | + <td>ND</td> | ||
| 70 | + </tr> | ||
| 71 | + <tr> | ||
| 72 | + <td>output_size</td> | ||
| 73 | + <td>属性</td> | ||
| 74 | + <td>表示输出结果在H,W维度上的空间大小。数据类型与入参`x`的保持一致。</td> | ||
| 75 | + <td>INT64</td> | ||
| 76 | + <td>-</td> | ||
| 77 | + </tr> | ||
| 78 | + <tr> | ||
| 79 | + <td>y</td> | ||
| 80 | + <td>输出</td> | ||
| 81 | + <td>待进行AdaptiveMaxPool2d计算的出参。shape与出参`indices`的保持一致,数据类型与入参`x`的保持一致。</td> | ||
| 82 | + <td>FLOAT、FLOAT16、BFLOAT16</td> | ||
| 83 | + <td>ND</td> | ||
| 84 | + </tr> | ||
| 85 | + <tr> | ||
| 86 | + <td>indices</td> | ||
| 87 | + <td>输出</td> | ||
| 88 | + <td>表示`y`元素在输入`x`中的索引位置。shape与出参`y`的保持一致。</td> | ||
| 89 | + <td>INT32</td> | ||
| 90 | + <td>ND</td> | ||
| 91 | + </tr> | ||
| 92 | + </tbody></table> | ||
| 93 | + | ||
| 94 | + | ||
| 95 | +## 约束说明 | ||
| 96 | +Shape描述: | ||
| 97 | + - self.shape = (N, C, Hin, Win) | ||
| 98 | + - outputSize = [Hout, Wout] | ||
| 99 | + - outputOut.shape = (N, C, Hout, Wout) | ||
| 100 | + - indicesOut.shape = (N, C, Hout, Wout) | ||
| 101 | + | ||
| 102 | + | ||
| 103 | +## 调用说明 | ||
| 104 | + | ||
| 105 | +| 调用方式 | 样例代码 | 说明 | | ||
| 106 | +| ---------------- | --------------------------- | --------------------------------------------------- | | ||
| 107 | +| aclnn接口 | [test_aclnn_adaptive_max_pool2d.cpp](examples/test_aclnn_adaptive_max_pool2d.cpp) | 通过[aclnnAdaptiveMaxPool2d](docs/aclnnAdaptiveMaxPool2d.md)接口方式调用AdaptiveMaxPool2d算子。 | | ||
| @@ -0,0 +1,396 @@ | |||
| 1 | +`# aclnnAdaptiveMaxPool2d | ||
| 2 | + | ||
| 3 | +[📄 查看源码](https://gitcode.com/cann/ops-nn/tree/master/pooling/adaptive_max_pool3d) | ||
| 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 | +根据输入的outputSize计算每次kernel的大小,对输入self进行2维最大池化操作,输出池化后的值out和索引indices。aclnnAdaptiveMaxPool2d与aclnnMaxPool2d的区别在于,只需指定outputSize大小,并按outputSize的大小来划分pooling区域。 | ||
| 19 | + | ||
| 20 | +## 函数原型 | ||
| 21 | +每个算子分为[两段式接口](../../../docs/zh/context/两段式接口.md),必须先调用“aclnnAdaptiveMaxPool2dGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnAdaptiveMaxPool2d”接口执行计算。 | ||
| 22 | + | ||
| 23 | +```Cpp | ||
| 24 | +aclnnStatus aclnnAdaptiveMaxPool2dGetWorkspaceSize( | ||
| 25 | + const aclTensor *self, | ||
| 26 | + const aclIntArray *outputSize, | ||
| 27 | + aclTensor *outputOut, | ||
| 28 | + aclTensor *indicesOut, | ||
| 29 | + uint64_t *workspaceSize, | ||
| 30 | + aclOpExecutor **executor) | ||
| 31 | +``` | ||
| 32 | +```Cpp | ||
| 33 | +aclnnStatus aclnnAdaptiveMaxPool2d( | ||
| 34 | + void *workspace, | ||
| 35 | + uint64_t workspaceSize, | ||
| 36 | + aclOpExecutor *executor, | ||
| 37 | + aclrtStream stream) | ||
| 38 | +``` | ||
| 39 | + | ||
| 40 | +## aclnnAdaptiveMaxPool2dGetWorkspaceSize | ||
| 41 | + | ||
| 42 | +- **参数说明:** | ||
| 43 | + | ||
| 44 | + <table style="undefined;table-layout: fixed; width: 1478px"><colgroup> | ||
| 45 | + <col style="width: 149px"> | ||
| 46 | + <col style="width: 121px"> | ||
| 47 | + <col style="width: 264px"> | ||
| 48 | + <col style="width: 253px"> | ||
| 49 | + <col style="width: 262px"> | ||
| 50 | + <col style="width: 148px"> | ||
| 51 | + <col style="width: 135px"> | ||
| 52 | + <col style="width: 146px"> | ||
| 53 | + </colgroup> | ||
| 54 | + <thead> | ||
| 55 | + <tr> | ||
| 56 | + <th>参数名</th> | ||
| 57 | + <th>输入/输出</th> | ||
| 58 | + <th>描述</th> | ||
| 59 | + <th>使用说明</th> | ||
| 60 | + <th>数据类型</th> | ||
| 61 | + <th>数据格式</th> | ||
| 62 | + <th>维度(shape)</th> | ||
| 63 | + <th>非连续Tensor</th> | ||
| 64 | + </tr></thead> | ||
| 65 | + <tbody> | ||
| 66 | + <tr> | ||
| 67 | + <td>self</td> | ||
| 68 | + <td>输入</td> | ||
| 69 | + <td>待计算张量。</td> | ||
| 70 | + <td>与outputOut的数据类型一致。</td> | ||
| 71 | + <td>FLOAT32、FLOAT16、BFLOAT16、DOUBLE</td> | ||
| 72 | + <td>NCHW、NCL、NHWC</td> | ||
| 73 | + <td>3-4</td> | ||
| 74 | + <td>√</td> | ||
| 75 | + </tr> | ||
| 76 | + <tr> | ||
| 77 | + <td>outputSize</td> | ||
| 78 | + <td>输入</td> | ||
| 79 | + <td>表示输出结果在H和W维度上的空间大小。</td> | ||
| 80 | + <td>-</td> | ||
| 81 | + <td>-</td> | ||
| 82 | + <td>-</td> | ||
| 83 | + <td>-</td> | ||
| 84 | + <td>-</td> | ||
| 85 | + </tr> | ||
| 86 | + <tr> | ||
| 87 | + <td>outputOut</td> | ||
| 88 | + <td>输出</td> | ||
| 89 | + <td>池化后的结果。</td> | ||
| 90 | + <td>与self的数据类型一致,shape与indicesOut一致。</td> | ||
| 91 | + <td>FLOAT32、FLOAT16、BFLOAT16、DOUBLE</td> | ||
| 92 | + <td>NCHW、NCL、NHWC</td> | ||
| 93 | + <td>3-4</td> | ||
| 94 | + <td>√</td> | ||
| 95 | + </tr> | ||
| 96 | + <tr> | ||
| 97 | + <td>indicesOut</td> | ||
| 98 | + <td>输出</td> | ||
| 99 | + <td>outputOut元素在输入self中的索引位置。</td> | ||
| 100 | + <td>shape与outputOut一致。</td> | ||
| 101 | + <td>INT64</td> | ||
| 102 | + <td>NCHW、NCL、NHWC</td> | ||
| 103 | + <td>3-4</td> | ||
| 104 | + <td>√</td> | ||
| 105 | + </tr> | ||
| 106 | + <tr> | ||
| 107 | + <td>workspaceSize</td> | ||
| 108 | + <td>输出</td> | ||
| 109 | + <td>返回需要在Device侧申请的workspace大小。</td> | ||
| 110 | + <td>-</td> | ||
| 111 | + <td>-</td> | ||
| 112 | + <td>-</td> | ||
| 113 | + <td>-</td> | ||
| 114 | + <td>-</td> | ||
| 115 | + </tr> | ||
| 116 | + <tr> | ||
| 117 | + <td>executor</td> | ||
| 118 | + <td>输出</td> | ||
| 119 | + <td>返回op执行器,包含了算子计算流程。</td> | ||
| 120 | + <td>-</td> | ||
| 121 | + <td>-</td> | ||
| 122 | + <td>-</td> | ||
| 123 | + <td>-</td> | ||
| 124 | + <td>-</td> | ||
| 125 | + </tr> | ||
| 126 | + </tbody></table> | ||
| 127 | + | ||
| 128 | +- **返回值:** | ||
| 129 | + | ||
| 130 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../docs/zh/context/aclnn返回码.md)。 | ||
| 131 | + | ||
| 132 | + 第一段接口完成入参校验,出现以下场景时报错: | ||
| 133 | + | ||
| 134 | + <table style="undefined;table-layout: fixed; width: 1166px"><colgroup> | ||
| 135 | + <col style="width: 267px"> | ||
| 136 | + <col style="width: 124px"> | ||
| 137 | + <col style="width: 775px"> | ||
| 138 | + </colgroup> | ||
| 139 | + <thead> | ||
| 140 | + <tr> | ||
| 141 | + <th>返回码</th> | ||
| 142 | + <th>错误码</th> | ||
| 143 | + <th>描述</th> | ||
| 144 | + </tr></thead> | ||
| 145 | + <tbody> | ||
| 146 | + <tr> | ||
| 147 | + <td>ACLNN_ERR_PARAM_NULLPTR</td> | ||
| 148 | + <td>161001</td> | ||
| 149 | + <td>传入的self、outputSize、outputOut或indicesOut是空指针。</td> | ||
| 150 | + </tr> | ||
| 151 | + <tr> | ||
| 152 | + <td rowspan="10">ACLNN_ERR_PARAM_INVALID</td> | ||
| 153 | + <td rowspan="10">161002</td> | ||
| 154 | + <td>self的数据类型不在支持的范围之内。</td> | ||
| 155 | + </tr> | ||
| 156 | + <tr> | ||
| 157 | + <td>self和outputOut的数据类型不一致。</td> | ||
| 158 | + </tr> | ||
| 159 | + <tr> | ||
| 160 | + <td>indicesOut的数据类型不为int64。</td> | ||
| 161 | + </tr> | ||
| 162 | + <tr> | ||
| 163 | + <td>self的shape不是3维或者4维。</td> | ||
| 164 | + </tr> | ||
| 165 | + <tr> | ||
| 166 | + <td>self在非第一维度上的size小于1。</td> | ||
| 167 | + </tr> | ||
| 168 | + <tr> | ||
| 169 | + <td>outputOut和indicesOut的shape不一致。</td> | ||
| 170 | + </tr> | ||
| 171 | + <tr> | ||
| 172 | + <td>outputSize的size大小不等于2。</td> | ||
| 173 | + </tr> | ||
| 174 | + <tr> | ||
| 175 | + <td>outputSize中元素值小于等于0。</td> | ||
| 176 | + </tr> | ||
| 177 | + <tr> | ||
| 178 | + <td>outputOut的shape与实际输出shape不匹配。</td> | ||
| 179 | + </tr> | ||
| 180 | + <tr> | ||
| 181 | + <td>self的format不是NCHW/NHWC/NCL这三种format。</td> | ||
| 182 | + </tr> | ||
| 183 | + <tr> | ||
| 184 | + <td>ACLNN_ERR_INNER_NULLPTR</td> | ||
| 185 | + <td>561103</td> | ||
| 186 | + <td>API内部校验错误,通常由于输入数据或属性的规格不在支持的范围之内导致。</td> | ||
| 187 | + </tr> | ||
| 188 | + </tbody> | ||
| 189 | + </table> | ||
| 190 | + | ||
| 191 | +## aclnnAdaptiveMaxPool2d | ||
| 192 | + | ||
| 193 | +- **参数说明:** | ||
| 194 | + <table style="undefined;table-layout: fixed; width: 1166px"><colgroup> | ||
| 195 | + <col style="width: 173px"> | ||
| 196 | + <col style="width: 133px"> | ||
| 197 | + <col style="width: 860px"> | ||
| 198 | + </colgroup> | ||
| 199 | + <thead> | ||
| 200 | + <tr> | ||
| 201 | + <th>参数名</th> | ||
| 202 | + <th>输入/输出</th> | ||
| 203 | + <th>描述</th> | ||
| 204 | + </tr></thead> | ||
| 205 | + <tbody> | ||
| 206 | + <tr> | ||
| 207 | + <td>workspace</td> | ||
| 208 | + <td>输入</td> | ||
| 209 | + <td>在Device侧申请的workspace内存地址。</td> | ||
| 210 | + </tr> | ||
| 211 | + <tr> | ||
| 212 | + <td>workspaceSize</td> | ||
| 213 | + <td>输入</td> | ||
| 214 | + <td>在Device侧申请的workspace大小,由第一段接口aclnnAdaptiveMaxPool2dGetWorkspaceSize获取。</td> | ||
| 215 | + </tr> | ||
| 216 | + <tr> | ||
| 217 | + <td>executor</td> | ||
| 218 | + <td>输入</td> | ||
| 219 | + <td>op执行器,包含了算子计算流程。</td> | ||
| 220 | + </tr> | ||
| 221 | + <tr> | ||
| 222 | + <td>stream</td> | ||
| 223 | + <td>输入</td> | ||
| 224 | + <td>指定执行任务的Stream。</td> | ||
| 225 | + </tr> | ||
| 226 | + </tbody> | ||
| 227 | + </table> | ||
| 228 | +- **返回值:** | ||
| 229 | + | ||
| 230 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../docs/zh/context/aclnn返回码.md)。 | ||
| 231 | + | ||
| 232 | +## 约束说明 | ||
| 233 | +- 确定性计算: | ||
| 234 | + - aclnnAdaptiveMaxPool2d默认确定性实现。 | ||
| 235 | + | ||
| 236 | +- Shape描述: | ||
| 237 | + - self.shape = (N, C, Hin, Win) 或者 (C, Hin, Win) 或 (N, Hin, Win, C) | ||
| 238 | + - outputSize = [Hout, Wout] | ||
| 239 | + - outputOut.shape = (N, C, Hout, Wout) 或者 (C, Hout, Wout) 或 (N, Hout, Wout, C) | ||
| 240 | + - indicesOut.shape = (N, C, Hout, Wout) 或者 (C, Hout, Wout) 或 (N, Hout, Wout, C) | ||
| 241 | + | ||
| 242 | +## 调用示例 | ||
| 243 | +示例代码如下,仅供参考,具体编译和执行过程请参考[编译与运行样例](../../../docs/zh/context/编译与运行样例.md)。 | ||
| 244 | +```Cpp | ||
| 245 | +#include <iostream> | ||
| 246 | +#include <vector> | ||
| 247 | +#include "acl/acl.h" | ||
| 248 | +#include "aclnnop/aclnn_adaptive_max_pool2d.h" | ||
| 249 | + | ||
| 250 | +#define CHECK_RET(cond, return_expr) \ | ||
| 251 | + do { \ | ||
| 252 | + if (!(cond)) { \ | ||
| 253 | + return_expr; \ | ||
| 254 | + } \ | ||
| 255 | + } while (0) | ||
| 256 | + | ||
| 257 | +#define LOG_PRINT(message, ...) \ | ||
| 258 | + do { \ | ||
| 259 | + printf(message, ##__VA_ARGS__); \ | ||
| 260 | + } while (0) | ||
| 261 | + | ||
| 262 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 263 | + int64_t shapeSize = 1; | ||
| 264 | + for (auto i : shape) { | ||
| 265 | + shapeSize *= i; | ||
| 266 | + } | ||
| 267 | + return shapeSize; | ||
| 268 | +} | ||
| 269 | + | ||
| 270 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 271 | + // 固定写法,资源初始化 | ||
| 272 | + auto ret = aclInit(nullptr); | ||
| 273 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 274 | + ret = aclrtSetDevice(deviceId); | ||
| 275 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 276 | + ret = aclrtCreateStream(stream); | ||
| 277 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 278 | + return 0; | ||
| 279 | +} | ||
| 280 | + | ||
| 281 | +template <typename T> | ||
| 282 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 283 | + aclDataType dataType, aclTensor** tensor) { | ||
| 284 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 285 | + // 调用aclrtMalloc申请device侧内存 | ||
| 286 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 287 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 288 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 289 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 290 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 291 | + | ||
| 292 | + // 计算连续tensor的strides | ||
| 293 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 294 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 295 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 299 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_NCHW, | ||
| 300 | + shape.data(), shape.size(), *deviceAddr); | ||
| 301 | + return 0; | ||
| 302 | +} | ||
| 303 | + | ||
| 304 | +int main() { | ||
| 305 | + // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 306 | + // 根据自己的实际device填写deviceId | ||
| 307 | + int32_t deviceId = 0; | ||
| 308 | + aclrtStream stream; | ||
| 309 | + auto ret = Init(deviceId, &stream); | ||
| 310 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 311 | + | ||
| 312 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 313 | + std::vector<int64_t> selfShape = {1, 1, 4, 4}; | ||
| 314 | + std::vector<int64_t> outShape = {1, 1, 2, 2}; | ||
| 315 | + void* selfDeviceAddr = nullptr; | ||
| 316 | + void* outDeviceAddr = nullptr; | ||
| 317 | + void* indDeviceAddr = nullptr; | ||
| 318 | + aclTensor* self = nullptr; | ||
| 319 | + aclTensor* out = nullptr; | ||
| 320 | + aclTensor* indices = nullptr; | ||
| 321 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7, | ||
| 322 | + 8, 9, 10, 11, 12, 13, 14, 15}; | ||
| 323 | + std::vector<float> outHostData = {0, 0, 0, 0.0}; | ||
| 324 | + std::vector<int64_t> indicesHostData = {0, 0, 0, 0}; | ||
| 325 | + // 创建self aclTensor | ||
| 326 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 327 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 328 | + | ||
| 329 | + // 创建out aclTensor | ||
| 330 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 331 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 332 | + | ||
| 333 | + // 创建indices aclTensor | ||
| 334 | + ret = CreateAclTensor(indicesHostData, outShape, &indDeviceAddr, aclDataType::ACL_INT64, &indices); | ||
| 335 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 336 | + | ||
| 337 | + std::vector<int64_t> arraySize = {2, 2}; | ||
| 338 | + const aclIntArray *outputSize = aclCreateIntArray(arraySize.data(), arraySize.size()); | ||
| 339 | + CHECK_RET(outputSize != nullptr, return ACL_ERROR_INTERNAL_ERROR); | ||
| 340 | + | ||
| 341 | + // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 342 | + uint64_t workspaceSize = 0; | ||
| 343 | + aclOpExecutor* executor; | ||
| 344 | + // 调用aclnnAdaptiveMaxPool2d第一段接口 | ||
| 345 | + ret = aclnnAdaptiveMaxPool2dGetWorkspaceSize(self, outputSize, out, indices, &workspaceSize, &executor); | ||
| 346 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdaptiveMaxPool2dGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 347 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 348 | + void* workspaceAddr = nullptr; | ||
| 349 | + if (workspaceSize > 0) { | ||
| 350 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 351 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 352 | + } | ||
| 353 | + // 调用aclnnAdaptiveMaxPool2d第二段接口 | ||
| 354 | + ret = aclnnAdaptiveMaxPool2d(workspaceAddr, workspaceSize, executor, stream); | ||
| 355 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdaptiveMaxPool2d failed. ERROR: %d\n", ret); return ret); | ||
| 356 | + | ||
| 357 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 358 | + ret = aclrtSynchronizeStream(stream); | ||
| 359 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 360 | + | ||
| 361 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 362 | + auto size = GetShapeSize(outShape); | ||
| 363 | + std::vector<float> outData(size, 0); | ||
| 364 | + std::vector<int64_t> indicesData(size, 0); | ||
| 365 | + ret = aclrtMemcpy(outData.data(), outData.size() * sizeof(outData[0]), outDeviceAddr, | ||
| 366 | + size * sizeof(outData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 367 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 368 | + ret = aclrtMemcpy(indicesData.data(), indicesData.size() * sizeof(indicesData[0]), indDeviceAddr, | ||
| 369 | + size * sizeof(indicesData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 370 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 371 | + for (int64_t i = 0; i < size; i++) { | ||
| 372 | + LOG_PRINT("out[%ld] is: %f\n", i, outData[i]); | ||
| 373 | + } | ||
| 374 | + for (int64_t i = 0; i < size; i++) { | ||
| 375 | + LOG_PRINT("indices[%ld] is: %ld\n", i, indicesData[i]); | ||
| 376 | + } | ||
| 377 | + | ||
| 378 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 379 | + aclDestroyTensor(self); | ||
| 380 | + aclDestroyTensor(out); | ||
| 381 | + aclDestroyTensor(indices); | ||
| 382 | + aclDestroyIntArray(outputSize); | ||
| 383 | + | ||
| 384 | + // 7. 释放device 资源 | ||
| 385 | + aclrtFree(selfDeviceAddr); | ||
| 386 | + aclrtFree(outDeviceAddr); | ||
| 387 | + aclrtFree(indDeviceAddr); | ||
| 388 | + if (workspaceSize > 0) { | ||
| 389 | + aclrtFree(workspaceAddr); | ||
| 390 | + } | ||
| 391 | + aclrtDestroyStream(stream); | ||
| 392 | + aclrtResetDevice(deviceId); | ||
| 393 | + aclFinalize(); | ||
| 394 | + return 0; | ||
| 395 | +} | ||
| 396 | +```` | ||
Rpooling/adaptive_max_pool3d/examples/test_aclnn_adaptive_max_pool2d.cpp→pooling/adaptive_max_pool2d/examples/test_aclnn_adaptive_max_pool2d.cpp+161-161
| @@ -1,162 +1,162 @@ | |||
| 1 | -/** | 1 | +/** |
| 2 | - * Copyright (c) 2025 Huawei Technologies Co., Ltd. | 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. |
| 3 | - * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of |
| 4 | - * CANN Open Software License Agreement Version 2.0 (the "License"). | 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). |
| 5 | - * Please refer to the License for details. You may not use this file except in compliance with the License. | 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. |
| 6 | - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | 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. | 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. | 8 | + * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | - */ | 9 | + */ |
| 10 | - | 10 | + |
| 11 | -#include <iostream> | 11 | +#include <iostream> |
| 12 | -#include <vector> | 12 | +#include <vector> |
| 13 | -#include "acl/acl.h" | 13 | +#include "acl/acl.h" |
| 14 | -#include "aclnnop/aclnn_adaptive_max_pool2d.h" | 14 | +#include "aclnnop/aclnn_adaptive_max_pool2d.h" |
| 15 | - | 15 | + |
| 16 | -#define CHECK_RET(cond, return_expr) \ | 16 | +#define CHECK_RET(cond, return_expr) \ |
| 17 | - do { \ | 17 | + do { \ |
| 18 | - if (!(cond)) { \ | 18 | + if (!(cond)) { \ |
| 19 | - return_expr; \ | 19 | + return_expr; \ |
| 20 | - } \ | 20 | + } \ |
| 21 | - } while (0) | 21 | + } while (0) |
| 22 | - | 22 | + |
| 23 | -#define LOG_PRINT(message, ...) \ | 23 | +#define LOG_PRINT(message, ...) \ |
| 24 | - do { \ | 24 | + do { \ |
| 25 | - printf(message, ##__VA_ARGS__); \ | 25 | + printf(message, ##__VA_ARGS__); \ |
| 26 | - } while (0) | 26 | + } while (0) |
| 27 | - | 27 | + |
| 28 | -int64_t GetShapeSize(const std::vector<int64_t>& shape) { | 28 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { |
| 29 | - int64_t shapeSize = 1; | 29 | + int64_t shapeSize = 1; |
| 30 | - for (auto i : shape) { | 30 | + for (auto i : shape) { |
| 31 | - shapeSize *= i; | 31 | + shapeSize *= i; |
| 32 | - } | 32 | + } |
| 33 | - return shapeSize; | 33 | + return shapeSize; |
| 34 | -} | 34 | +} |
| 35 | - | 35 | + |
| 36 | -int Init(int32_t deviceId, aclrtStream* stream) { | 36 | +int Init(int32_t deviceId, aclrtStream* stream) { |
| 37 | - // 固定写法,资源初始化 | 37 | + // 固定写法,资源初始化 |
| 38 | - auto ret = aclInit(nullptr); | 38 | + auto ret = aclInit(nullptr); |
| 39 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 39 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 40 | - ret = aclrtSetDevice(deviceId); | 40 | + ret = aclrtSetDevice(deviceId); |
| 41 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 41 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 42 | - ret = aclrtCreateStream(stream); | 42 | + ret = aclrtCreateStream(stream); |
| 43 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 43 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 44 | - return 0; | 44 | + return 0; |
| 45 | -} | 45 | +} |
| 46 | - | 46 | + |
| 47 | -template <typename T> | 47 | +template <typename T> |
| 48 | -int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 48 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 49 | - aclDataType dataType, aclTensor** tensor) { | 49 | + aclDataType dataType, aclTensor** tensor) { |
| 50 | - auto size = GetShapeSize(shape) * sizeof(T); | 50 | + auto size = GetShapeSize(shape) * sizeof(T); |
| 51 | - // 调用aclrtMalloc申请device侧内存 | 51 | + // 调用aclrtMalloc申请device侧内存 |
| 52 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 52 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 53 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 53 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); |
| 54 | - // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 54 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 55 | - ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 55 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 56 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 56 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); |
| 57 | - | 57 | + |
| 58 | - // 计算连续tensor的strides | 58 | + // 计算连续tensor的strides |
| 59 | - std::vector<int64_t> strides(shape.size(), 1); | 59 | + std::vector<int64_t> strides(shape.size(), 1); |
| 60 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 60 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 61 | - strides[i] = shape[i + 1] * strides[i + 1]; | 61 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 62 | - } | 62 | + } |
| 63 | - | 63 | + |
| 64 | - // 调用aclCreateTensor接口创建aclTensor | 64 | + // 调用aclCreateTensor接口创建aclTensor |
| 65 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_NCHW, | 65 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_NCHW, |
| 66 | - shape.data(), shape.size(), *deviceAddr); | 66 | + shape.data(), shape.size(), *deviceAddr); |
| 67 | - return 0; | 67 | + return 0; |
| 68 | -} | 68 | +} |
| 69 | - | 69 | + |
| 70 | -int main() { | 70 | +int main() { |
| 71 | - // 1. (固定写法)device/stream初始化,参考acl API手册 | 71 | + // 1. (固定写法)device/stream初始化,参考acl API手册 |
| 72 | - // 根据自己的实际device填写deviceId | 72 | + // 根据自己的实际device填写deviceId |
| 73 | - int32_t deviceId = 0; | 73 | + int32_t deviceId = 0; |
| 74 | - aclrtStream stream; | 74 | + aclrtStream stream; |
| 75 | - auto ret = Init(deviceId, &stream); | 75 | + auto ret = Init(deviceId, &stream); |
| 76 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 76 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); |
| 77 | - | 77 | + |
| 78 | - // 2. 构造输入与输出,需要根据API的接口自定义构造 | 78 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 79 | - std::vector<int64_t> selfShape = {1, 2, 3, 4}; | 79 | + std::vector<int64_t> selfShape = {1, 2, 3, 4}; |
| 80 | - std::vector<int64_t> outShape = {1, 2, 2, 2}; | 80 | + std::vector<int64_t> outShape = {1, 2, 2, 2}; |
| 81 | - void* selfDeviceAddr = nullptr; | 81 | + void* selfDeviceAddr = nullptr; |
| 82 | - void* outDeviceAddr = nullptr; | 82 | + void* outDeviceAddr = nullptr; |
| 83 | - void* indDeviceAddr = nullptr; | 83 | + void* indDeviceAddr = nullptr; |
| 84 | - aclTensor* self = nullptr; | 84 | + aclTensor* self = nullptr; |
| 85 | - aclTensor* out = nullptr; | 85 | + aclTensor* out = nullptr; |
| 86 | - aclTensor* indices = nullptr; | 86 | + aclTensor* indices = nullptr; |
| 87 | - std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7, | 87 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7, |
| 88 | - 8, 9, 10, 11, 12, 13, 14, 15, | 88 | + 8, 9, 10, 11, 12, 13, 14, 15, |
| 89 | - 16, 17, 18, 19, 20, 21, 22, 23}; | 89 | + 16, 17, 18, 19, 20, 21, 22, 23}; |
| 90 | - std::vector<float> outHostData = {0, 0, 0, 0.0}; | 90 | + std::vector<float> outHostData = {0, 0, 0, 0.0}; |
| 91 | - std::vector<int64_t> indicesHostData = {0, 0, 0, 0}; | 91 | + std::vector<int64_t> indicesHostData = {0, 0, 0, 0}; |
| 92 | - // 创建self aclTensor | 92 | + // 创建self aclTensor |
| 93 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 93 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); |
| 94 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 94 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 95 | - | 95 | + |
| 96 | - // 创建out aclTensor | 96 | + // 创建out aclTensor |
| 97 | - ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | 97 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); |
| 98 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 98 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 99 | - | 99 | + |
| 100 | - // 创建indices aclTensor | 100 | + // 创建indices aclTensor |
| 101 | - ret = CreateAclTensor(indicesHostData, outShape, &indDeviceAddr, aclDataType::ACL_INT64, &indices); | 101 | + ret = CreateAclTensor(indicesHostData, outShape, &indDeviceAddr, aclDataType::ACL_INT64, &indices); |
| 102 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 102 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 103 | - | 103 | + |
| 104 | - std::vector<int64_t> arraySize = {2, 2}; | 104 | + std::vector<int64_t> arraySize = {2, 2}; |
| 105 | - const aclIntArray *outputSize = aclCreateIntArray(arraySize.data(), arraySize.size()); | 105 | + const aclIntArray *outputSize = aclCreateIntArray(arraySize.data(), arraySize.size()); |
| 106 | - CHECK_RET(outputSize != nullptr, return ACL_ERROR_INTERNAL_ERROR); | 106 | + CHECK_RET(outputSize != nullptr, return ACL_ERROR_INTERNAL_ERROR); |
| 107 | - | 107 | + |
| 108 | - // 3. 调用CANN算子库API,需要修改为具体的Api名称 | 108 | + // 3. 调用CANN算子库API,需要修改为具体的Api名称 |
| 109 | - uint64_t workspaceSize = 0; | 109 | + uint64_t workspaceSize = 0; |
| 110 | - aclOpExecutor* executor; | 110 | + aclOpExecutor* executor; |
| 111 | - // 调用aclnnAdaptiveMaxPool2d第一段接口 | 111 | + // 调用aclnnAdaptiveMaxPool2d第一段接口 |
| 112 | - ret = aclnnAdaptiveMaxPool2dGetWorkspaceSize(self, outputSize, out, indices, &workspaceSize, &executor); | 112 | + ret = aclnnAdaptiveMaxPool2dGetWorkspaceSize(self, outputSize, out, indices, &workspaceSize, &executor); |
| 113 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdaptiveMaxPool2dGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | 113 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdaptiveMaxPool2dGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); |
| 114 | - // 根据第一段接口计算出的workspaceSize申请device内存 | 114 | + // 根据第一段接口计算出的workspaceSize申请device内存 |
| 115 | - void* workspaceAddr = nullptr; | 115 | + void* workspaceAddr = nullptr; |
| 116 | - if (workspaceSize > 0) { | 116 | + if (workspaceSize > 0) { |
| 117 | - ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | 117 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); |
| 118 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | 118 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); |
| 119 | - } | 119 | + } |
| 120 | - // 调用aclnnAdaptiveMaxPool2d第二段接口 | 120 | + // 调用aclnnAdaptiveMaxPool2d第二段接口 |
| 121 | - ret = aclnnAdaptiveMaxPool2d(workspaceAddr, workspaceSize, executor, stream); | 121 | + ret = aclnnAdaptiveMaxPool2d(workspaceAddr, workspaceSize, executor, stream); |
| 122 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdaptiveMaxPool2d failed. ERROR: %d\n", ret); return ret); | 122 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdaptiveMaxPool2d failed. ERROR: %d\n", ret); return ret); |
| 123 | - | 123 | + |
| 124 | - // 4. (固定写法)同步等待任务执行结束 | 124 | + // 4. (固定写法)同步等待任务执行结束 |
| 125 | - ret = aclrtSynchronizeStream(stream); | 125 | + ret = aclrtSynchronizeStream(stream); |
| 126 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | 126 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); |
| 127 | - | 127 | + |
| 128 | - // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | 128 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 |
| 129 | - auto size = GetShapeSize(outShape); | 129 | + auto size = GetShapeSize(outShape); |
| 130 | - std::vector<float> outData(size, 0); | 130 | + std::vector<float> outData(size, 0); |
| 131 | - std::vector<int64_t> indicesData(size, 0); | 131 | + std::vector<int64_t> indicesData(size, 0); |
| 132 | - ret = aclrtMemcpy(outData.data(), outData.size() * sizeof(outData[0]), outDeviceAddr, | 132 | + ret = aclrtMemcpy(outData.data(), outData.size() * sizeof(outData[0]), outDeviceAddr, |
| 133 | - size * sizeof(outData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | 133 | + size * sizeof(outData[0]), ACL_MEMCPY_DEVICE_TO_HOST); |
| 134 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | 134 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); |
| 135 | - ret = aclrtMemcpy(indicesData.data(), indicesData.size() * sizeof(indicesData[0]), indDeviceAddr, | 135 | + ret = aclrtMemcpy(indicesData.data(), indicesData.size() * sizeof(indicesData[0]), indDeviceAddr, |
| 136 | - size * sizeof(indicesData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | 136 | + size * sizeof(indicesData[0]), ACL_MEMCPY_DEVICE_TO_HOST); |
| 137 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | 137 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); |
| 138 | - for (int64_t i = 0; i < size; i++) { | 138 | + for (int64_t i = 0; i < size; i++) { |
| 139 | - LOG_PRINT("out[%ld] is: %f\n", i, outData[i]); | 139 | + LOG_PRINT("out[%ld] is: %f\n", i, outData[i]); |
| 140 | - } | 140 | + } |
| 141 | - for (int64_t i = 0; i < size; i++) { | 141 | + for (int64_t i = 0; i < size; i++) { |
| 142 | - LOG_PRINT("indices[%ld] is: %ld\n", i, indicesData[i]); | 142 | + LOG_PRINT("indices[%ld] is: %ld\n", i, indicesData[i]); |
| 143 | - } | 143 | + } |
| 144 | - | 144 | + |
| 145 | - // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | 145 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 |
| 146 | - aclDestroyTensor(self); | 146 | + aclDestroyTensor(self); |
| 147 | - aclDestroyTensor(out); | 147 | + aclDestroyTensor(out); |
| 148 | - aclDestroyTensor(indices); | 148 | + aclDestroyTensor(indices); |
| 149 | - aclDestroyIntArray(outputSize); | 149 | + aclDestroyIntArray(outputSize); |
| 150 | - | 150 | + |
| 151 | - // 7. 释放device 资源 | 151 | + // 7. 释放device 资源 |
| 152 | - aclrtFree(selfDeviceAddr); | 152 | + aclrtFree(selfDeviceAddr); |
| 153 | - aclrtFree(outDeviceAddr); | 153 | + aclrtFree(outDeviceAddr); |
| 154 | - aclrtFree(indDeviceAddr); | 154 | + aclrtFree(indDeviceAddr); |
| 155 | - if (workspaceSize > 0) { | 155 | + if (workspaceSize > 0) { |
| 156 | - aclrtFree(workspaceAddr); | 156 | + aclrtFree(workspaceAddr); |
| 157 | - } | 157 | + } |
| 158 | - aclrtDestroyStream(stream); | 158 | + aclrtDestroyStream(stream); |
| 159 | - aclrtResetDevice(deviceId); | 159 | + aclrtResetDevice(deviceId); |
| 160 | - aclFinalize(); | 160 | + aclFinalize(); |
| 161 | - return 0; | 161 | + return 0; |
| 162 | } | 162 | } |
Rpooling/adaptive_max_pool3d/op_api/aclnn_adaptive_max_pool2d.cpp→pooling/adaptive_max_pool2d/op_api/aclnn_adaptive_max_pool2d.cpp+379-172
| @@ -9,18 +9,17 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | /*! | 11 | /*! |
| 12 | - * \file aclnn_mv.cpp | 12 | + * \file aclnn_adaptive_max_pool2d.cpp |
| 13 | * \brief | 13 | * \brief |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | - | ||
| 18 | 17 | ||
| 19 | 18 | ||
| 20 | 19 | ||
| 21 | 20 | ||
| 22 | - | ||
| 23 | 21 | ||
| 22 | + | ||
| 24 | 23 | ||
| 25 | 24 | ||
| 26 | 25 | ||
| @@ -71,8 +70,17 @@ static bool IsSelfDtypeDouble(const aclTensor* self) | |||
| 71 | 70 | ||
| 72 | static bool IsSocVersion910B() | 71 | static bool IsSocVersion910B() |
| 73 | { | 72 | { |
| 74 | - if (op::GetCurrentPlatformInfo().GetSocVersion() >= op::SocVersion::ASCEND910B && | 73 | + auto curArch = GetCurrentPlatformInfo().GetCurNpuArch(); |
| 75 | - op::GetCurrentPlatformInfo().GetSocVersion() <= op::SocVersion::ASCEND910E) { | 74 | + if (curArch == NpuArch::DAV_2201) { |
| 75 | + return true; | ||
| 76 | + } | ||
| 77 | + return false; | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +static bool IsSocVersion910D() | ||
| 81 | +{ | ||
| 82 | + auto curArch = GetCurrentPlatformInfo().GetCurNpuArch(); | ||
| 83 | + if (Ops::NN::AclnnUtil::IsRegbase(curArch)) { | ||
| 76 | return true; | 84 | return true; |
| 77 | } | 85 | } |
| 78 | return false; | 86 | return false; |
| @@ -80,8 +88,7 @@ static bool IsSocVersion910B() | |||
| 80 | 88 | ||
| 81 | static const std::initializer_list<DataType>& GetDtypeSupportList() | 89 | static const std::initializer_list<DataType>& GetDtypeSupportList() |
| 82 | { | 90 | { |
| 83 | - if (GetCurrentPlatformInfo().GetSocVersion() >= SocVersion::ASCEND910B && | 91 | + if (IsSocVersion910B() || IsSocVersion910D()) { |
| 84 | - GetCurrentPlatformInfo().GetSocVersion() <= SocVersion::ASCEND910E) { | ||
| 85 | return DTYPE_SUPPORT_LIST_ASCEND910B; | 92 | return DTYPE_SUPPORT_LIST_ASCEND910B; |
| 86 | } else { | 93 | } else { |
| 87 | return DTYPE_SUPPORT_LIST; | 94 | return DTYPE_SUPPORT_LIST; |
| @@ -187,12 +194,366 @@ static aclnnStatus CheckParams( | |||
| 187 | return ACLNN_SUCCESS; | 194 | return ACLNN_SUCCESS; |
| 188 | } | 195 | } |
| 189 | 196 | ||
| 197 | +static inline const aclTensor* View3Das5D(const aclTensor* input, aclOpExecutor* executor) | ||
| 198 | +{ | ||
| 199 | + // CHW -> unsqueeze -> reformat -> NCDHW | ||
| 200 | + // unsqueeze input into 4D | ||
| 201 | + const aclTensor* unsqueezedInput = l0op::UnsqueezeNd(input, 1, executor); | ||
| 202 | + CHECK_RET(unsqueezedInput != nullptr, nullptr); | ||
| 203 | + // unsqueeze input into 5D | ||
| 204 | + auto unsqueezedInput5D = l0op::UnsqueezeNd(unsqueezedInput, static_cast<int64_t>(0), executor); | ||
| 205 | + CHECK_RET(unsqueezedInput5D != nullptr, nullptr); | ||
| 206 | + // reformat to NCDHW | ||
| 207 | + auto reformatInput = l0op::ReFormat(unsqueezedInput5D, op::Format::FORMAT_NCDHW); | ||
| 208 | + CHECK_RET(reformatInput != nullptr, nullptr); | ||
| 209 | + | ||
| 210 | + return reformatInput; | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +static inline const aclTensor* View4Das5D(const aclTensor* input, aclOpExecutor* executor) | ||
| 214 | +{ | ||
| 215 | + // NCHW -> unsqueeze -> reformat -> NCDHW | ||
| 216 | + // unsqueeze input into 5D | ||
| 217 | + auto unsqueezedInput = l0op::UnsqueezeNd(input, 2, executor); | ||
| 218 | + CHECK_RET(unsqueezedInput != nullptr, nullptr); | ||
| 219 | + // reformat to NCDHW | ||
| 220 | + auto reformatInput = l0op::ReFormat(unsqueezedInput, op::Format::FORMAT_NCDHW); | ||
| 221 | + CHECK_RET(reformatInput != nullptr, nullptr); | ||
| 222 | + | ||
| 223 | + return reformatInput; | ||
| 224 | +} | ||
| 225 | + | ||
| 226 | +static inline const aclTensor* View5Das3D(const aclTensor* input, const op::Format& format, aclOpExecutor* executor) | ||
| 227 | +{ | ||
| 228 | + // NCDHW -> squeeze -> reformat -> CHW | ||
| 229 | + // squeeze out into 4D | ||
| 230 | + const aclTensor* squeezedInput = l0op::SqueezeNd(input, 2, executor); | ||
| 231 | + CHECK_RET(squeezedInput != nullptr, nullptr); | ||
| 232 | + // squeeze out into 3D | ||
| 233 | + auto squeezedInput3D = l0op::SqueezeNd(squeezedInput, static_cast<int64_t>(0), executor); | ||
| 234 | + CHECK_RET(squeezedInput != nullptr, nullptr); | ||
| 235 | + // reformat to NCL | ||
| 236 | + auto reformatInput = l0op::ReFormat(squeezedInput3D, format); | ||
| 237 | + CHECK_RET(reformatInput != nullptr, nullptr); | ||
| 238 | + | ||
| 239 | + return reformatInput; | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +static inline const aclTensor* View5Das4D(const aclTensor* input, const op::Format& format, aclOpExecutor* executor) | ||
| 243 | +{ | ||
| 244 | + // NCDHW -> squeeze -> reformat -> NCHW | ||
| 245 | + // squeeze out into 3D | ||
| 246 | + auto squeezedInput = l0op::SqueezeNd(input, 2, executor); | ||
| 247 | + CHECK_RET(squeezedInput != nullptr, nullptr); | ||
| 248 | + // reformat to NCHW | ||
| 249 | + auto reformatInput = l0op::ReFormat(squeezedInput, format); | ||
| 250 | + CHECK_RET(reformatInput != nullptr, nullptr); | ||
| 251 | + | ||
| 252 | + return reformatInput; | ||
| 253 | +} | ||
| 254 | + | ||
| 255 | +static const aclTensor* View3Das4D(const aclTensor* input, aclOpExecutor* executor) | ||
| 256 | +{ | ||
| 257 | + // NCL -> unsqueeze -> reformat -> NCHW | ||
| 258 | + // unsqueeze input into 4D | ||
| 259 | + const int64_t appendDim[] = {0}; | ||
| 260 | + aclIntArray* dimUnsqueeze = executor->AllocIntArray(appendDim, 1); | ||
| 261 | + CHECK_RET(dimUnsqueeze != nullptr, nullptr); | ||
| 262 | + auto unsqueezedInput = l0op::UnsqueezeNd(input, dimUnsqueeze, executor); | ||
| 263 | + CHECK_RET(unsqueezedInput != nullptr, nullptr); | ||
| 264 | + // reformat to NCHW | ||
| 265 | + auto reformatInput = l0op::ReFormat(unsqueezedInput, op::Format::FORMAT_NCHW); | ||
| 266 | + CHECK_RET(reformatInput != nullptr, nullptr); | ||
| 267 | + | ||
| 268 | + return reformatInput; | ||
| 269 | +} | ||
| 270 | + | ||
| 271 | +static aclnnStatus ProcessAndCopyResults( | ||
| 272 | + const aclTensor* outResult, | ||
| 273 | + const aclTensor* indicesResultCast, | ||
| 274 | + aclTensor* outputOut, | ||
| 275 | + aclTensor* indicesOut, | ||
| 276 | + aclOpExecutor* executor) | ||
| 277 | +{ | ||
| 278 | + auto resShapeVector = op::ToShapeVector(outputOut->GetViewShape()); | ||
| 279 | + aclIntArray* resShapeArray = | ||
| 280 | + executor->AllocIntArray(resShapeVector.data(), resShapeVector.size()); | ||
| 281 | + CHECK_RET(resShapeArray != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 282 | + auto resTranReshapeOut = l0op::Reshape(outResult, resShapeArray, executor); | ||
| 283 | + CHECK_RET(resTranReshapeOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 284 | + | ||
| 285 | + resTranReshapeOut = l0op::ReFormat(resTranReshapeOut, outputOut->GetStorageFormat(), executor); | ||
| 286 | + CHECK_RET(resTranReshapeOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 287 | + | ||
| 288 | + auto viewCopyResultOut = l0op::ViewCopy(resTranReshapeOut, outputOut, executor); | ||
| 289 | + CHECK_RET(viewCopyResultOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 290 | + | ||
| 291 | + auto resTranReshapeIndices = l0op::Reshape(indicesResultCast, resShapeArray, executor); | ||
| 292 | + CHECK_RET(resTranReshapeIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 293 | + | ||
| 294 | + resTranReshapeIndices = | ||
| 295 | + l0op::ReFormat(resTranReshapeIndices, indicesOut->GetStorageFormat(), executor); | ||
| 296 | + CHECK_RET(resTranReshapeIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 297 | + | ||
| 298 | + auto viewCopyResultIndices = l0op::ViewCopy(resTranReshapeIndices, indicesOut, executor); | ||
| 299 | + CHECK_RET(viewCopyResultIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 300 | + | ||
| 301 | + return ACLNN_SUCCESS; | ||
| 302 | +} | ||
| 303 | + | ||
| 304 | +// 转MaxPool3D | ||
| 305 | +static aclnnStatus HandleMaxPool3DCase( | ||
| 306 | + const aclTensor* inputContiguousReshape, | ||
| 307 | + const std::vector<int64_t>& kernelSizeArr, | ||
| 308 | + aclTensor* outputOut, | ||
| 309 | + aclTensor* indicesOut, | ||
| 310 | + aclOpExecutor* executor) | ||
| 311 | +{ | ||
| 312 | + const aclIntArray* kernelSize = aclCreateIntArray(kernelSizeArr.data(), kernelSizeArr.size()); | ||
| 313 | + const aclIntArray* stride = aclCreateIntArray(kernelSizeArr.data(), kernelSizeArr.size()); | ||
| 314 | + std::vector<int64_t> paddingArr = {0, 0, 0}; | ||
| 315 | + const aclIntArray* padding = aclCreateIntArray(paddingArr.data(), paddingArr.size()); | ||
| 316 | + std::vector<int64_t> dilationArr = {1, 1, 1}; | ||
| 317 | + const aclIntArray* dilation = aclCreateIntArray(dilationArr.data(), dilationArr.size()); | ||
| 318 | + bool ceilMode = false; | ||
| 319 | + std::string dataFormat = "NCDHW"; | ||
| 320 | + | ||
| 321 | + inputContiguousReshape = | ||
| 322 | + l0op::ReFormat(inputContiguousReshape, op::Format::FORMAT_NCDHW, executor); | ||
| 323 | + CHECK_RET(inputContiguousReshape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 324 | + | ||
| 325 | + auto [outResult, indicesResult] = l0op::MaxPool3DWithArgmaxV2Ncdhw( | ||
| 326 | + inputContiguousReshape, kernelSize, stride, padding, dilation, ceilMode, dataFormat, | ||
| 327 | + executor); | ||
| 328 | + CHECK_RET(outResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 329 | + CHECK_RET(indicesResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 330 | + auto indicesResultCast = l0op::Cast(indicesResult, op::DataType::DT_INT64, executor); | ||
| 331 | + CHECK_RET(indicesResultCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 332 | + | ||
| 333 | + auto ret = ProcessAndCopyResults(outResult, indicesResultCast, outputOut, indicesOut, executor); | ||
| 334 | + if (ret != ACLNN_SUCCESS) { | ||
| 335 | + return ret; | ||
| 336 | + } | ||
| 337 | + aclDestroyIntArray(kernelSize); | ||
| 338 | + aclDestroyIntArray(stride); | ||
| 339 | + aclDestroyIntArray(padding); | ||
| 340 | + aclDestroyIntArray(dilation); | ||
| 341 | + | ||
| 342 | + return ACLNN_SUCCESS; | ||
| 343 | +} | ||
| 344 | + | ||
| 345 | +// AdaptiveMaxPool2d的处理逻辑 | ||
| 346 | +static aclnnStatus ProcessAdaptiveMaxPoolResults( | ||
| 347 | + const aclTensor* outResult, | ||
| 348 | + const aclTensor* indicesResult, | ||
| 349 | + aclTensor* outputOut, | ||
| 350 | + aclTensor* indicesOut, | ||
| 351 | + aclOpExecutor* executor) | ||
| 352 | +{ | ||
| 353 | + auto indicesResultCast = l0op::Cast(indicesResult, op::DataType::DT_INT64, executor); | ||
| 354 | + CHECK_RET(indicesResultCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 355 | + | ||
| 356 | + auto resShapeVector = op::ToShapeVector(outputOut->GetViewShape()); | ||
| 357 | + aclIntArray* resShapeArray = | ||
| 358 | + executor->AllocIntArray(resShapeVector.data(), resShapeVector.size()); | ||
| 359 | + CHECK_RET(resShapeArray != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 360 | + auto resTranReshapeOut = l0op::Reshape(outResult, resShapeArray, executor); | ||
| 361 | + CHECK_RET(resTranReshapeOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 362 | + auto viewCopyResultOut = l0op::ViewCopy(resTranReshapeOut, outputOut, executor); | ||
| 363 | + CHECK_RET(viewCopyResultOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 364 | + | ||
| 365 | + auto resTranReshapeIndices = l0op::Reshape(indicesResultCast, resShapeArray, executor); | ||
| 366 | + CHECK_RET(resTranReshapeIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 367 | + auto viewCopyResultIndices = l0op::ViewCopy(resTranReshapeIndices, indicesOut, executor); | ||
| 368 | + CHECK_RET(viewCopyResultIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 369 | + | ||
| 370 | + return ACLNN_SUCCESS; | ||
| 371 | +} | ||
| 372 | + | ||
| 373 | +// NHWC->NCHW | ||
| 374 | +static aclnnStatus ConvertNHWCtoNCHW( | ||
| 375 | + const aclTensor*& inputContiguous, | ||
| 376 | + const aclTensor* self, | ||
| 377 | + aclOpExecutor* executor) | ||
| 378 | +{ | ||
| 379 | + if (self->GetViewFormat() == op::Format::FORMAT_NHWC) { | ||
| 380 | + std::vector<int64_t> valuePerm{INDEX_DIM0, INDEX_DIM3, INDEX_DIM1, INDEX_DIM2}; | ||
| 381 | + auto perm = executor->AllocIntArray(valuePerm.data(), NCHW_DIM_NUM); | ||
| 382 | + CHECK_RET(perm != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 383 | + inputContiguous = l0op::Transpose(inputContiguous, perm, executor); | ||
| 384 | + CHECK_RET(inputContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 385 | + } | ||
| 386 | + return ACLNN_SUCCESS; | ||
| 387 | +} | ||
| 388 | + | ||
| 389 | +static aclnnStatus Handle910DCase( | ||
| 390 | + const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, | ||
| 391 | + aclOpExecutor* executor) | ||
| 392 | +{ | ||
| 393 | + auto inputContiguous = l0op::Contiguous(self, executor); | ||
| 394 | + CHECK_RET(inputContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 395 | + | ||
| 396 | + // NHWC -> NCHW | ||
| 397 | + auto ret = ConvertNHWCtoNCHW(inputContiguous, self, executor); | ||
| 398 | + if (ret != ACLNN_SUCCESS) { | ||
| 399 | + return ret; | ||
| 400 | + } | ||
| 401 | + | ||
| 402 | + // reshape NCHW/NCL -> NCDHW | ||
| 403 | + op::Shape inputContiguousShape = inputContiguous->GetViewShape(); | ||
| 404 | + int64_t inputDimNum = static_cast<int64_t>(inputContiguousShape.GetDimNum()); | ||
| 405 | + int64_t hiValue = inputDimNum == 3 ? inputContiguous->GetViewShape()[1] : inputContiguous->GetViewShape()[2]; | ||
| 406 | + int64_t wiValue = inputDimNum == 3 ? inputContiguous->GetViewShape()[2] : inputContiguous->GetViewShape()[3]; | ||
| 407 | + | ||
| 408 | + int64_t hValueRemainder = hiValue % (*outputSize)[0]; | ||
| 409 | + int64_t wValueRemainder = wiValue % (*outputSize)[1]; | ||
| 410 | + bool ifTranMaxPool3D = hValueRemainder == 0 && wValueRemainder == 0; | ||
| 411 | + const aclTensor* inputContiguousReshape = inputContiguous; | ||
| 412 | + if (inputDimNum == 3 && !ifTranMaxPool3D) { // 转ada 2d | ||
| 413 | + inputContiguousReshape = View3Das4D(inputContiguous, executor); | ||
| 414 | + } else if (ifTranMaxPool3D) { // 转max3d | ||
| 415 | + inputContiguousReshape = inputDimNum == 3 ? View3Das5D(inputContiguous, executor) : | ||
| 416 | + View4Das5D(inputContiguous, executor); | ||
| 417 | + } | ||
| 418 | + if (ifTranMaxPool3D) { | ||
| 419 | + int64_t kernelDSize = 1; | ||
| 420 | + int64_t kernelHSize = inputContiguousReshape->GetViewShape()[INDEX_DIM3] / (*outputSize)[INDEX_DIM0]; | ||
| 421 | + int64_t kernelWSize = inputContiguousReshape->GetViewShape()[INDEX_DIM4] / (*outputSize)[INDEX_DIM1]; | ||
| 422 | + std::vector<int64_t> kernelSizeArr = {kernelDSize, kernelHSize, kernelWSize}; | ||
| 423 | + ret = HandleMaxPool3DCase(inputContiguousReshape, kernelSizeArr, outputOut, indicesOut, | ||
| 424 | + executor); | ||
| 425 | + if (ret != ACLNN_SUCCESS) { | ||
| 426 | + return ret; | ||
| 427 | + } | ||
| 428 | + } else { | ||
| 429 | + auto [outResult, indicesResult] = | ||
| 430 | + l0op::AdaptiveMaxPool2d(inputContiguousReshape, outputSize, executor); | ||
| 431 | + CHECK_RET(outResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 432 | + CHECK_RET(indicesResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 433 | + | ||
| 434 | + ret = ProcessAdaptiveMaxPoolResults(outResult, indicesResult, outputOut, indicesOut, executor); | ||
| 435 | + if (ret != ACLNN_SUCCESS) { | ||
| 436 | + return ret; | ||
| 437 | + } | ||
| 438 | + } | ||
| 439 | + return ACLNN_SUCCESS; | ||
| 440 | +} | ||
| 441 | + | ||
| 442 | +static aclnnStatus Handle910BCase( | ||
| 443 | + const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, | ||
| 444 | + aclOpExecutor* executor) | ||
| 445 | +{ | ||
| 446 | + // 将2d参数转换为3d可以使用的参数 | ||
| 447 | + int64_t newOutputSizeData[] = {1, (*outputSize)[0], (*outputSize)[1]}; | ||
| 448 | + aclIntArray* newOutputSize = executor->AllocIntArray(newOutputSizeData, 3); | ||
| 449 | + | ||
| 450 | + auto inputContiguous = l0op::Contiguous(self, executor); | ||
| 451 | + CHECK_RET(inputContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 452 | + | ||
| 453 | + // NHWC -> NCHW | ||
| 454 | + auto ret = ConvertNHWCtoNCHW(inputContiguous, self, executor); | ||
| 455 | + if (ret != ACLNN_SUCCESS) { | ||
| 456 | + return ret; | ||
| 457 | + } | ||
| 458 | + | ||
| 459 | + // reshape NCHW/NCL -> NCDHW | ||
| 460 | + op::Shape inputContiguousShape = inputContiguous->GetViewShape(); | ||
| 461 | + int64_t inputDimNum = static_cast<int64_t>(inputContiguousShape.GetDimNum()); | ||
| 462 | + std::vector<int64_t> valueShape(NCDHW_DIM_NUM); | ||
| 463 | + valueShape[0] = inputDimNum == static_cast<int64_t>(NCHW_DIM_NUM) ? inputContiguousShape.GetDim(0) : 1; | ||
| 464 | + valueShape[1] = inputDimNum == static_cast<int64_t>(NCHW_DIM_NUM) ? inputContiguousShape.GetDim(1) : | ||
| 465 | + inputContiguousShape.GetDim(0); | ||
| 466 | + valueShape[DIM_D] = 1; | ||
| 467 | + for (int64_t i = inputDimNum - static_cast<int64_t>(OUTPUT_SIZE_NUM); i < inputDimNum; i++) { | ||
| 468 | + valueShape[NCDHW_DIM_NUM - inputDimNum + i] = inputContiguousShape.GetDim(i); | ||
| 469 | + } | ||
| 470 | + auto reshapeShape = executor->AllocIntArray(valueShape.data(), NCDHW_DIM_NUM); | ||
| 471 | + CHECK_RET(reshapeShape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 472 | + auto inputContiguousReshape = l0op::Reshape(inputContiguous, reshapeShape, executor); | ||
| 473 | + CHECK_RET(inputContiguousReshape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 474 | + | ||
| 475 | + int64_t dValueRemainder = inputContiguousReshape->GetViewShape()[INDEX_DIM2] % (*newOutputSize)[INDEX_DIM0]; | ||
| 476 | + int64_t hValueRemainder = inputContiguousReshape->GetViewShape()[INDEX_DIM3] % (*newOutputSize)[INDEX_DIM1]; | ||
| 477 | + int64_t wValueRemainder = inputContiguousReshape->GetViewShape()[INDEX_DIM4] % (*newOutputSize)[INDEX_DIM2]; | ||
| 478 | + if (dValueRemainder == 0 && hValueRemainder == 0 && wValueRemainder == 0) { | ||
| 479 | + int64_t kernelDSize = inputContiguousReshape->GetViewShape()[INDEX_DIM2] / (*newOutputSize)[INDEX_DIM0]; | ||
| 480 | + int64_t kernelHSize = inputContiguousReshape->GetViewShape()[INDEX_DIM3] / (*newOutputSize)[INDEX_DIM1]; | ||
| 481 | + int64_t kernelWSize = inputContiguousReshape->GetViewShape()[INDEX_DIM4] / (*newOutputSize)[INDEX_DIM2]; | ||
| 482 | + std::vector<int64_t> kernelSizeArr = {kernelDSize, kernelHSize, kernelWSize}; | ||
| 483 | + | ||
| 484 | + ret = HandleMaxPool3DCase(inputContiguousReshape, kernelSizeArr, outputOut, indicesOut, executor); | ||
| 485 | + if (ret != ACLNN_SUCCESS) { | ||
| 486 | + return ret; | ||
| 487 | + } | ||
| 488 | + } else { | ||
| 489 | + auto [outResult, indicesResult] = | ||
| 490 | + l0op::AdaptiveMaxPool3d(inputContiguousReshape, newOutputSize, executor); | ||
| 491 | + CHECK_RET(outResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 492 | + CHECK_RET(indicesResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 493 | + | ||
| 494 | + ret = ProcessAdaptiveMaxPoolResults(outResult, indicesResult, outputOut, indicesOut, executor); | ||
| 495 | + if (ret != ACLNN_SUCCESS) { | ||
| 496 | + return ret; | ||
| 497 | + } | ||
| 498 | + } | ||
| 499 | + return ACLNN_SUCCESS; | ||
| 500 | +} | ||
| 501 | + | ||
| 502 | +static aclnnStatus HandleGeneralCase( | ||
| 503 | + const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, | ||
| 504 | + aclOpExecutor* executor) | ||
| 505 | +{ | ||
| 506 | + auto selfContiguous = l0op::Contiguous(self, executor); | ||
| 507 | + CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 508 | + | ||
| 509 | + const aclTensor* selfNewFormat = selfContiguous; | ||
| 510 | + if (self->GetViewShape().GetDimNum() != NCHW_DIM_NUM) { | ||
| 511 | + auto selfNd = l0op::UnsqueezeNd(selfContiguous, AXIS_DIM, executor); | ||
| 512 | + CHECK_RET(selfNd != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 513 | + | ||
| 514 | + selfNewFormat = l0op::ReFormat(selfNd, static_cast<op::Format>(ACL_FORMAT_NCHW)); | ||
| 515 | + CHECK_RET(selfNewFormat != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | + CHECK_RET(CheckInputFormat(selfNewFormat), ACLNN_ERR_PARAM_INVALID); | ||
| 519 | + | ||
| 520 | + auto result = l0op::AdaptiveMaxPool2d(selfNewFormat, outputSize, executor); | ||
| 521 | + const aclTensor* outputRst = std::get<0>(result); | ||
| 522 | + const aclTensor* indicesRst = std::get<1>(result); | ||
| 523 | + | ||
| 524 | + CHECK_RET(outputRst != nullptr && indicesRst != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 525 | + | ||
| 526 | + auto outputNewFormat = outputRst; | ||
| 527 | + auto indicesNewFormat = indicesRst; | ||
| 528 | + if (self->GetViewShape().GetDimNum() != NCHW_DIM_NUM) { | ||
| 529 | + auto outputNewShape = l0op::SqueezeNd(outputRst, AXIS_DIM, executor); | ||
| 530 | + CHECK_RET(outputNewShape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 531 | + | ||
| 532 | + auto indicesNewShape = l0op::SqueezeNd(indicesRst, AXIS_DIM, executor); | ||
| 533 | + CHECK_RET(indicesNewShape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 534 | + | ||
| 535 | + outputNewFormat = l0op::ReFormat(outputNewShape, outputOut->GetViewFormat()); | ||
| 536 | + CHECK_RET(outputNewFormat != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 537 | + | ||
| 538 | + indicesNewFormat = l0op::ReFormat(indicesNewShape, indicesOut->GetViewFormat()); | ||
| 539 | + CHECK_RET(indicesNewFormat != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 540 | + } | ||
| 541 | + // check output shape | ||
| 542 | + CHECK_RET(CheckReduceOutShape(outputNewFormat, outputOut), ACLNN_ERR_PARAM_INVALID); | ||
| 543 | + CHECK_RET(CheckReduceOutShape(indicesNewFormat, indicesOut), ACLNN_ERR_PARAM_INVALID); | ||
| 544 | + auto viewCopyOutputResult = l0op::ViewCopy(outputNewFormat, outputOut, executor); | ||
| 545 | + CHECK_RET(viewCopyOutputResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 546 | + | ||
| 547 | + auto viewCopyIndicesResult = l0op::ViewCopy(indicesNewFormat, indicesOut, executor); | ||
| 548 | + CHECK_RET(viewCopyIndicesResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 549 | + return ACLNN_SUCCESS; | ||
| 550 | +} | ||
| 551 | + | ||
| 190 | aclnnStatus aclnnAdaptiveMaxPool2dGetWorkspaceSize( | 552 | aclnnStatus aclnnAdaptiveMaxPool2dGetWorkspaceSize( |
| 191 | const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, | 553 | const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, |
| 192 | uint64_t* workspaceSize, aclOpExecutor** executor) | 554 | uint64_t* workspaceSize, aclOpExecutor** executor) |
| 193 | { | 555 | { |
| 194 | L2_DFX_PHASE_1(aclnnAdaptiveMaxPool2d, DFX_IN(self, outputSize), DFX_OUT(outputOut, indicesOut)); | 556 | L2_DFX_PHASE_1(aclnnAdaptiveMaxPool2d, DFX_IN(self, outputSize), DFX_OUT(outputOut, indicesOut)); |
| 195 | - | ||
| 196 | auto uniqueExecutor = CREATE_EXECUTOR(); | 557 | auto uniqueExecutor = CREATE_EXECUTOR(); |
| 197 | CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | 558 | CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); |
| 198 | 559 | ||
| @@ -205,171 +566,17 @@ aclnnStatus aclnnAdaptiveMaxPool2dGetWorkspaceSize( | |||
| 205 | return ACLNN_SUCCESS; | 566 | return ACLNN_SUCCESS; |
| 206 | } | 567 | } |
| 207 | 568 | ||
| 208 | - if (IsSocVersion910B() && !(IsSelfDtypeDouble(self))) { | 569 | + if (IsSocVersion910D() && !(IsSelfDtypeDouble(self))) { |
| 209 | - // 将2d参数转换为3d可以使用的参数 | 570 | + CHECK_RET( |
| 210 | - int64_t newOutputSizeData[] = {1, (*outputSize)[0], (*outputSize)[1]}; | 571 | + Handle910DCase(self, outputSize, outputOut, indicesOut, uniqueExecutor.get()) == ACLNN_SUCCESS, |
| 211 | - aclIntArray* newOutputSize = uniqueExecutor.get()->AllocIntArray(newOutputSizeData, 3); | 572 | + ACLNN_ERR_INNER_NULLPTR); |
| 212 | - | 573 | + } else if (IsSocVersion910B() && !(IsSelfDtypeDouble(self))) { |
| 213 | - auto inputContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | 574 | + CHECK_RET(Handle910BCase(self, outputSize, outputOut, indicesOut, uniqueExecutor.get()) == ACLNN_SUCCESS, |
| 214 | - CHECK_RET(inputContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | 575 | + ACLNN_ERR_INNER_NULLPTR); |
| 215 | - | 576 | + } else { |
| 216 | - // NHWC -> NCHW | 577 | + CHECK_RET(HandleGeneralCase(self, outputSize, outputOut, indicesOut, uniqueExecutor.get()) == ACLNN_SUCCESS, |
| 217 | - if (self->GetViewFormat() == op::Format::FORMAT_NHWC) { | 578 | + ACLNN_ERR_INNER_NULLPTR); |
| 218 | - std::vector<int64_t> valuePerm{INDEX_DIM0, INDEX_DIM3, INDEX_DIM1, INDEX_DIM2}; | ||
| 219 | - auto perm = uniqueExecutor.get()->AllocIntArray(valuePerm.data(), NCHW_DIM_NUM); | ||
| 220 | - CHECK_RET(perm != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 221 | - inputContiguous = l0op::Transpose(inputContiguous, perm, uniqueExecutor.get()); | ||
| 222 | - CHECK_RET(inputContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 223 | - } | ||
| 224 | - | ||
| 225 | - // reshape NCHW/NCL -> NCDHW | ||
| 226 | - op::Shape inputContiguousShape = inputContiguous->GetViewShape(); | ||
| 227 | - int64_t inputDimNum = static_cast<int64_t>(inputContiguousShape.GetDimNum()); | ||
| 228 | - std::vector<int64_t> valueShape(NCDHW_DIM_NUM); | ||
| 229 | - valueShape[0] = inputDimNum == static_cast<int64_t>(NCHW_DIM_NUM) ? inputContiguousShape.GetDim(0) : 1; | ||
| 230 | - valueShape[1] = inputDimNum == static_cast<int64_t>(NCHW_DIM_NUM) ? inputContiguousShape.GetDim(1) : | ||
| 231 | - inputContiguousShape.GetDim(0); | ||
| 232 | - valueShape[DIM_D] = 1; | ||
| 233 | - for (int64_t i = inputDimNum - static_cast<int64_t>(OUTPUT_SIZE_NUM); i < inputDimNum; i++) { | ||
| 234 | - valueShape[NCDHW_DIM_NUM - inputDimNum + i] = inputContiguousShape.GetDim(i); | ||
| 235 | - } | ||
| 236 | - auto reshapeShape = uniqueExecutor.get()->AllocIntArray(valueShape.data(), NCDHW_DIM_NUM); | ||
| 237 | - CHECK_RET(reshapeShape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 238 | - auto inputContiguousReshape = l0op::Reshape(inputContiguous, reshapeShape, uniqueExecutor.get()); | ||
| 239 | - CHECK_RET(inputContiguousReshape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 240 | - | ||
| 241 | - int64_t dValueRemainder = inputContiguousReshape->GetViewShape()[INDEX_DIM2] % (*newOutputSize)[INDEX_DIM0]; | ||
| 242 | - int64_t hValueRemainder = inputContiguousReshape->GetViewShape()[INDEX_DIM3] % (*newOutputSize)[INDEX_DIM1]; | ||
| 243 | - int64_t wValueRemainder = inputContiguousReshape->GetViewShape()[INDEX_DIM4] % (*newOutputSize)[INDEX_DIM2]; | ||
| 244 | - if (dValueRemainder == 0 && hValueRemainder == 0 && wValueRemainder == 0) { | ||
| 245 | - size_t kernelDSize = inputContiguousReshape->GetViewShape()[INDEX_DIM2] / (*newOutputSize)[INDEX_DIM0]; | ||
| 246 | - size_t kernelHSize = inputContiguousReshape->GetViewShape()[INDEX_DIM3] / (*newOutputSize)[INDEX_DIM1]; | ||
| 247 | - size_t kernelWSize = inputContiguousReshape->GetViewShape()[INDEX_DIM4] / (*newOutputSize)[INDEX_DIM2]; | ||
| 248 | - std::vector<int64_t> kernelSizeArr = {}; | ||
| 249 | - kernelSizeArr.push_back(kernelDSize); | ||
| 250 | - kernelSizeArr.push_back(kernelHSize); | ||
| 251 | - kernelSizeArr.push_back(kernelWSize); | ||
| 252 | - const aclIntArray* kernelSize = aclCreateIntArray(kernelSizeArr.data(), kernelSizeArr.size()); | ||
| 253 | - const aclIntArray* stride = aclCreateIntArray(kernelSizeArr.data(), kernelSizeArr.size()); | ||
| 254 | - std::vector<int64_t> paddingArr = {0, 0, 0}; | ||
| 255 | - const aclIntArray* padding = aclCreateIntArray(paddingArr.data(), paddingArr.size()); | ||
| 256 | - std::vector<int64_t> dilationArr = {1, 1, 1}; | ||
| 257 | - const aclIntArray* dilation = aclCreateIntArray(dilationArr.data(), dilationArr.size()); | ||
| 258 | - bool ceilMode = false; | ||
| 259 | - std::string dataFormat = "NCDHW"; | ||
| 260 | - | ||
| 261 | - inputContiguousReshape = | ||
| 262 | - l0op::ReFormat(inputContiguousReshape, op::Format::FORMAT_NCDHW, uniqueExecutor.get()); | ||
| 263 | - CHECK_RET(inputContiguousReshape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 264 | - | ||
| 265 | - auto [outResult, indicesResult] = l0op::MaxPool3DWithArgmaxV2Ncdhw( | ||
| 266 | - inputContiguousReshape, kernelSize, stride, padding, dilation, ceilMode, dataFormat, | ||
| 267 | - uniqueExecutor.get()); | ||
| 268 | - CHECK_RET(outResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 269 | - CHECK_RET(indicesResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 270 | - auto indicesResultCast = l0op::Cast(indicesResult, op::DataType::DT_INT64, uniqueExecutor.get()); | ||
| 271 | - CHECK_RET(indicesResultCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 272 | - | ||
| 273 | - auto resShapeVector = op::ToShapeVector(outputOut->GetViewShape()); | ||
| 274 | - aclIntArray* resShapeArray = | ||
| 275 | - uniqueExecutor.get()->AllocIntArray(resShapeVector.data(), resShapeVector.size()); | ||
| 276 | - CHECK_RET(resShapeArray != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 277 | - auto resTranReshapeOut = l0op::Reshape(outResult, resShapeArray, uniqueExecutor.get()); | ||
| 278 | - CHECK_RET(resTranReshapeOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 279 | - | ||
| 280 | - resTranReshapeOut = l0op::ReFormat(resTranReshapeOut, outputOut->GetStorageFormat(), uniqueExecutor.get()); | ||
| 281 | - CHECK_RET(resTranReshapeOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 282 | - | ||
| 283 | - auto viewCopyResultOut = l0op::ViewCopy(resTranReshapeOut, outputOut, uniqueExecutor.get()); | ||
| 284 | - CHECK_RET(viewCopyResultOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 285 | - | ||
| 286 | - auto resTranReshapeIndices = l0op::Reshape(indicesResultCast, resShapeArray, uniqueExecutor.get()); | ||
| 287 | - CHECK_RET(resTranReshapeIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 288 | - | ||
| 289 | - resTranReshapeIndices = | ||
| 290 | - l0op::ReFormat(resTranReshapeIndices, indicesOut->GetStorageFormat(), uniqueExecutor.get()); | ||
| 291 | - CHECK_RET(resTranReshapeIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 292 | - | ||
| 293 | - auto viewCopyResultIndices = l0op::ViewCopy(resTranReshapeIndices, indicesOut, uniqueExecutor.get()); | ||
| 294 | - CHECK_RET(viewCopyResultIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 295 | - // 释放资源 | ||
| 296 | - aclDestroyIntArray(kernelSize); | ||
| 297 | - aclDestroyIntArray(stride); | ||
| 298 | - aclDestroyIntArray(padding); | ||
| 299 | - aclDestroyIntArray(dilation); | ||
| 300 | - } else { | ||
| 301 | - auto [outResult, indicesResult] = | ||
| 302 | - l0op::AdaptiveMaxPool3d(inputContiguousReshape, newOutputSize, uniqueExecutor.get()); | ||
| 303 | - CHECK_RET(outResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 304 | - CHECK_RET(indicesResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 305 | - auto indicesResultCast = l0op::Cast(indicesResult, op::DataType::DT_INT64, uniqueExecutor.get()); | ||
| 306 | - CHECK_RET(indicesResultCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 307 | - | ||
| 308 | - auto resShapeVector = op::ToShapeVector(outputOut->GetViewShape()); | ||
| 309 | - aclIntArray* resShapeArray = | ||
| 310 | - uniqueExecutor.get()->AllocIntArray(resShapeVector.data(), resShapeVector.size()); | ||
| 311 | - CHECK_RET(resShapeArray != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 312 | - auto resTranReshapeOut = l0op::Reshape(outResult, resShapeArray, uniqueExecutor.get()); | ||
| 313 | - CHECK_RET(resTranReshapeOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 314 | - auto viewCopyResultOut = l0op::ViewCopy(resTranReshapeOut, outputOut, uniqueExecutor.get()); | ||
| 315 | - CHECK_RET(viewCopyResultOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 316 | - | ||
| 317 | - auto resTranReshapeIndices = l0op::Reshape(indicesResultCast, resShapeArray, uniqueExecutor.get()); | ||
| 318 | - CHECK_RET(resTranReshapeIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 319 | - auto viewCopyResultIndices = l0op::ViewCopy(resTranReshapeIndices, indicesOut, uniqueExecutor.get()); | ||
| 320 | - CHECK_RET(viewCopyResultIndices != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 321 | - } | ||
| 322 | - | ||
| 323 | - // 固定写法,获取计算过程中需要使用的workspace大小 | ||
| 324 | - *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 325 | - uniqueExecutor.ReleaseTo(executor); | ||
| 326 | - return ACLNN_SUCCESS; | ||
| 327 | } | 579 | } |
| 328 | - auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | ||
| 329 | - CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 330 | - | ||
| 331 | - const aclTensor* selfNewFormat = selfContiguous; | ||
| 332 | - if (self->GetViewShape().GetDimNum() != NCHW_DIM_NUM) { | ||
| 333 | - auto selfNd = l0op::UnsqueezeNd(selfContiguous, AXIS_DIM, uniqueExecutor.get()); | ||
| 334 | - CHECK_RET(selfNd != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 335 | - | ||
| 336 | - selfNewFormat = l0op::ReFormat(selfNd, static_cast<op::Format>(ACL_FORMAT_NCHW)); | ||
| 337 | - CHECK_RET(selfNewFormat != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 338 | - } | ||
| 339 | - | ||
| 340 | - CHECK_RET(CheckInputFormat(selfNewFormat), ACLNN_ERR_PARAM_INVALID); | ||
| 341 | - | ||
| 342 | - auto result = l0op::AdaptiveMaxPool2d(selfNewFormat, outputSize, uniqueExecutor.get()); | ||
| 343 | - const aclTensor* outputRst = std::get<0>(result); | ||
| 344 | - const aclTensor* indicesRst = std::get<1>(result); | ||
| 345 | - | ||
| 346 | - CHECK_RET(outputRst != nullptr && indicesRst != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 347 | - | ||
| 348 | - auto outputNewFormat = outputRst; | ||
| 349 | - auto indicesNewFormat = indicesRst; | ||
| 350 | - if (self->GetViewShape().GetDimNum() != NCHW_DIM_NUM) { | ||
| 351 | - auto outputNewShape = l0op::SqueezeNd(outputRst, AXIS_DIM, uniqueExecutor.get()); | ||
| 352 | - CHECK_RET(outputNewShape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 353 | - | ||
| 354 | - auto indicesNewShape = l0op::SqueezeNd(indicesRst, AXIS_DIM, uniqueExecutor.get()); | ||
| 355 | - CHECK_RET(indicesNewShape != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 356 | - | ||
| 357 | - outputNewFormat = l0op::ReFormat(outputNewShape, outputOut->GetViewFormat()); | ||
| 358 | - CHECK_RET(outputNewFormat != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 359 | - | ||
| 360 | - indicesNewFormat = l0op::ReFormat(indicesNewShape, indicesOut->GetViewFormat()); | ||
| 361 | - CHECK_RET(indicesNewFormat != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 362 | - } | ||
| 363 | - // check output shape | ||
| 364 | - CHECK_RET(CheckReduceOutShape(outputNewFormat, outputOut), ACLNN_ERR_PARAM_INVALID); | ||
| 365 | - CHECK_RET(CheckReduceOutShape(indicesNewFormat, indicesOut), ACLNN_ERR_PARAM_INVALID); | ||
| 366 | - auto viewCopyOutputResult = l0op::ViewCopy(outputNewFormat, outputOut, uniqueExecutor.get()); | ||
| 367 | - CHECK_RET(viewCopyOutputResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 368 | - | ||
| 369 | - auto viewCopyIndicesResult = l0op::ViewCopy(indicesNewFormat, indicesOut, uniqueExecutor.get()); | ||
| 370 | - CHECK_RET(viewCopyIndicesResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 371 | - | ||
| 372 | - // 固定写法,获取计算过程中需要使用的workspace大小 | ||
| 373 | *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | 580 | *workspaceSize = uniqueExecutor->GetWorkspaceSize(); |
| 374 | uniqueExecutor.ReleaseTo(executor); | 581 | uniqueExecutor.ReleaseTo(executor); |
| 375 | return ACLNN_SUCCESS; | 582 | return ACLNN_SUCCESS; |
Rpooling/adaptive_max_pool3d/op_api/aclnn_adaptive_max_pool2d.h→pooling/adaptive_max_pool2d/op_api/aclnn_adaptive_max_pool2d.h+0-0
文件重命名但无更改。
Rpooling/adaptive_max_pool3d/op_api/adaptive_max_pool2d.cpp→pooling/adaptive_max_pool2d/op_api/adaptive_max_pool2d.cpp+41-4
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 18 | 19 | ||
| 19 | using namespace op; | 20 | using namespace op; |
| 20 | namespace l0op { | 21 | namespace l0op { |
| @@ -25,6 +26,17 @@ static constexpr size_t DIM_W = 1; | |||
| 25 | static constexpr size_t NHWC_DIM_H = 3; | 26 | static constexpr size_t NHWC_DIM_H = 3; |
| 26 | static constexpr size_t NHWC_DIM_W = 2; | 27 | static constexpr size_t NHWC_DIM_W = 2; |
| 27 | 28 | ||
| 29 | +static const std::initializer_list<op::DataType> AICORE_DTYPE_SUPPORT_LIST_950 = { | ||
| 30 | + op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16}; | ||
| 31 | + | ||
| 32 | +static bool IsAscend950iCoreSupport(const aclTensor* self) | ||
| 33 | +{ | ||
| 34 | + if (!Ops::NN::AclnnUtil::IsRegbase()) { | ||
| 35 | + return false; | ||
| 36 | + } | ||
| 37 | + return CheckType(self->GetDataType(), AICORE_DTYPE_SUPPORT_LIST_950); | ||
| 38 | +} | ||
| 39 | + | ||
| 28 | std::tuple<aclTensor*, aclTensor*> AdapativeMaxPool2dAiCpu( | 40 | std::tuple<aclTensor*, aclTensor*> AdapativeMaxPool2dAiCpu( |
| 29 | const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, | 41 | const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, |
| 30 | aclOpExecutor* executor) | 42 | aclOpExecutor* executor) |
| @@ -41,6 +53,17 @@ std::tuple<aclTensor*, aclTensor*> AdapativeMaxPool2dAiCpu( | |||
| 41 | return std::tuple<aclTensor*, aclTensor*>(outputOut, indicesOut); | 53 | return std::tuple<aclTensor*, aclTensor*>(outputOut, indicesOut); |
| 42 | } | 54 | } |
| 43 | 55 | ||
| 56 | +std::tuple<aclTensor*, aclTensor*> AdapativeMaxPool2dAiCore( | ||
| 57 | + const aclTensor* self, const aclIntArray* outputSize, aclTensor* outputOut, aclTensor* indicesOut, | ||
| 58 | + aclOpExecutor* executor) | ||
| 59 | +{ | ||
| 60 | + L0_DFX(AdapativeMaxPool2dAiCore, self, outputSize, outputOut, indicesOut); | ||
| 61 | + ADD_TO_LAUNCHER_LIST_AICORE( | ||
| 62 | + AdaptiveMaxPool2d, OP_INPUT(self), OP_OUTPUT(outputOut, indicesOut), OP_ATTR(outputSize)); | ||
| 63 | + return std::tuple<aclTensor*, aclTensor*>(outputOut, indicesOut); | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | + | ||
| 44 | std::tuple<aclTensor*, aclTensor*> AdaptiveMaxPool2d( | 67 | std::tuple<aclTensor*, aclTensor*> AdaptiveMaxPool2d( |
| 45 | const aclTensor* self, const aclIntArray* outputSize, aclOpExecutor* executor) | 68 | const aclTensor* self, const aclIntArray* outputSize, aclOpExecutor* executor) |
| 46 | { | 69 | { |
| @@ -58,11 +81,25 @@ std::tuple<aclTensor*, aclTensor*> AdaptiveMaxPool2d( | |||
| 58 | } | 81 | } |
| 59 | 82 | ||
| 60 | auto outputOut = executor->AllocTensor(outShape, self->GetDataType(), self->GetStorageFormat()); | 83 | auto outputOut = executor->AllocTensor(outShape, self->GetDataType(), self->GetStorageFormat()); |
| 61 | - auto indicesOut = executor->AllocTensor(outShape, op::DataType::DT_INT64, self->GetStorageFormat()); | 84 | + |
| 62 | - if (outputOut == nullptr || indicesOut == nullptr) { | 85 | + if (outputOut == nullptr) { |
| 63 | - OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "outputOut or indicesOut is nullptr."); | 86 | + OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "outputOut is nullptr."); |
| 64 | return std::tuple<aclTensor*, aclTensor*>(nullptr, nullptr); | 87 | return std::tuple<aclTensor*, aclTensor*>(nullptr, nullptr); |
| 65 | } | 88 | } |
| 66 | - return AdapativeMaxPool2dAiCpu(self, outputSize, outputOut, indicesOut, executor); | 89 | + if (IsAscend950iCoreSupport(self)) { |
| 90 | + auto indicesInt32Out = executor->AllocTensor(outShape, op::DataType::DT_INT32, self->GetStorageFormat()); | ||
| 91 | + if (indicesInt32Out == nullptr) { | ||
| 92 | + OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "indicesInt32Out is nullptr."); | ||
| 93 | + return std::tuple<aclTensor*, aclTensor*>(nullptr, nullptr); | ||
| 94 | + } | ||
| 95 | + OP_LOGI("beigin adaptive maxpool2d.\n"); | ||
| 96 | + return AdapativeMaxPool2dAiCore(self, outputSize, outputOut, indicesInt32Out, executor); | ||
| 97 | + } | ||
| 98 | + auto indicesInt64Out = executor->AllocTensor(outShape, op::DataType::DT_INT64, self->GetStorageFormat()); | ||
| 99 | + if (indicesInt64Out == nullptr) { | ||
| 100 | + OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "indicesInt64Out is nullptr."); | ||
| 101 | + return std::tuple<aclTensor*, aclTensor*>(nullptr, nullptr); | ||
| 102 | + } | ||
| 103 | + return AdapativeMaxPool2dAiCpu(self, outputSize, outputOut, indicesInt64Out, executor); | ||
| 67 | } | 104 | } |
| 68 | } // namespace l0op | 105 | } // namespace l0op |
Rpooling/adaptive_max_pool3d/op_api/adaptive_max_pool2d.h→pooling/adaptive_max_pool2d/op_api/adaptive_max_pool2d.h+0-0
文件重命名但无更改。
| @@ -0,0 +1,51 @@ | |||
| 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 adaptive_max_pool2d_def.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +constexpr int DTYPE_INT32 = 3; | ||
| 18 | +namespace ops { | ||
| 19 | +class AdaptiveMaxPool2d : public OpDef | ||
| 20 | +{ | ||
| 21 | +public: | ||
| 22 | + explicit AdaptiveMaxPool2d(const char* name) : OpDef(name) | ||
| 23 | + { | ||
| 24 | + this->Input("x") | ||
| 25 | + .ParamType(REQUIRED) | ||
| 26 | + .DataType({ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_BF16}) | ||
| 27 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 28 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); | ||
| 29 | + this->Output("y") | ||
| 30 | + .ParamType(REQUIRED) | ||
| 31 | + .DataType({ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_BF16, ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_BF16}) | ||
| 32 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 33 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); | ||
| 34 | + this->Output("indices") | ||
| 35 | + .ParamType(REQUIRED) | ||
| 36 | + .DataType({ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64}) | ||
| 37 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 38 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); | ||
| 39 | + this->Attr("output_size").AttrType(REQUIRED).ListInt(); | ||
| 40 | + this->Attr("indices_dtype").AttrType(OPTIONAL).Int(DTYPE_INT32); | ||
| 41 | + | ||
| 42 | + OpAICoreConfig aicore_config; | ||
| 43 | + aicore_config.DynamicCompileStaticFlag(true) | ||
| 44 | + .DynamicRankSupportFlag(true) | ||
| 45 | + .DynamicShapeSupportFlag(true); | ||
| 46 | + this->AICore().AddConfig("ascend950"); | ||
| 47 | + } | ||
| 48 | +}; | ||
| 49 | + | ||
| 50 | +OP_ADD(AdaptiveMaxPool2d); | ||
| 51 | +} // namespace ops | ||
| @@ -0,0 +1,158 @@ | |||
| 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 adaptive_max_pool2d_tiling.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +using Ops::NN::Optiling::TilingRegistry; | ||
| 19 | + | ||
| 20 | +namespace optiling { | ||
| 21 | +constexpr uint64_t NCHW_DIM_N = 0; | ||
| 22 | +constexpr uint64_t NCHW_DIM_C = 1; | ||
| 23 | +constexpr uint64_t NCHW_DIM_H = 2; | ||
| 24 | +constexpr uint64_t NCHW_DIM_W = 3; | ||
| 25 | +constexpr uint64_t OUTPUTSIZE_DIM_MAX = 2; | ||
| 26 | +constexpr uint64_t DIM_NUM_FOUR = 4; | ||
| 27 | +static const gert::Shape g_vec_1_shape = {1}; | ||
| 28 | + | ||
| 29 | +static const gert::Shape &EnsureNotScalar(const gert::Shape &inShape) { | ||
| 30 | + if (inShape.IsScalar()) { | ||
| 31 | + return g_vec_1_shape; | ||
| 32 | + } | ||
| 33 | + return inShape; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +bool AdaMaxPool2dBaseTiling::IsCapable() | ||
| 37 | +{ | ||
| 38 | + return true; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +ge::graphStatus AdaMaxPool2dBaseTiling::DoOpTiling() | ||
| 42 | +{ | ||
| 43 | + return ge::GRAPH_SUCCESS; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +ge::graphStatus AdaMaxPool2dBaseTiling::DoLibApiTiling() | ||
| 47 | +{ | ||
| 48 | + return ge::GRAPH_SUCCESS; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +uint64_t AdaMaxPool2dBaseTiling::GetTilingKey() const | ||
| 52 | +{ | ||
| 53 | + return 0; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +ge::graphStatus AdaMaxPool2dBaseTiling::GetPlatformInfo() | ||
| 57 | +{ | ||
| 58 | + auto compileInfo = context_->GetCompileInfo<AdaptiveMaxPool2dCompileInfo>(); | ||
| 59 | + OP_CHECK_NULL_WITH_CONTEXT(context_, compileInfo); | ||
| 60 | + input_.coreNum = compileInfo->coreNum; | ||
| 61 | + input_.ubSizePlatForm = compileInfo->ubSizePlatForm; | ||
| 62 | + OP_CHECK_IF(input_.coreNum <= 0, OP_LOGE(context_, "GetPlatformInfo get corenum <= 0"), return ge::GRAPH_FAILED); | ||
| 63 | + sysWorkspaceSize_ = compileInfo->sysWorkspaceSize; | ||
| 64 | + return ge::GRAPH_SUCCESS; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +ge::graphStatus AdaMaxPool2dBaseTiling::GetShapeAttrsInfo() | ||
| 68 | +{ | ||
| 69 | + auto nodeName = context_->GetNodeName(); | ||
| 70 | + OP_LOGD(nodeName, "GetShapeAttrsInfo begin."); | ||
| 71 | + | ||
| 72 | + auto inputX = context_->GetInputShape(0); | ||
| 73 | + OP_CHECK_NULL_WITH_CONTEXT(context_, inputX); | ||
| 74 | + auto inputXDesc = context_->GetInputDesc(0); | ||
| 75 | + OP_CHECK_NULL_WITH_CONTEXT(context_, inputXDesc); | ||
| 76 | + auto xDtype = inputXDesc->GetDataType(); | ||
| 77 | + OP_CHECK_IF( | ||
| 78 | + (xDtype != ge::DT_FLOAT && xDtype != ge::DT_FLOAT16 && xDtype != ge::DT_BF16), | ||
| 79 | + OP_LOGE(nodeName, "x datatype only support float, float16, bfloat16"), return ge::GRAPH_FAILED); | ||
| 80 | + input_.xDtype = xDtype; | ||
| 81 | + gert::Shape xShape = EnsureNotScalar(inputX->GetStorageShape()); | ||
| 82 | + if (xShape.GetDimNum() == DIM_NUM_FOUR) { | ||
| 83 | + input_.N = xShape.GetDim(NCHW_DIM_N); | ||
| 84 | + input_.C = xShape.GetDim(NCHW_DIM_C); | ||
| 85 | + input_.Hi = xShape.GetDim(NCHW_DIM_H); | ||
| 86 | + input_.Wi = xShape.GetDim(NCHW_DIM_W); | ||
| 87 | + } else { | ||
| 88 | + OP_LOGE(nodeName, "xShape dim number should be 5"); | ||
| 89 | + return ge::GRAPH_FAILED; | ||
| 90 | + } | ||
| 91 | + OP_CHECK_IF( | ||
| 92 | + input_.N < 1 || input_.C < 1 || input_.Hi < 1 || input_.Wi < 1, | ||
| 93 | + OP_LOGE(nodeName, "Invalid shape. Maybe empty tensor."), return ge::GRAPH_FAILED); | ||
| 94 | + OP_CHECK_IF(input_.Hi * input_.Wi > static_cast<int64_t>(std::numeric_limits<int32_t>::max()), | ||
| 95 | + OP_LOGE(nodeName, "no support for H*W of input greater than int32 max value"), return ge::GRAPH_FAILED); | ||
| 96 | + | ||
| 97 | + auto attrPtr = context_->GetAttrs(); | ||
| 98 | + OP_CHECK_NULL_WITH_CONTEXT(context_, attrPtr); | ||
| 99 | + auto outputSizePtr = attrPtr->GetAttrPointer<gert::ContinuousVector>(0); | ||
| 100 | + OP_CHECK_NULL_WITH_CONTEXT(context_, outputSizePtr); | ||
| 101 | + OP_CHECK_IF( | ||
| 102 | + outputSizePtr->GetSize() != OUTPUTSIZE_DIM_MAX, OP_LOGE(nodeName, "the size of outputsize only support 2"), | ||
| 103 | + return ge::GRAPH_FAILED); | ||
| 104 | + const int64_t* outputSize = static_cast<const int64_t*>(outputSizePtr->GetData()); | ||
| 105 | + OP_CHECK_IF( | ||
| 106 | + outputSize[0] <= 0 || outputSize[1] <= 0, | ||
| 107 | + OP_LOGE(nodeName, "the value of outputsize should > 0"), return ge::GRAPH_FAILED); | ||
| 108 | + input_.Ho = outputSize[0]; | ||
| 109 | + input_.Wo = outputSize[1]; | ||
| 110 | + return ge::GRAPH_SUCCESS; | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +ge::graphStatus AdaMaxPool2dBaseTiling::GetWorkspaceSize() | ||
| 114 | +{ | ||
| 115 | + size_t* workspaces = context_->GetWorkspaceSizes(1); | ||
| 116 | + workspaces[0] = sysWorkspaceSize_; | ||
| 117 | + return ge::GRAPH_SUCCESS; | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +ge::graphStatus AdaMaxPool2dBaseTiling::PostTiling() | ||
| 121 | +{ | ||
| 122 | + return ge::GRAPH_SUCCESS; | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +static ge::graphStatus Tiling4AdaptiveMaxPool2d(gert::TilingContext* context) | ||
| 126 | +{ | ||
| 127 | + return TilingRegistry::GetInstance().DoTilingImpl(context); | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +static ge::graphStatus TilingPrepare4AdaptiveMaxPool2d(gert::TilingParseContext* context) | ||
| 131 | +{ | ||
| 132 | + OP_LOGD(context, "TilingPrepare4AdaptiveMaxPool2d enter."); | ||
| 133 | + | ||
| 134 | + auto compileInfo = context->GetCompiledInfo<AdaptiveMaxPool2dCompileInfo>(); | ||
| 135 | + OP_CHECK_NULL_WITH_CONTEXT(context, compileInfo); | ||
| 136 | + auto platformInfo = context->GetPlatformInfo(); | ||
| 137 | + OP_CHECK_NULL_WITH_CONTEXT(context, platformInfo); | ||
| 138 | + | ||
| 139 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo); | ||
| 140 | + compileInfo->coreNum = ascendcPlatform.GetCoreNumAiv(); | ||
| 141 | + uint64_t ubSizePlatForm; | ||
| 142 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSizePlatForm); | ||
| 143 | + compileInfo->ubSizePlatForm = ubSizePlatForm; | ||
| 144 | + | ||
| 145 | + size_t sysWorkspaceSize = ascendcPlatform.GetLibApiWorkSpaceSize(); | ||
| 146 | + compileInfo->sysWorkspaceSize = sysWorkspaceSize; | ||
| 147 | + | ||
| 148 | + OP_CHECK_IF((compileInfo->coreNum <= 0), OP_LOGE(context, "Failed to get corenum size"), return ge::GRAPH_FAILED); | ||
| 149 | + OP_CHECK_IF((compileInfo->ubSizePlatForm <= 0), OP_LOGE(context, "Failed to get ub size"), return ge::GRAPH_FAILED); | ||
| 150 | + OP_LOGD(context, "ub_size_platform is %lu", compileInfo->ubSizePlatForm); | ||
| 151 | + OP_LOGD(context, "TilingPrepare4AdaptiveMaxPool2d end"); | ||
| 152 | + return ge::GRAPH_SUCCESS; | ||
| 153 | +} | ||
| 154 | + | ||
| 155 | +IMPL_OP_OPTILING(AdaptiveMaxPool2d) | ||
| 156 | + .Tiling(Tiling4AdaptiveMaxPool2d) | ||
| 157 | + .TilingParse<AdaptiveMaxPool2dCompileInfo>(TilingPrepare4AdaptiveMaxPool2d); | ||
| 158 | +} // namespace optiling | ||
| @@ -0,0 +1,136 @@ | |||
| 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 adaptive_max_pool2d_tiling_base.h | ||
| 13 | + * \brief tiling base imply for adaptive_max_pool2d | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +using namespace std; | ||
| 28 | + | ||
| 29 | +namespace optiling { | ||
| 30 | +using Ops::NN::Optiling::TilingBaseClass; | ||
| 31 | +const int HW_DIMS = 2; | ||
| 32 | +const uint32_t H_DIM = 0; | ||
| 33 | +const uint32_t W_DIM = 1; | ||
| 34 | +const uint32_t MAX_DIV = 2; | ||
| 35 | +const uint32_t NCHW_CONV_ADDR_LIST_SIZE = 16; | ||
| 36 | +const uint32_t MIN_TRANSPOSE_ROWS = 16; | ||
| 37 | +const uint32_t INT64_FP32 = 2; | ||
| 38 | +const uint32_t BINARY_SEARCH_COEFF = 2; | ||
| 39 | +const uint32_t BLOCK_LEN_FP32 = 8; | ||
| 40 | +const uint32_t BLOCK_LEN_FP16 = 16; | ||
| 41 | + | ||
| 42 | +struct AdaptiveMaxPool2dCompileInfo { | ||
| 43 | + uint64_t coreNum = 0; | ||
| 44 | + uint64_t ubSizePlatForm = 0; | ||
| 45 | + size_t sysWorkspaceSize = 0; | ||
| 46 | +}; | ||
| 47 | + | ||
| 48 | +struct InputInfo { | ||
| 49 | + uint64_t coreNum{0}; | ||
| 50 | + uint64_t ubSizePlatForm{0}; | ||
| 51 | + ge::DataType xDtype{ge::DT_FLOAT}; | ||
| 52 | + ge::DataType indicesDtype{ge::DT_INT32}; | ||
| 53 | + uint64_t N{0}; | ||
| 54 | + uint64_t C{0}; | ||
| 55 | + uint64_t Hi{0}; | ||
| 56 | + uint64_t Wi{0}; | ||
| 57 | + uint64_t Ho{0}; | ||
| 58 | + uint64_t Wo{0}; | ||
| 59 | +}; | ||
| 60 | + | ||
| 61 | +struct CalculateInfo { | ||
| 62 | + uint64_t useCoreNum{0}; | ||
| 63 | + uint64_t totalIdx{0}; | ||
| 64 | + uint64_t blockFactor{0}; | ||
| 65 | + uint64_t blockTail{0}; | ||
| 66 | + uint64_t ncFactor{0}; | ||
| 67 | + uint64_t hoFactor{0}; | ||
| 68 | + uint64_t woFactor{0}; | ||
| 69 | + uint64_t ncOuter{0}; | ||
| 70 | + uint64_t hoOuter{0}; | ||
| 71 | + uint64_t woOuter{0}; | ||
| 72 | + uint64_t ncTail{0}; | ||
| 73 | + uint64_t hoTail{0}; | ||
| 74 | + uint64_t woTail{0}; | ||
| 75 | + uint64_t kernelHMax{0}; | ||
| 76 | + uint64_t kernelWMax{0}; | ||
| 77 | +}; | ||
| 78 | + | ||
| 79 | +BEGIN_TILING_DATA_DEF(AdaptiveMaxPool2dTilingData) | ||
| 80 | +TILING_DATA_FIELD_DEF(int64_t, N); | ||
| 81 | +TILING_DATA_FIELD_DEF(int64_t, C); | ||
| 82 | +TILING_DATA_FIELD_DEF(int64_t, Hi); | ||
| 83 | +TILING_DATA_FIELD_DEF(int64_t, Wi); | ||
| 84 | +TILING_DATA_FIELD_DEF(int64_t, Ho); | ||
| 85 | +TILING_DATA_FIELD_DEF(int64_t, Wo); | ||
| 86 | +TILING_DATA_FIELD_DEF(int64_t, coreNums); | ||
| 87 | +TILING_DATA_FIELD_DEF(int64_t, useCoreNum); | ||
| 88 | +TILING_DATA_FIELD_DEF(int64_t, totalIdx); | ||
| 89 | +TILING_DATA_FIELD_DEF(int64_t, blockFactor); | ||
| 90 | +TILING_DATA_FIELD_DEF(int64_t, blockTail); | ||
| 91 | +TILING_DATA_FIELD_DEF(int64_t, ncFactor); | ||
| 92 | +TILING_DATA_FIELD_DEF(int64_t, hoFactor); | ||
| 93 | +TILING_DATA_FIELD_DEF(int64_t, woFactor); | ||
| 94 | +TILING_DATA_FIELD_DEF(int64_t, ncOuter); | ||
| 95 | +TILING_DATA_FIELD_DEF(int64_t, hoOuter); | ||
| 96 | +TILING_DATA_FIELD_DEF(int64_t, woOuter); | ||
| 97 | +TILING_DATA_FIELD_DEF(int64_t, ncTail); | ||
| 98 | +TILING_DATA_FIELD_DEF(int64_t, hoTail); | ||
| 99 | +TILING_DATA_FIELD_DEF(int64_t, woTail); | ||
| 100 | + | ||
| 101 | +TILING_DATA_FIELD_DEF(int64_t, threadNums); | ||
| 102 | +TILING_DATA_FIELD_DEF(int64_t, blockNums); | ||
| 103 | +TILING_DATA_FIELD_DEF(int64_t, kMaxSizeH); | ||
| 104 | +TILING_DATA_FIELD_DEF(int64_t, kMaxSizeW); | ||
| 105 | +END_TILING_DATA_DEF; | ||
| 106 | + | ||
| 107 | +REGISTER_TILING_DATA_CLASS(AdaptiveMaxPool2d, AdaptiveMaxPool2dTilingData); | ||
| 108 | + | ||
| 109 | + | ||
| 110 | +class AdaMaxPool2dBaseTiling : public TilingBaseClass { | ||
| 111 | +public: | ||
| 112 | + explicit AdaMaxPool2dBaseTiling(gert::TilingContext* context) : TilingBaseClass(context) | ||
| 113 | + {} | ||
| 114 | + | ||
| 115 | + ~AdaMaxPool2dBaseTiling() override | ||
| 116 | + {} | ||
| 117 | + | ||
| 118 | +protected: | ||
| 119 | + bool IsCapable() override; | ||
| 120 | + ge::graphStatus GetPlatformInfo() override; | ||
| 121 | + ge::graphStatus GetShapeAttrsInfo() override; | ||
| 122 | + ge::graphStatus DoOpTiling() override; | ||
| 123 | + ge::graphStatus DoLibApiTiling() override; | ||
| 124 | + uint64_t GetTilingKey() const override; | ||
| 125 | + ge::graphStatus GetWorkspaceSize() override; | ||
| 126 | + ge::graphStatus PostTiling() override; | ||
| 127 | + | ||
| 128 | +public: | ||
| 129 | + ge::DataType dtype = ge::DataType::DT_FLOAT; | ||
| 130 | + size_t sysWorkspaceSize_ = 0; | ||
| 131 | + InputInfo input_; | ||
| 132 | + CalculateInfo calInfo_; | ||
| 133 | +}; | ||
| 134 | +} // namespace optiling | ||
| 135 | + | ||
| 136 | + | ||
| @@ -0,0 +1,317 @@ | |||
| 1 | +{ | ||
| 2 | + "op_type": "AdaptiveMaxPool2d", | ||
| 3 | + "op_list": [ | ||
| 4 | + { | ||
| 5 | + "bin_filename": "AdaptiveMaxPool2d_be522d0caeae375632e98b1a501019f3", | ||
| 6 | + "inputs": [ | ||
| 7 | + { | ||
| 8 | + "name": "x", | ||
| 9 | + "index": 0, | ||
| 10 | + "dtype": "float32", | ||
| 11 | + "format": "ND", | ||
| 12 | + "paramType": "required", | ||
| 13 | + "shape": [ | ||
| 14 | + -2 | ||
| 15 | + ], | ||
| 16 | + "format_match_mode": "FormatAgnostic" | ||
| 17 | + } | ||
| 18 | + ], | ||
| 19 | + "outputs": [ | ||
| 20 | + { | ||
| 21 | + "name": "y", | ||
| 22 | + "index": 0, | ||
| 23 | + "dtype": "float32", | ||
| 24 | + "format": "ND", | ||
| 25 | + "paramType": "required", | ||
| 26 | + "shape": [ | ||
| 27 | + -2 | ||
| 28 | + ], | ||
| 29 | + "format_match_mode": "FormatAgnostic" | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + "name": "indices", | ||
| 33 | + "index": 1, | ||
| 34 | + "dtype": "int32", | ||
| 35 | + "format": "ND", | ||
| 36 | + "paramType": "required", | ||
| 37 | + "shape": [ | ||
| 38 | + -2 | ||
| 39 | + ], | ||
| 40 | + "format_match_mode": "FormatAgnostic" | ||
| 41 | + } | ||
| 42 | + ], | ||
| 43 | + "attrs": [ | ||
| 44 | + { | ||
| 45 | + "name": "output_size", | ||
| 46 | + "dtype": "list_int", | ||
| 47 | + "value": [] | ||
| 48 | + }, | ||
| 49 | + { | ||
| 50 | + "name": "indices_dtype", | ||
| 51 | + "dtype": "int", | ||
| 52 | + "value": 0 | ||
| 53 | + } | ||
| 54 | + ] | ||
| 55 | + }, | ||
| 56 | + { | ||
| 57 | + "bin_filename": "AdaptiveMaxPool2d_95c63351e3c3a70b21f41be389ff8ff4", | ||
| 58 | + "inputs": [ | ||
| 59 | + { | ||
| 60 | + "name": "x", | ||
| 61 | + "index": 0, | ||
| 62 | + "dtype": "bfloat16", | ||
| 63 | + "format": "ND", | ||
| 64 | + "paramType": "required", | ||
| 65 | + "shape": [ | ||
| 66 | + -2 | ||
| 67 | + ], | ||
| 68 | + "format_match_mode": "FormatAgnostic" | ||
| 69 | + } | ||
| 70 | + ], | ||
| 71 | + "outputs": [ | ||
| 72 | + { | ||
| 73 | + "name": "y", | ||
| 74 | + "index": 0, | ||
| 75 | + "dtype": "bfloat16", | ||
| 76 | + "format": "ND", | ||
| 77 | + "paramType": "required", | ||
| 78 | + "shape": [ | ||
| 79 | + -2 | ||
| 80 | + ], | ||
| 81 | + "format_match_mode": "FormatAgnostic" | ||
| 82 | + }, | ||
| 83 | + { | ||
| 84 | + "name": "indices", | ||
| 85 | + "index": 1, | ||
| 86 | + "dtype": "int32", | ||
| 87 | + "format": "ND", | ||
| 88 | + "paramType": "required", | ||
| 89 | + "shape": [ | ||
| 90 | + -2 | ||
| 91 | + ], | ||
| 92 | + "format_match_mode": "FormatAgnostic" | ||
| 93 | + } | ||
| 94 | + ], | ||
| 95 | + "attrs": [ | ||
| 96 | + { | ||
| 97 | + "name": "output_size", | ||
| 98 | + "dtype": "list_int", | ||
| 99 | + "value": [] | ||
| 100 | + }, | ||
| 101 | + { | ||
| 102 | + "name": "indices_dtype", | ||
| 103 | + "dtype": "int", | ||
| 104 | + "value": 0 | ||
| 105 | + } | ||
| 106 | + ] | ||
| 107 | + }, | ||
| 108 | + { | ||
| 109 | + "bin_filename": "AdaptiveMaxPool2d_d18392463d762fbcc48f41e994d30719", | ||
| 110 | + "inputs": [ | ||
| 111 | + { | ||
| 112 | + "name": "x", | ||
| 113 | + "index": 0, | ||
| 114 | + "dtype": "float16", | ||
| 115 | + "format": "ND", | ||
| 116 | + "paramType": "required", | ||
| 117 | + "shape": [ | ||
| 118 | + -2 | ||
| 119 | + ], | ||
| 120 | + "format_match_mode": "FormatAgnostic" | ||
| 121 | + } | ||
| 122 | + ], | ||
| 123 | + "outputs": [ | ||
| 124 | + { | ||
| 125 | + "name": "y", | ||
| 126 | + "index": 0, | ||
| 127 | + "dtype": "float16", | ||
| 128 | + "format": "ND", | ||
| 129 | + "paramType": "required", | ||
| 130 | + "shape": [ | ||
| 131 | + -2 | ||
| 132 | + ], | ||
| 133 | + "format_match_mode": "FormatAgnostic" | ||
| 134 | + }, | ||
| 135 | + { | ||
| 136 | + "name": "indices", | ||
| 137 | + "index": 1, | ||
| 138 | + "dtype": "int64", | ||
| 139 | + "format": "ND", | ||
| 140 | + "paramType": "required", | ||
| 141 | + "shape": [ | ||
| 142 | + -2 | ||
| 143 | + ], | ||
| 144 | + "format_match_mode": "FormatAgnostic" | ||
| 145 | + } | ||
| 146 | + ], | ||
| 147 | + "attrs": [ | ||
| 148 | + { | ||
| 149 | + "name": "output_size", | ||
| 150 | + "dtype": "list_int", | ||
| 151 | + "value": [] | ||
| 152 | + }, | ||
| 153 | + { | ||
| 154 | + "name": "indices_dtype", | ||
| 155 | + "dtype": "int", | ||
| 156 | + "value": 0 | ||
| 157 | + } | ||
| 158 | + ] | ||
| 159 | + }, | ||
| 160 | + { | ||
| 161 | + "bin_filename": "AdaptiveMaxPool2d_946b3699e34bac16354098363baf0f3c", | ||
| 162 | + "inputs": [ | ||
| 163 | + { | ||
| 164 | + "name": "x", | ||
| 165 | + "index": 0, | ||
| 166 | + "dtype": "bfloat16", | ||
| 167 | + "format": "ND", | ||
| 168 | + "paramType": "required", | ||
| 169 | + "shape": [ | ||
| 170 | + -2 | ||
| 171 | + ], | ||
| 172 | + "format_match_mode": "FormatAgnostic" | ||
| 173 | + } | ||
| 174 | + ], | ||
| 175 | + "outputs": [ | ||
| 176 | + { | ||
| 177 | + "name": "y", | ||
| 178 | + "index": 0, | ||
| 179 | + "dtype": "bfloat16", | ||
| 180 | + "format": "ND", | ||
| 181 | + "paramType": "required", | ||
| 182 | + "shape": [ | ||
| 183 | + -2 | ||
| 184 | + ], | ||
| 185 | + "format_match_mode": "FormatAgnostic" | ||
| 186 | + }, | ||
| 187 | + { | ||
| 188 | + "name": "indices", | ||
| 189 | + "index": 1, | ||
| 190 | + "dtype": "int64", | ||
| 191 | + "format": "ND", | ||
| 192 | + "paramType": "required", | ||
| 193 | + "shape": [ | ||
| 194 | + -2 | ||
| 195 | + ], | ||
| 196 | + "format_match_mode": "FormatAgnostic" | ||
| 197 | + } | ||
| 198 | + ], | ||
| 199 | + "attrs": [ | ||
| 200 | + { | ||
| 201 | + "name": "output_size", | ||
| 202 | + "dtype": "list_int", | ||
| 203 | + "value": [] | ||
| 204 | + }, | ||
| 205 | + { | ||
| 206 | + "name": "indices_dtype", | ||
| 207 | + "dtype": "int", | ||
| 208 | + "value": 0 | ||
| 209 | + } | ||
| 210 | + ] | ||
| 211 | + }, | ||
| 212 | + { | ||
| 213 | + "bin_filename": "AdaptiveMaxPool2d_3b64a0aab8fee8a04f831218e79592ba", | ||
| 214 | + "inputs": [ | ||
| 215 | + { | ||
| 216 | + "name": "x", | ||
| 217 | + "index": 0, | ||
| 218 | + "dtype": "float32", | ||
| 219 | + "format": "ND", | ||
| 220 | + "paramType": "required", | ||
| 221 | + "shape": [ | ||
| 222 | + -2 | ||
| 223 | + ], | ||
| 224 | + "format_match_mode": "FormatAgnostic" | ||
| 225 | + } | ||
| 226 | + ], | ||
| 227 | + "outputs": [ | ||
| 228 | + { | ||
| 229 | + "name": "y", | ||
| 230 | + "index": 0, | ||
| 231 | + "dtype": "float32", | ||
| 232 | + "format": "ND", | ||
| 233 | + "paramType": "required", | ||
| 234 | + "shape": [ | ||
| 235 | + -2 | ||
| 236 | + ], | ||
| 237 | + "format_match_mode": "FormatAgnostic" | ||
| 238 | + }, | ||
| 239 | + { | ||
| 240 | + "name": "indices", | ||
| 241 | + "index": 1, | ||
| 242 | + "dtype": "int64", | ||
| 243 | + "format": "ND", | ||
| 244 | + "paramType": "required", | ||
| 245 | + "shape": [ | ||
| 246 | + -2 | ||
| 247 | + ], | ||
| 248 | + "format_match_mode": "FormatAgnostic" | ||
| 249 | + } | ||
| 250 | + ], | ||
| 251 | + "attrs": [ | ||
| 252 | + { | ||
| 253 | + "name": "output_size", | ||
| 254 | + "dtype": "list_int", | ||
| 255 | + "value": [] | ||
| 256 | + }, | ||
| 257 | + { | ||
| 258 | + "name": "indices_dtype", | ||
| 259 | + "dtype": "int", | ||
| 260 | + "value": 0 | ||
| 261 | + } | ||
| 262 | + ] | ||
| 263 | + }, | ||
| 264 | + { | ||
| 265 | + "bin_filename": "AdaptiveMaxPool2d_4a1e4f3b6a197926a3518a0bcd1d53f9", | ||
| 266 | + "inputs": [ | ||
| 267 | + { | ||
| 268 | + "name": "x", | ||
| 269 | + "index": 0, | ||
| 270 | + "dtype": "float16", | ||
| 271 | + "format": "ND", | ||
| 272 | + "paramType": "required", | ||
| 273 | + "shape": [ | ||
| 274 | + -2 | ||
| 275 | + ], | ||
| 276 | + "format_match_mode": "FormatAgnostic" | ||
| 277 | + } | ||
| 278 | + ], | ||
| 279 | + "outputs": [ | ||
| 280 | + { | ||
| 281 | + "name": "y", | ||
| 282 | + "index": 0, | ||
| 283 | + "dtype": "float16", | ||
| 284 | + "format": "ND", | ||
| 285 | + "paramType": "required", | ||
| 286 | + "shape": [ | ||
| 287 | + -2 | ||
| 288 | + ], | ||
| 289 | + "format_match_mode": "FormatAgnostic" | ||
| 290 | + }, | ||
| 291 | + { | ||
| 292 | + "name": "indices", | ||
| 293 | + "index": 1, | ||
| 294 | + "dtype": "int32", | ||
| 295 | + "format": "ND", | ||
| 296 | + "paramType": "required", | ||
| 297 | + "shape": [ | ||
| 298 | + -2 | ||
| 299 | + ], | ||
| 300 | + "format_match_mode": "FormatAgnostic" | ||
| 301 | + } | ||
| 302 | + ], | ||
| 303 | + "attrs": [ | ||
| 304 | + { | ||
| 305 | + "name": "output_size", | ||
| 306 | + "dtype": "list_int", | ||
| 307 | + "value": [] | ||
| 308 | + }, | ||
| 309 | + { | ||
| 310 | + "name": "indices_dtype", | ||
| 311 | + "dtype": "int", | ||
| 312 | + "value": 0 | ||
| 313 | + } | ||
| 314 | + ] | ||
| 315 | + } | ||
| 316 | + ] | ||
| 317 | +} | ||
| @@ -0,0 +1,13 @@ | |||
| 1 | +; 该文件主要影响 opc 工具 编译二进制kernel时, --simplified_key_mode 选项中填写的值,格式如下所示: | ||
| 2 | +; [某算子] | ||
| 3 | +; default=xx | ||
| 4 | +; ascendxx=xx | ||
| 5 | +; 其中,default为默认mode,ascendxx为可选mode,如果不同芯片有差异化要求时,需要配置; | ||
| 6 | +; 1)如果没有配置:非ascendC算子继续按空处理,即opc编译命令中不添加 --simplified_key_mode 选项,AscendC算子按照 simplified_key_mode=0 处理 | ||
| 7 | +; 2)如果仅有default配置:各个版本按default配置 | ||
| 8 | +; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 | ||
| 9 | +; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 | ||
| 10 | +; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 | ||
| 11 | +; 6)是否是AscendC算子,由 ops/build-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 | ||
| 12 | +[AdaptiveMaxPool2d] | ||
| 13 | +default=0 | ||
| @@ -0,0 +1,226 @@ | |||
| 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 max_pool2d_with_argmax_v2_simt_tiling.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | +using namespace ge; | ||
| 32 | + | ||
| 33 | +constexpr uint64_t CAL_KER_THRESHOLD = 10000; | ||
| 34 | +constexpr int64_t N_IDX = 0; | ||
| 35 | +constexpr int64_t C_IDX = 1; | ||
| 36 | +constexpr int64_t H_IDX = 2; | ||
| 37 | +constexpr int64_t W_IDX = 3; | ||
| 38 | + | ||
| 39 | +namespace optiling{ | ||
| 40 | + | ||
| 41 | +static const gert::Shape g_vec_1_shape = {1}; | ||
| 42 | + | ||
| 43 | +static const gert::Shape& EnsureNotScalar(const gert::Shape &inShape) { | ||
| 44 | + if (inShape.IsScalar()) { | ||
| 45 | + return g_vec_1_shape; | ||
| 46 | + } | ||
| 47 | + return inShape; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +bool AdaMaxPool2dTilingSIMT::IsCapable() | ||
| 51 | +{ | ||
| 52 | + return true; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +ge::graphStatus AdaMaxPool2dTilingSIMT::GetPlatformInfo() | ||
| 56 | +{ | ||
| 57 | + auto compileInfo = reinterpret_cast<const AdaptiveMaxPool2dCompileInfo*>(context_->GetCompileInfo()); | ||
| 58 | + OP_CHECK_NULL_WITH_CONTEXT(context_, compileInfo); | ||
| 59 | + coreNum_ = compileInfo->coreNum; | ||
| 60 | + OP_CHECK_IF(coreNum_ <= 0, OP_LOGE(context_, "GetPlatformInfo get corenum <= 0"), return ge::GRAPH_FAILED); | ||
| 61 | + sysWorkspaceSize_ = compileInfo->sysWorkspaceSize; | ||
| 62 | + return ge::GRAPH_SUCCESS; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +ge::graphStatus AdaMaxPool2dTilingSIMT::CheckPlatformAndGetShapes() { | ||
| 66 | + auto platformInfo = context_->GetPlatformInfo(); | ||
| 67 | + OP_CHECK_NULL_WITH_CONTEXT(context_, platformInfo); | ||
| 68 | + auto inputX = context_->GetInputShape(FIRPOS); | ||
| 69 | + OPS_CHECK_NULL_WITH_CONTEXT(context_, inputX); | ||
| 70 | + auto inputShape = EnsureNotScalar(inputX->GetStorageShape()); | ||
| 71 | + auto outX = context_->GetOutputShape(FIRPOS); | ||
| 72 | + OPS_CHECK_NULL_WITH_CONTEXT(context_, outX); | ||
| 73 | + auto outShape = EnsureNotScalar(outX->GetStorageShape()); | ||
| 74 | + auto indicesX = context_->GetOutputShape(SECPOS); | ||
| 75 | + OPS_CHECK_NULL_WITH_CONTEXT(context_, indicesX); | ||
| 76 | + if (inputShape.GetDimNum() != NCHW_DIMS) { | ||
| 77 | + VECTOR_INNER_ERR_REPORT_TILIING(context_->GetNodeName(), | ||
| 78 | + "AdaptiveMaxPool2d: input shape dim = %zu, should be equal 4", | ||
| 79 | + inputShape.GetDimNum()); | ||
| 80 | + return ge::GRAPH_FAILED; | ||
| 81 | + } | ||
| 82 | + OP_CHECK_IF( | ||
| 83 | + inputShape.GetDim(N_IDX) < 1 || inputShape.GetDim(C_IDX) < 1 || | ||
| 84 | + inputShape.GetDim(H_IDX) < 1 || inputShape.GetDim(W_IDX) < 1, | ||
| 85 | + OP_LOGE(context_->GetNodeName(), "Invalid shape. Maybe empty tensor."), return ge::GRAPH_FAILED); | ||
| 86 | + | ||
| 87 | + inputData.inputShape = | ||
| 88 | + array<uint64_t, NCHW_DIMS>{uint64_t(inputShape.GetDim(N_IDX)), uint64_t(inputShape.GetDim(C_IDX)), | ||
| 89 | + uint64_t(inputShape.GetDim(H_IDX)), uint64_t(inputShape.GetDim(W_IDX))}; | ||
| 90 | + inputData.outShape = | ||
| 91 | + array<uint64_t, NCHW_DIMS>{uint64_t(inputShape.GetDim(N_IDX)), uint64_t(inputShape.GetDim(C_IDX)), | ||
| 92 | + uint64_t(outShape.GetDim(H_IDX)), uint64_t(outShape.GetDim(W_IDX))}; | ||
| 93 | + | ||
| 94 | + return ge::GRAPH_SUCCESS; | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +ge::graphStatus AdaMaxPool2dTilingSIMT::CheckDataTypeAndAttrs() { | ||
| 98 | + auto inputDesc = context_->GetInputDesc(0); | ||
| 99 | + OPS_CHECK_NULL_WITH_CONTEXT(context_, inputDesc); | ||
| 100 | + dtype = inputDesc->GetDataType(); | ||
| 101 | + if (dtype != ge::DataType::DT_BF16 && dtype != ge::DataType::DT_FLOAT16 && dtype != ge::DataType::DT_FLOAT) { | ||
| 102 | + VECTOR_INNER_ERR_REPORT_TILIING(context_->GetNodeName(), | ||
| 103 | + "AdaptiveMaxPool2d: invalid dtype %s, should be BFloat16、Float16 or Float32", | ||
| 104 | + Ops::Base::ToString(dtype).c_str()); | ||
| 105 | + return ge::GRAPH_FAILED; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + auto indicesX = context_->GetOutputShape(SECPOS); | ||
| 109 | + OPS_CHECK_NULL_WITH_CONTEXT(context_, indicesX); | ||
| 110 | + auto indicesShape = EnsureNotScalar(indicesX->GetStorageShape()); | ||
| 111 | + if (indicesShape.GetDimNum() != NCHW_DIMS) { | ||
| 112 | + VECTOR_INNER_ERR_REPORT_TILIING(context_->GetNodeName(), | ||
| 113 | + "AdaptiveMaxPool2d: indices shape dim = %zu, should be 4", | ||
| 114 | + indicesShape.GetDimNum()); | ||
| 115 | + return ge::GRAPH_FAILED; | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + array<uint64_t, NCHW_DIMS> indicesArray{ | ||
| 119 | + uint64_t(indicesShape.GetDim(N_IDX)), | ||
| 120 | + uint64_t(indicesShape.GetDim(C_IDX)), | ||
| 121 | + uint64_t(indicesShape.GetDim(H_IDX)), | ||
| 122 | + uint64_t(indicesShape.GetDim(W_IDX)) | ||
| 123 | + }; | ||
| 124 | + if (indicesArray != inputData.outShape) { | ||
| 125 | + VECTOR_INNER_ERR_REPORT_TILIING(context_->GetNodeName(), | ||
| 126 | + "AdaptiveMaxPool2d: indices shape and values shape is different"); | ||
| 127 | + return ge::GRAPH_FAILED; | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + auto attrPtr = context_->GetAttrs(); | ||
| 131 | + OP_CHECK_NULL_WITH_CONTEXT(context_, attrPtr); | ||
| 132 | + auto outputSizePtr = attrPtr->GetAttrPointer<gert::ContinuousVector>(0); | ||
| 133 | + OP_CHECK_NULL_WITH_CONTEXT(context_, outputSizePtr); | ||
| 134 | + OP_CHECK_IF( | ||
| 135 | + outputSizePtr->GetSize() != DOUB, | ||
| 136 | + OP_LOGE(context_->GetNodeName(), "the size of outputsize only support 2"), | ||
| 137 | + return ge::GRAPH_FAILED); | ||
| 138 | + const int64_t* outputSize = static_cast<const int64_t*>(outputSizePtr->GetData()); | ||
| 139 | + OP_CHECK_IF( | ||
| 140 | + outputSize[0] <= 0 || outputSize[1] <= 0, | ||
| 141 | + OP_LOGE(context_->GetNodeName(), "the value of outputsize should > 0"), return ge::GRAPH_FAILED); | ||
| 142 | + | ||
| 143 | + return ge::GRAPH_SUCCESS; | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +ge::graphStatus AdaMaxPool2dTilingSIMT::GetShapeAttrsInfo() { | ||
| 147 | + auto status = CheckPlatformAndGetShapes(); | ||
| 148 | + if (status != ge::GRAPH_SUCCESS) return status; | ||
| 149 | + return CheckDataTypeAndAttrs(); | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +ge::graphStatus AdaMaxPool2dTilingSIMT::DoOpTiling() | ||
| 153 | +{ | ||
| 154 | + tiling.set_N(inputData.inputShape[N_DIM_]); | ||
| 155 | + tiling.set_C(inputData.inputShape[C_DIM_]); | ||
| 156 | + tiling.set_Hi(inputData.inputShape[H_DIM_]); | ||
| 157 | + tiling.set_Wi(inputData.inputShape[W_DIM_]); | ||
| 158 | + tiling.set_Ho(inputData.outShape[H_DIM_]); | ||
| 159 | + tiling.set_Wo(inputData.outShape[W_DIM_]); | ||
| 160 | + tiling.set_kMaxSizeH(inputData.kernelHMax); | ||
| 161 | + tiling.set_kMaxSizeW(inputData.kernelWMax); | ||
| 162 | + tiling.set_coreNums(0); | ||
| 163 | + tiling.set_useCoreNum(0); | ||
| 164 | + tiling.set_totalIdx(0); | ||
| 165 | + tiling.set_blockFactor(0); | ||
| 166 | + tiling.set_blockTail(0); | ||
| 167 | + tiling.set_ncFactor(0); | ||
| 168 | + tiling.set_hoFactor(0); | ||
| 169 | + tiling.set_woFactor(0); | ||
| 170 | + tiling.set_ncOuter(0); | ||
| 171 | + tiling.set_hoOuter(0); | ||
| 172 | + tiling.set_woOuter(0); | ||
| 173 | + tiling.set_ncTail(0); | ||
| 174 | + tiling.set_hoTail(0); | ||
| 175 | + tiling.set_woTail(0); | ||
| 176 | + int64_t outputDataCount = tiling.get_N() * tiling.get_C() * tiling.get_Hi() * tiling.get_Wi(); | ||
| 177 | + int64_t threads = std::min(outputDataCount, MAX_THREAD_NUM); | ||
| 178 | + int64_t blockNum = Ops::Base::CeilDiv(outputDataCount, threads); | ||
| 179 | + blockNum = std::min(blockNum, static_cast<int64_t>(coreNum_)); | ||
| 180 | + context_->SetBlockDim(blockNum); | ||
| 181 | + context_->SetTilingKey(GetTilingKey()); | ||
| 182 | + tiling.set_threadNums(threads); | ||
| 183 | + tiling.set_blockNums(blockNum); | ||
| 184 | + return ge::GRAPH_SUCCESS; | ||
| 185 | +} | ||
| 186 | + | ||
| 187 | +uint64_t AdaMaxPool2dTilingSIMT::GetTilingKey() const | ||
| 188 | +{ | ||
| 189 | + return 0; | ||
| 190 | +} | ||
| 191 | + | ||
| 192 | +ge::graphStatus AdaMaxPool2dTilingSIMT::GetWorkspaceSize() | ||
| 193 | +{ | ||
| 194 | + size_t* currentWorkspace = context_->GetWorkspaceSizes(1); | ||
| 195 | + OP_CHECK_NULL_WITH_CONTEXT(context_, currentWorkspace); | ||
| 196 | + currentWorkspace[0] = sysWorkspaceSize_; | ||
| 197 | + return ge::GRAPH_SUCCESS; | ||
| 198 | +} | ||
| 199 | + | ||
| 200 | +ge::graphStatus AdaMaxPool2dTilingSIMT::PostTiling() | ||
| 201 | +{ | ||
| 202 | + OP_CHECK_IF(context_->GetRawTilingData()->GetCapacity() < tiling.GetDataSize(), | ||
| 203 | + OP_LOGE(context_, "tiling data's[%zu] is larger than capacity[%zu].", tiling.GetDataSize(), | ||
| 204 | + context_->GetRawTilingData()->GetCapacity()), | ||
| 205 | + return ge::GRAPH_FAILED); | ||
| 206 | + tiling.SaveToBuffer(context_->GetRawTilingData()->GetData(), context_->GetRawTilingData()->GetCapacity()); | ||
| 207 | + context_->GetRawTilingData()->SetDataSize(tiling.GetDataSize()); | ||
| 208 | + return ge::GRAPH_SUCCESS; | ||
| 209 | +} | ||
| 210 | + | ||
| 211 | +void AdaMaxPool2dTilingSIMT::DumpTilingInfo() | ||
| 212 | +{ | ||
| 213 | + std::string str; | ||
| 214 | + str += " threadNums:" + std::to_string(tiling.get_threadNums()); | ||
| 215 | + str += " blockNums:" + std::to_string(tiling.get_blockNums()); | ||
| 216 | + str += " nDim:" + std::to_string(tiling.get_N()); | ||
| 217 | + str += " cDim:" + std::to_string(tiling.get_C()); | ||
| 218 | + str += " hInDim:" + std::to_string(tiling.get_Hi()); | ||
| 219 | + str += " wInDim:" + std::to_string(tiling.get_Wi()); | ||
| 220 | + str += " hOutDim:" + std::to_string(tiling.get_Ho()); | ||
| 221 | + str += " wOutDim:" + std::to_string(tiling.get_Wo()); | ||
| 222 | + str += " kMaxSizeH:" + std::to_string(tiling.get_kMaxSizeH()); | ||
| 223 | + str += " kMaxSizeW:" + std::to_string(tiling.get_kMaxSizeW()); | ||
| 224 | +} | ||
| 225 | +REGISTER_TILING_TEMPLATE("AdaptiveMaxPool2d", AdaMaxPool2dTilingSIMT, 0); | ||
| 226 | +} // namespace optiling | ||
| @@ -0,0 +1,33 @@ | |||
| 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 adaptive_max_pool2d.cpp | ||
| 13 | + * \brief adaptive_max_pool2d implied | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +using namespace AscendC; | ||
| 21 | + | ||
| 22 | +extern "C" __global__ __aicore__ void adaptive_max_pool2d( | ||
| 23 | + GM_ADDR x, GM_ADDR y, GM_ADDR indices, GM_ADDR workspace, GM_ADDR tiling) | ||
| 24 | +{ | ||
| 25 | + AscendC::TPipe pipeBase; | ||
| 26 | + KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_AIV_ONLY); | ||
| 27 | + GET_TILING_DATA(tilingData, tiling); | ||
| 28 | + if (TILING_KEY_IS(0)) { | ||
| 29 | + AdaptiveMaxPool2DWithSimt::AdaptiveMaxPool2DSimt<DTYPE_X, DTYPE_INDICES, int32_t, uint32_t> op(&pipeBase, &tilingData); | ||
| 30 | + op.Init(x, y, indices); | ||
| 31 | + op.Process(); | ||
| 32 | + } | ||
| 33 | +} | ||
| @@ -0,0 +1,227 @@ | |||
| 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 adaptive_max_pool2d_simt.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace AdaptiveMaxPool2DWithSimt{ | ||
| 29 | + using namespace AscendC; | ||
| 30 | + | ||
| 31 | + constexpr uint32_t THREAD_DIM = 1024; | ||
| 32 | + constexpr size_t PARAM_NUM = 4; | ||
| 33 | + constexpr static uint32_t DIV_HW_IDX = 0; | ||
| 34 | + constexpr static uint32_t DIV_H_IDX = 2; | ||
| 35 | + constexpr static uint32_t DIV_W_IDX = 4; | ||
| 36 | + | ||
| 37 | + template <typename DIV_T> | ||
| 38 | + __aicore__ __attribute__((always_inline)) inline static DIV_T startIndex(DIV_T outIdx, DIV_T magicOutLen, DIV_T shiftOutLen, DIV_T inLen) | ||
| 39 | + { | ||
| 40 | + DIV_T pStart = outIdx * inLen; | ||
| 41 | + return Simt::UintDiv<DIV_T>(pStart, magicOutLen, shiftOutLen); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + template <typename DIV_T> | ||
| 45 | + __aicore__ __attribute__((always_inline)) inline static DIV_T endIndex(DIV_T outIdx, DIV_T magicOutLen, DIV_T shiftOutLen, DIV_T inLen) | ||
| 46 | + { | ||
| 47 | + DIV_T pEnd = ((outIdx + 1) * inLen - 1); | ||
| 48 | + pEnd = Simt::UintDiv<DIV_T>(pEnd, magicOutLen, shiftOutLen); | ||
| 49 | + return pEnd + 1; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + template <typename VALUE_T, typename INDICES_T, typename FORMAT_T, typename DIV_T> | ||
| 53 | + __aicore__ __attribute__((always_inline)) inline static void executeFunc(FORMAT_T count, __gm__ VALUE_T* bottomData, | ||
| 54 | + FORMAT_T ncSize, FORMAT_T height, FORMAT_T width, | ||
| 55 | + FORMAT_T outputNc, FORMAT_T outputHeight, FORMAT_T outputWidth, | ||
| 56 | + __gm__ VALUE_T* valueData, __gm__ INDICES_T* indicesData, | ||
| 57 | + DIV_T magicHW, DIV_T shiftHW, DIV_T magicH, DIV_T shiftH, | ||
| 58 | + DIV_T magicW, DIV_T shiftW) { | ||
| 59 | + for (DIV_T index = Simt::GetBlockIdx() * Simt::GetThreadNum() + Simt::GetThreadIdx(); index < count; | ||
| 60 | + index += Simt::GetBlockNum() * Simt::GetThreadNum()) { | ||
| 61 | + // 计算NC索引 (index / (outputHeight * outputWidth)) | ||
| 62 | + DIV_T ncId = Simt::UintDiv<DIV_T>(index, magicHW, shiftHW); | ||
| 63 | + DIV_T indexIdx = index - ncId * outputNc; // 在当前NC内的偏移 | ||
| 64 | + | ||
| 65 | + // 计算高度和宽度索引 (indexIdx = h * outputWidth + w) | ||
| 66 | + DIV_T hId = Simt::UintDiv<DIV_T>(indexIdx, magicW, shiftW); | ||
| 67 | + DIV_T wId = indexIdx - hId * outputWidth; | ||
| 68 | + | ||
| 69 | + // 计算输入窗口的起始和结束位置 | ||
| 70 | + FORMAT_T startInH = startIndex<DIV_T>(hId, magicH, shiftH, height); | ||
| 71 | + FORMAT_T endInH = endIndex<DIV_T>(hId, magicH, shiftH, height); | ||
| 72 | + FORMAT_T startInW = startIndex<DIV_T>(wId, magicW, shiftW, width); | ||
| 73 | + FORMAT_T endInW = endIndex<DIV_T>(wId, magicW, shiftW, width); | ||
| 74 | + | ||
| 75 | + VALUE_T maxVal = AscendC::NumericLimits<VALUE_T>::NegativeInfinity(); | ||
| 76 | + FORMAT_T maxIdx = startInH * width + startInW; // 2D索引: h * width + w | ||
| 77 | + | ||
| 78 | + auto ncStartData = bottomData + ncId * ncSize; | ||
| 79 | + | ||
| 80 | + // 2D池化: 只在高度和宽度上滑动 | ||
| 81 | + for (FORMAT_T h = startInH; h < endInH; ++h) { | ||
| 82 | + for (FORMAT_T w = startInW; w < endInW; ++w) { | ||
| 83 | + FORMAT_T idxOffset = h * width + w; // 2D索引 | ||
| 84 | + VALUE_T val = static_cast<VALUE_T>(ncStartData[idxOffset]); | ||
| 85 | + if ((static_cast<VALUE_T>(val) > maxVal) || Simt::IsNan(static_cast<float>(val))) { | ||
| 86 | + maxIdx = idxOffset; | ||
| 87 | + maxVal = val; | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + valueData[index] = static_cast<VALUE_T>(maxVal); | ||
| 92 | + indicesData[index] = static_cast<INDICES_T>(maxIdx); | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | +template <typename VALUE_T, typename INDICES_T, typename FORMAT_T, typename DIV_T> | ||
| 97 | +class AdaptiveMaxPool2DSimt | ||
| 98 | +{ | ||
| 99 | +public: | ||
| 100 | + __aicore__ inline AdaptiveMaxPool2DSimt(TPipe *pipe, const AdaptiveMaxPool2dTilingData* __restrict tilingData) | ||
| 101 | + : pipe_(pipe), tilingData_(tilingData) | ||
| 102 | + { | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, GM_ADDR indices); | ||
| 106 | + __aicore__ inline void Process(); | ||
| 107 | + | ||
| 108 | +private: | ||
| 109 | + TPipe *pipe_; | ||
| 110 | + AscendC::GlobalTensor<VALUE_T> x_; | ||
| 111 | + AscendC::GlobalTensor<VALUE_T> y_; | ||
| 112 | + AscendC::GlobalTensor<INDICES_T> indices_; | ||
| 113 | + const AdaptiveMaxPool2dTilingData* tilingData_; | ||
| 114 | + TBuf<TPosition::VECCALC> paramBuf_; | ||
| 115 | +}; | ||
| 116 | + | ||
| 117 | +template <typename VALUE_T, typename INDICES_T, typename FORMAT_T, typename DIV_T> | ||
| 118 | +__aicore__ inline void AdaptiveMaxPool2DSimt<VALUE_T, INDICES_T, FORMAT_T, DIV_T>::Init(GM_ADDR x, GM_ADDR y, GM_ADDR indices) | ||
| 119 | +{ | ||
| 120 | + x_.SetGlobalBuffer((__gm__ VALUE_T*)(x)); | ||
| 121 | + y_.SetGlobalBuffer((__gm__ VALUE_T*)(y)); | ||
| 122 | + indices_.SetGlobalBuffer((__gm__ INDICES_T*)(indices)); | ||
| 123 | + if constexpr (!(std::is_same<FORMAT_T, int32_t>::value && std::is_same<DIV_T, uint32_t>::value)){ | ||
| 124 | + pipe_->InitBuffer(paramBuf_, PARAM_NUM * sizeof(DIV_T)); | ||
| 125 | + } | ||
| 126 | +} | ||
| 127 | + | ||
| 128 | +template <typename VALUE_T, typename INDICES_T, typename FORMAT_T, typename DIV_T> | ||
| 129 | +__simt_vf__ __aicore__ LAUNCH_BOUND(THREAD_DIM) inline void AdaptiveMaxPool2DNchwUb(FORMAT_T count, __gm__ VALUE_T* bottomData, | ||
| 130 | + FORMAT_T ncSize, FORMAT_T height, FORMAT_T width, | ||
| 131 | + FORMAT_T outputNc, FORMAT_T outputHeight, FORMAT_T outputWidth, | ||
| 132 | + __gm__ VALUE_T* valueData, __gm__ INDICES_T* indicesData, | ||
| 133 | + __ubuf__ DIV_T* SimtParam) | ||
| 134 | +{ | ||
| 135 | + DIV_T magicHW = SimtParam[DIV_HW_IDX]; | ||
| 136 | + DIV_T shiftHW = SimtParam[DIV_HW_IDX + 1]; | ||
| 137 | + DIV_T magicH = SimtParam[DIV_H_IDX]; | ||
| 138 | + DIV_T shiftH = SimtParam[DIV_H_IDX + 1]; | ||
| 139 | + DIV_T magicW = SimtParam[DIV_W_IDX]; | ||
| 140 | + DIV_T shiftW = SimtParam[DIV_W_IDX + 1]; | ||
| 141 | + executeFunc<VALUE_T, INDICES_T, FORMAT_T, DIV_T>(count, bottomData, ncSize, height, width, | ||
| 142 | + outputNc, outputHeight, outputWidth, | ||
| 143 | + valueData, indicesData, | ||
| 144 | + magicHW, shiftHW, magicH, shiftH, magicW, shiftW); | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | +template <typename VALUE_T, typename INDICES_T, typename FORMAT_T, typename DIV_T> | ||
| 148 | +__simt_vf__ __aicore__ LAUNCH_BOUND(THREAD_DIM) inline void AdaptiveMaxPool2DNchwFunc(FORMAT_T count, __gm__ VALUE_T* bottomData, | ||
| 149 | + FORMAT_T ncSize, FORMAT_T height, FORMAT_T width, | ||
| 150 | + FORMAT_T outputNc, FORMAT_T outputHeight, FORMAT_T outputWidth, | ||
| 151 | + __gm__ VALUE_T* valueData, __gm__ INDICES_T* indicesData, | ||
| 152 | + DIV_T magicHW, DIV_T shiftHW, DIV_T magicH, DIV_T shiftH, | ||
| 153 | + DIV_T magicW, DIV_T shiftW) | ||
| 154 | +{ | ||
| 155 | + executeFunc<VALUE_T, INDICES_T, FORMAT_T, DIV_T>(count, bottomData, ncSize, height, width, | ||
| 156 | + outputNc, outputHeight, outputWidth, | ||
| 157 | + valueData, indicesData, | ||
| 158 | + magicHW, shiftHW, magicH, shiftH, magicW, shiftW); | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +template <typename VALUE_T, typename INDICES_T, typename FORMAT_T, typename DIV_T> | ||
| 162 | +__aicore__ inline void AdaptiveMaxPool2DSimt<VALUE_T, INDICES_T, FORMAT_T, DIV_T>::Process() | ||
| 163 | +{ | ||
| 164 | + auto inputData = (__gm__ VALUE_T*)x_.GetPhyAddr(); | ||
| 165 | + auto outputData = (__gm__ VALUE_T*)y_.GetPhyAddr(); | ||
| 166 | + auto indicesData = (__gm__ INDICES_T*)indices_.GetPhyAddr(); | ||
| 167 | + | ||
| 168 | + DIV_T hw = tilingData_->Ho * tilingData_->Wo; // H * W | ||
| 169 | + FORMAT_T totalSize = hw * tilingData_->N * tilingData_->C; // N * C * H * W | ||
| 170 | + FORMAT_T ncSize = tilingData_->Hi * tilingData_->Wi; // 每个N*C的2D数据大小 | ||
| 171 | + | ||
| 172 | + DIV_T magicHW = 0; | ||
| 173 | + DIV_T shiftHW = 0; | ||
| 174 | + DIV_T magicH = 0; | ||
| 175 | + DIV_T shiftH = 0; | ||
| 176 | + DIV_T magicW = 0; | ||
| 177 | + DIV_T shiftW = 0; | ||
| 178 | + | ||
| 179 | + GetUintDivMagicAndShift<DIV_T>(magicHW, shiftHW, hw); | ||
| 180 | + GetUintDivMagicAndShift<DIV_T>(magicH, shiftH, tilingData_->Ho); | ||
| 181 | + GetUintDivMagicAndShift<DIV_T>(magicW, shiftW, tilingData_->Wo); | ||
| 182 | + | ||
| 183 | + if constexpr (std::is_same<FORMAT_T, int32_t>::value && std::is_same<DIV_T, uint32_t>::value){ | ||
| 184 | + Simt::VF_CALL<AdaptiveMaxPool2DNchwFunc<VALUE_T, INDICES_T, FORMAT_T, DIV_T>>( | ||
| 185 | + Simt::Dim3(THREAD_DIM), | ||
| 186 | + static_cast<FORMAT_T>(totalSize), | ||
| 187 | + inputData, | ||
| 188 | + ncSize, | ||
| 189 | + static_cast<FORMAT_T>(tilingData_->Hi), | ||
| 190 | + static_cast<FORMAT_T>(tilingData_->Wi), | ||
| 191 | + static_cast<FORMAT_T>(hw), | ||
| 192 | + static_cast<FORMAT_T>(tilingData_->Ho), | ||
| 193 | + static_cast<FORMAT_T>(tilingData_->Wo), | ||
| 194 | + outputData, | ||
| 195 | + indicesData, | ||
| 196 | + magicHW, shiftHW, magicH, shiftH, magicW, shiftW | ||
| 197 | + ); | ||
| 198 | + } else { | ||
| 199 | + LocalTensor<DIV_T> SimtParam = paramBuf_.Get<DIV_T>(); | ||
| 200 | + SimtParam.SetValue(0, static_cast<DIV_T>(magicHW)); | ||
| 201 | + SimtParam.SetValue(1, static_cast<DIV_T>(shiftHW)); | ||
| 202 | + SimtParam.SetValue(DIV_H_IDX, static_cast<DIV_T>(magicH)); | ||
| 203 | + SimtParam.SetValue(DIV_H_IDX + 1, static_cast<DIV_T>(shiftH)); | ||
| 204 | + SimtParam.SetValue(DIV_W_IDX, static_cast<DIV_T>(magicW)); | ||
| 205 | + SimtParam.SetValue(DIV_W_IDX + 1, static_cast<DIV_T>(shiftW)); | ||
| 206 | + DataSyncBarrier<MemDsbT::UB>(); | ||
| 207 | + | ||
| 208 | + Simt::VF_CALL<AdaptiveMaxPool2DNchwUb<VALUE_T, INDICES_T, FORMAT_T, DIV_T>>( | ||
| 209 | + Simt::Dim3(THREAD_DIM), | ||
| 210 | + static_cast<FORMAT_T>(totalSize), | ||
| 211 | + inputData, | ||
| 212 | + ncSize, | ||
| 213 | + static_cast<FORMAT_T>(tilingData_->Hi), | ||
| 214 | + static_cast<FORMAT_T>(tilingData_->Wi), | ||
| 215 | + static_cast<FORMAT_T>(hw), | ||
| 216 | + static_cast<FORMAT_T>(tilingData_->Ho), | ||
| 217 | + static_cast<FORMAT_T>(tilingData_->Wo), | ||
| 218 | + outputData, | ||
| 219 | + indicesData, | ||
| 220 | + (__ubuf__ DIV_T*)SimtParam.GetPhyAddr() | ||
| 221 | + ); | ||
| 222 | + } | ||
| 223 | +} | ||
| 224 | + | ||
| 225 | +} | ||
| 226 | + | ||
| 227 | + | ||
| @@ -0,0 +1,18 @@ | |||
| 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 | +message(STATUS "=== Debug: start ops.pooling.adaptive_max_pool2d.tests.CMakeLists.txt ") | ||
| 12 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 13 | +message(STATUS "=== Debug: CURRENT_DIRS =${CURRENT_DIRS} ") | ||
| 14 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 15 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 16 | + add_subdirectory(${SUB_DIR}) | ||
| 17 | + endif() | ||
| 18 | +endforeach() | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify. | ||
| 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 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 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 12 | +if(UT_TEST_ALL OR OP_API_UT) | ||
| 13 | + add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | +endif() | ||


代码结构与可维护性: 日志信息中存在拼写错误:'beigin' 应为 'begin'。虽然不影响功能,但降低了代码的专业性和可读性。
问题类型: 代码结构与可维护性 文件路径:
pooling/adaptive_max_pool2d/op_api/adaptive_max_pool2d.cpp行号: 96 问题代码:OP_LOGI("beigin adaptive maxpool2d.\n");修改建议:
此评论由代码审查工具自动生成