已合并
feat: 新增BatchToSpaceND A5实现 #1943
zhanw_coding创建于 3月27日
feat: 新增BatchToSpaceND A5实现 #1943
已合并
共 23 个文件变更+7277-0
| @@ -0,0 +1,17 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 3 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 4 | +# This file is a part of the CANN Open Software. | ||
| 5 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 8 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +add_all_modules_sources( | ||
| 13 | + OPTYPE batch_to_space_nd | ||
| 14 | + ACLNNTYPE aclnn_exclude | ||
| 15 | + COMPUTE_UNIT ascend950 | ||
| 16 | + TILING_DIR arch35 | ||
| 17 | +) | ||
| @@ -0,0 +1,104 @@ | |||
| 1 | +# BatchToSpaceND | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +| 产品 | 是否支持 | | ||
| 6 | +| :----------------------------------------------------------- | :------: | | ||
| 7 | +| <term>Ascend 950PR/Ascend 950DT</term> | √ | | ||
| 8 | +| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ | | ||
| 9 | +| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ | | ||
| 10 | +| <term>Atlas 200I/500 A2 推理产品</term> | √ | | ||
| 11 | +| <term>Atlas 推理系列产品</term> | √ | | ||
| 12 | +| <term>Atlas 训练系列产品</term> | √ | | ||
C | |||
| 13 | + | ||
| 14 | +## 功能说明 | ||
| 15 | + | ||
| 16 | +- 算子功能:将批次维度的数据重新排列到空间维度,并裁剪空间维度。 | ||
| 17 | + | ||
| 18 | +- 功能描述: | ||
| 19 | + 该算子是 SpaceToBatchND 的逆操作。它首先将输入张量的批次维度按照指定的块形状(block_shape)重新排列到空间维度中,然后根据裁剪参数(crops)裁剪空间维度。具体来说,它将批次维度中的数据分散到空间维度中,从而增加空间维度的大小,同时减少批次维度的大小。 | ||
| 20 | + | ||
| 21 | +- 计算公式: | ||
| 22 | + 设输入张量 x 为 N 维,形状为 $[x_0, x_1, \ldots, x_{N-1}]$,block_shape 为 M 维 1D 张量 $[b_0, b_1, \ldots, b_{M-1}]$,crops 为 $M \times 2$ 的 2D 张量 $[[c_{00}, c_{01}], [c_{10}, c_{11}], \ldots, [c_{M-1,0}, c_{M-1,1}]]$,满足 $1 \leq M < N \leq 8$。 | ||
| 23 | + | ||
| 24 | + 输出张量 y 形状为 $[y_0, y_1, \ldots, y_{N-1}]$,计算方式如下: | ||
| 25 | + | ||
| 26 | + $$ | ||
| 27 | + y_i = \begin{cases} | ||
| 28 | + \frac{x_0}{\prod_{j=0}^{M-1} b_j}, & i = 0 \\ | ||
| 29 | + x_i \times b_{i-1} - c_{i-1,0} - c_{i-1,1}, & 1 \leq i \leq M \\ | ||
| 30 | + x_i, & M+1 \leq i \leq N-1 | ||
| 31 | + \end{cases} | ||
| 32 | + $$ | ||
| 33 | + | ||
| 34 | + 其中,$x_0$ 必须能够被 $\prod_{j=0}^{M-1} b_j$ 整除。 | ||
| 35 | + | ||
| 36 | +## 参数说明 | ||
| 37 | + | ||
| 38 | +<table style="undefined;table-layout: fixed; width: 1480px"> | ||
| 39 | + <colgroup> | ||
| 40 | + <col style="width: 177px"> | ||
| 41 | + <col style="width: 120px"> | ||
| 42 | + <col style="width: 273px"> | ||
| 43 | + <col style="width: 292px"> | ||
| 44 | + <col style="width: 152px"> | ||
| 45 | + </colgroup> | ||
| 46 | + <thead> | ||
| 47 | + <tr> | ||
| 48 | + <th>参数名</th> | ||
| 49 | + <th>输入/输出/属性</th> | ||
| 50 | + <th>描述</th> | ||
| 51 | + <th>数据类型</th> | ||
| 52 | + <th>数据格式</th> | ||
| 53 | + </tr> | ||
| 54 | + </thead> | ||
| 55 | + <tbody> | ||
| 56 | + <tr> | ||
| 57 | + <td>x</td> | ||
| 58 | + <td>输入</td> | ||
| 59 | + <td>表示输入张量,支持多种数据类型</td> | ||
| 60 | + <td>INT8、UINT8、INT16、UINT16、INT32、UINT32、INT64、UINT64、BF16、FLOAT16、FLOAT、DOUBLE、BOOL、COMPLEX32、COMPLEX64</td> | ||
| 61 | + <td>ND</td> | ||
| 62 | + </tr> | ||
| 63 | + <tr> | ||
| 64 | + <td>block_shape</td> | ||
| 65 | + <td>输入</td> | ||
| 66 | + <td>表示空间块的形状,1D张量,形状为[M],指定每个空间维度的块大小</td> | ||
| 67 | + <td>INT32、INT64</td> | ||
| 68 | + <td>-</td> | ||
| 69 | + </tr> | ||
| 70 | + <tr> | ||
| 71 | + <td>crops</td> | ||
| 72 | + <td>输入</td> | ||
| 73 | + <td>表示裁剪量,2D张量,形状为[M, 2],指定每个空间维度从顶部和底部(或左侧和右侧)裁剪的元素数量</td> | ||
| 74 | + <td>INT32、INT64</td> | ||
| 75 | + <td>-</td> | ||
| 76 | + </tr> | ||
| 77 | + <tr> | ||
| 78 | + <td>y</td> | ||
| 79 | + <td>输出</td> | ||
| 80 | + <td>表示输出张量,与输入x具有相同的数据类型。输出形状根据block_shape和crops进行计算</td> | ||
| 81 | + <td>与x一致</td> | ||
| 82 | + <td>ND</td> | ||
| 83 | + </tr> | ||
| 84 | + </tbody> | ||
| 85 | +</table> | ||
| 86 | + | ||
| 87 | +- <term>Atlas 训练系列产品</term>、<term>Atlas 推理系列产品</term>、<term>Atlas 200I/500 A2 推理产品</term>、<term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term>、<term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term>:不支持BOOL。 | ||
| 88 | + | ||
| 89 | +## 约束说明 | ||
| 90 | + | ||
| 91 | +1. 输入张量 x 的维度 N 必须满足 2 ≤ N ≤ 8。 | ||
| 92 | +2. block_shape 的维度 M 必须满足 1 ≤ M < N。 | ||
| 93 | +3. block_shape 的长度必须等于 crops 的第一维度长度。 | ||
| 94 | +4. crops 的形状必须为 [M, 2]。 | ||
| 95 | +5. 输入张量的第 0 维(batch 维度)必须能够被 block_shape 中所有元素的乘积整除。 | ||
| 96 | +6. block_shape 中的每个元素必须大于 0。 | ||
| 97 | +7. crops 中的每个元素必须是非负整数。 | ||
| 98 | +8. 对于每个空间维度 i(i = 1, 2, ..., M),裁剪后的维度大小必须大于等于 0,即:x.shape[i] × block_shape[i-1] - crops[i-1][0] - crops[i-1][1] ≥ 0。 | ||
| 99 | + | ||
| 100 | +## 调用说明 | ||
| 101 | + | ||
| 102 | +| 调用方式 | 样例代码 | 说明 | | ||
| 103 | +| :-------- | :----------------------------------------------------------- | :----------------------------------------------------------- | | ||
| 104 | +| 图模式调用 | [test_geir_batch_to_space_nd](./examples/test_geir_batch_to_space_nd.cpp) | 通过[算子IR](./op_graph/batch_to_space_nd_proto.h)构图方式调用BatchToSpaceND算子。 | | ||
| @@ -0,0 +1,309 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +using namespace ge; | ||
| 37 | +using std::map; | ||
| 38 | +using std::string; | ||
| 39 | +using std::vector; | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + vector<int64_t> placeholder##intputIndex##_shape = inputShape; \ | ||
| 43 | + auto placeholder##intputIndex = op::Data("placeholder" + intputIndex).set_attr_index(0); \ | ||
| 44 | + TensorDesc placeholder##intputIndex##_desc = \ | ||
| 45 | + TensorDesc(ge::Shape(placeholder##intputIndex##_shape), FORMAT_ND, intputDtype); \ | ||
| 46 | + placeholder##intputIndex##_desc.SetPlacement(ge::kPlacementHost); \ | ||
| 47 | + placeholder##intputIndex##_desc.SetFormat(FORMAT_ND); \ | ||
| 48 | + Tensor tensor_placeholder##intputIndex; \ | ||
| 49 | + ret = GenSequenceData( \ | ||
| 50 | + placeholder##intputIndex##_shape, tensor_placeholder##intputIndex, placeholder##intputIndex##_desc, \ | ||
| 51 | + intputDtype); \ | ||
| 52 | + if (ret != SUCCESS) { \ | ||
| 53 | + printf("%s - ERROR - [XIR]: Generate input data failed\n", GetTime().c_str()); \ | ||
| 54 | + return FAILED; \ | ||
| 55 | + } \ | ||
| 56 | + placeholder##intputIndex.update_input_desc_x(placeholder##intputIndex##_desc); \ | ||
| 57 | + input.push_back(tensor_placeholder##intputIndex); \ | ||
| 58 | + graph.AddOp(placeholder##intputIndex); \ | ||
| 59 | + node.set_input_##intputName(placeholder##intputIndex); \ | ||
| 60 | + inputs.push_back(placeholder##intputIndex); | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + vector<int64_t> placeholder##intputIndex##_shape = inputShape; \ | ||
| 64 | + auto placeholder##intputIndex = op::Data("placeholder" + intputIndex).set_attr_index(0); \ | ||
| 65 | + TensorDesc placeholder##intputIndex##_desc = \ | ||
| 66 | + TensorDesc(ge::Shape(placeholder##intputIndex##_shape), FORMAT_ND, intputDtype); \ | ||
| 67 | + placeholder##intputIndex##_desc.SetPlacement(ge::kPlacementHost); \ | ||
| 68 | + placeholder##intputIndex##_desc.SetFormat(FORMAT_ND); \ | ||
| 69 | + Tensor tensor_placeholder##intputIndex; \ | ||
| 70 | + ret = GenOnesData( \ | ||
| 71 | + placeholder##intputIndex##_shape, tensor_placeholder##intputIndex, placeholder##intputIndex##_desc, \ | ||
| 72 | + intputDtype, value); \ | ||
| 73 | + if (ret != SUCCESS) { \ | ||
| 74 | + printf("%s - ERROR - [XIR]: Generate input data failed\n", GetTime().c_str()); \ | ||
| 75 | + return FAILED; \ | ||
| 76 | + } \ | ||
| 77 | + placeholder##intputIndex.update_input_desc_x(placeholder##intputIndex##_desc); \ | ||
| 78 | + input.push_back(tensor_placeholder##intputIndex); \ | ||
| 79 | + graph.AddOp(placeholder##intputIndex); \ | ||
| 80 | + node.set_input_##intputName(placeholder##intputIndex); \ | ||
| 81 | + inputs.push_back(placeholder##intputIndex); | ||
| 82 | + | ||
| 83 | + | ||
| 84 | + TensorDesc outputName##outputIndex##_desc = TensorDesc(ge::Shape(outputShape), FORMAT_ND, outputDtype); \ | ||
| 85 | + node.update_output_desc_##outputName(outputName##outputIndex##_desc); | ||
| 86 | + | ||
| 87 | + | ||
| 88 | + do { \ | ||
| 89 | + printf(message, ##__VA_ARGS__); \ | ||
| 90 | + } while (0) | ||
| 91 | + | ||
| 92 | +string GetTime() | ||
| 93 | +{ | ||
| 94 | + time_t timep; | ||
| 95 | + time(&timep); | ||
| 96 | + char tmp[64]; | ||
| 97 | + strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S,000", localtime(&timep)); | ||
| 98 | + return tmp; | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +uint32_t GetDataTypeSize(DataType dt) | ||
| 102 | +{ | ||
| 103 | + uint32_t dilation = 1; | ||
| 104 | + uint32_t oneByte = 1; | ||
| 105 | + uint32_t twoByte = 2; | ||
| 106 | + uint32_t fourByte = 4; | ||
| 107 | + uint32_t eightByte = 8; | ||
| 108 | + | ||
| 109 | + if (dt == ge::DT_FLOAT) { | ||
| 110 | + dilation = fourByte; | ||
| 111 | + } else if (dt == ge::DT_FLOAT16) { | ||
| 112 | + dilation = twoByte; | ||
| 113 | + } else if (dt == ge::DT_BF16) { | ||
| 114 | + dilation = twoByte; | ||
| 115 | + } else if (dt == ge::DT_INT16) { | ||
| 116 | + dilation = twoByte; | ||
| 117 | + } else if (dt == ge::DT_UINT16) { | ||
| 118 | + dilation = twoByte; | ||
| 119 | + } else if (dt == ge::DT_INT32) { | ||
| 120 | + dilation = fourByte; | ||
| 121 | + } else if (dt == ge::DT_UINT32) { | ||
| 122 | + dilation = fourByte; | ||
| 123 | + } else if (dt == ge::DT_INT64) { | ||
| 124 | + dilation = eightByte; | ||
| 125 | + } else if (dt == ge::DT_UINT64) { | ||
| 126 | + dilation = eightByte; | ||
| 127 | + } else if (dt == ge::DT_INT8) { | ||
| 128 | + dilation = oneByte; | ||
| 129 | + } | ||
| 130 | + return dilation; | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +int32_t GenSequenceData(vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& input_tensor_desc, DataType data_type) | ||
| 134 | +{ | ||
| 135 | + input_tensor_desc.SetRealDimCnt(shapes.size()); | ||
| 136 | + size_t size = 1; | ||
| 137 | + for (uint32_t i = 0; i < shapes.size(); i++) { | ||
| 138 | + size *= shapes[i]; | ||
| 139 | + } | ||
| 140 | + uint32_t data_len = size * GetDataTypeSize(data_type); | ||
| 141 | + int32_t* pData = new (std::nothrow) int32_t[data_len]; | ||
| 142 | + int value = 0; | ||
| 143 | + for (uint32_t i = 0; i < size; ++i) { | ||
| 144 | + *(pData + i) = value++; | ||
| 145 | + } | ||
| 146 | + input_tensor = Tensor(input_tensor_desc, reinterpret_cast<uint8_t*>(pData), data_len); | ||
| 147 | + return SUCCESS; | ||
| 148 | +} | ||
| 149 | + | ||
| 150 | +int32_t GenOnesData( | ||
| 151 | + vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& input_tensor_desc, DataType data_type, | ||
| 152 | + const vector<int32_t>& value) | ||
| 153 | +{ | ||
| 154 | + input_tensor_desc.SetRealDimCnt(shapes.size()); | ||
| 155 | + size_t size = 1; | ||
| 156 | + for (uint32_t i = 0; i < shapes.size(); i++) { | ||
| 157 | + size *= shapes[i]; | ||
| 158 | + } | ||
| 159 | + uint32_t data_len = size * GetDataTypeSize(data_type); | ||
| 160 | + int32_t* pData = new (std::nothrow) int32_t[data_len]; | ||
| 161 | + for (uint32_t i = 0; i < size; ++i) { | ||
| 162 | + *(pData + i) = value[i]; | ||
| 163 | + } | ||
| 164 | + input_tensor = Tensor(input_tensor_desc, reinterpret_cast<uint8_t*>(pData), data_len); | ||
| 165 | + return SUCCESS; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +int32_t WriteDataToFile(string bin_file, uint64_t data_size, uint8_t* inputData) | ||
| 169 | +{ | ||
| 170 | + FILE* fp = fopen(bin_file.c_str(), "w"); | ||
| 171 | + fwrite(inputData, sizeof(uint8_t), data_size, fp); | ||
| 172 | + fclose(fp); | ||
| 173 | + return SUCCESS; | ||
| 174 | +} | ||
| 175 | + | ||
| 176 | +int CreateOppInGraph( | ||
| 177 | + DataType inDtype, std::vector<ge::Tensor>& input, std::vector<Operator>& inputs, std::vector<Operator>& outputs, | ||
| 178 | + Graph& graph) | ||
| 179 | +{ | ||
| 180 | + Status ret = SUCCESS; | ||
| 181 | + // 自定义代码:添加单算子定义到图中 | ||
| 182 | + auto node = op::BatchToSpaceND("node"); | ||
| 183 | + std::vector<int64_t> xShape = {4, 2, 3}; | ||
| 184 | + std::vector<int64_t> yShape = {2, 3, 3}; | ||
| 185 | + std::vector<int64_t> blockShapeShape = {1}; | ||
| 186 | + std::vector<int32_t> blockShapeValue = {2}; | ||
| 187 | + std::vector<int64_t> cropsShape = {1, 2}; | ||
| 188 | + std::vector<int32_t> cropsValue = {1, 0}; | ||
| 189 | + | ||
| 190 | + ADD_SEQUENCE_INPUT(1, x, inDtype, xShape); | ||
| 191 | + | ||
| 192 | + ADD_INT_INPUT(2, block_shape, DT_INT32, blockShapeShape, blockShapeValue); | ||
| 193 | + ADD_INT_INPUT(3, crops, DT_INT32, cropsShape, cropsValue); | ||
| 194 | + | ||
| 195 | + ADD_OUTPUT(1, y, inDtype, yShape); | ||
| 196 | + outputs.push_back(node); | ||
| 197 | + // 添加完毕 | ||
| 198 | + return SUCCESS; | ||
| 199 | +} | ||
| 200 | + | ||
| 201 | +int main(int argc, char* argv[]) | ||
| 202 | +{ | ||
| 203 | + const char* graph_name = "tc_ge_irrun_test"; | ||
| 204 | + Graph graph(graph_name); | ||
| 205 | + std::vector<ge::Tensor> input; | ||
| 206 | + | ||
| 207 | + printf("%s - INFO - [XIR]: Start to initialize ge using ge global options\n", GetTime().c_str()); | ||
| 208 | + std::map<AscendString, AscendString> global_options = {{"ge.exec.deviceId", "0"}, {"ge.graphRunMode", "1"}}; | ||
| 209 | + Status ret = ge::GEInitialize(global_options); | ||
| 210 | + if (ret != SUCCESS) { | ||
| 211 | + printf("%s - INFO - [XIR]: Initialize ge using ge global options failed\n", GetTime().c_str()); | ||
| 212 | + return FAILED; | ||
| 213 | + } | ||
| 214 | + printf("%s - INFO - [XIR]: Initialize ge using ge global options success\n", GetTime().c_str()); | ||
| 215 | + | ||
| 216 | + std::vector<Operator> inputs{}; | ||
| 217 | + std::vector<Operator> outputs{}; | ||
| 218 | + | ||
| 219 | + std::cout << argv[1] << std::endl; | ||
| 220 | + char* endptr; | ||
| 221 | + | ||
| 222 | + DataType inDtype = DT_INT32; | ||
| 223 | + std::cout << inDtype << std::endl; | ||
| 224 | + | ||
| 225 | + ret = CreateOppInGraph(inDtype, input, inputs, outputs, graph); | ||
| 226 | + if (ret != SUCCESS) { | ||
| 227 | + printf("%s - ERROR - [XIR]: Create ir session using build options failed\n", GetTime().c_str()); | ||
| 228 | + return FAILED; | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + if (!inputs.empty() && !outputs.empty()) { | ||
| 232 | + graph.SetInputs(inputs).SetOutputs(outputs); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + std::map<AscendString, AscendString> build_options = { | ||
| 236 | + | ||
| 237 | + }; | ||
| 238 | + printf("%s - INFO - [XIR]: Start to create ir session using build options\n", GetTime().c_str()); | ||
| 239 | + ge::Session* session = new Session(build_options); | ||
| 240 | + | ||
| 241 | + if (session == nullptr) { | ||
| 242 | + printf("%s - ERROR - [XIR]: Create ir session using build options failed\n", GetTime().c_str()); | ||
| 243 | + return FAILED; | ||
| 244 | + } | ||
| 245 | + printf("%s - INFO - [XIR]: Create ir session using build options success\n", GetTime().c_str()); | ||
| 246 | + printf("%s - INFO - [XIR]: Start to add compute graph to ir session\n", GetTime().c_str()); | ||
| 247 | + | ||
| 248 | + std::map<AscendString, AscendString> graph_options = { | ||
| 249 | + | ||
| 250 | + }; | ||
| 251 | + uint32_t graph_id = 0; | ||
| 252 | + ret = session->AddGraph(graph_id, graph, graph_options); | ||
| 253 | + | ||
| 254 | + printf("%s - INFO - [XIR]: Session add ir compute graph to ir session success\n", GetTime().c_str()); | ||
| 255 | + printf("%s - INFO - [XIR]: dump graph to txt\n", GetTime().c_str()); | ||
| 256 | + std::string file_path = "./dump"; | ||
| 257 | + aclgrphDumpGraph(graph, file_path.c_str(), file_path.length()); | ||
| 258 | + printf("%s - INFO - [XIR]: Start to run ir compute graph\n", GetTime().c_str()); | ||
| 259 | + std::vector<ge::Tensor> output; | ||
| 260 | + ret = session->RunGraph(graph_id, input, output); | ||
| 261 | + if (ret != SUCCESS) { | ||
| 262 | + printf("%s - INFO - [XIR]: Run graph failed\n", GetTime().c_str()); | ||
| 263 | + delete session; | ||
| 264 | + GEFinalize(); | ||
| 265 | + return FAILED; | ||
| 266 | + } | ||
| 267 | + printf("%s - INFO - [XIR]: Session run ir compute graph success\n", GetTime().c_str()); | ||
| 268 | + | ||
| 269 | + int input_num = input.size(); | ||
| 270 | + for (int i = 0; i < input_num; i++) { | ||
| 271 | + std::cout << "input " << i << " dtype : " << input[i].GetTensorDesc().GetDataType() << std::endl; | ||
| 272 | + string input_file = "./tc_ge_irrun_test_0008_npu_input_" + std::to_string(i) + ".bin"; | ||
| 273 | + uint8_t* input_data_i = input[i].GetData(); | ||
| 274 | + int64_t input_shape = input[i].GetTensorDesc().GetShape().GetShapeSize(); | ||
| 275 | + std::cout << "this is " << i << "th input, input shape size =" << input_shape << std::endl; | ||
| 276 | + uint32_t data_size = input_shape * GetDataTypeSize(input[i].GetTensorDesc().GetDataType()); | ||
| 277 | + WriteDataToFile((const char*)input_file.c_str(), data_size, input_data_i); | ||
| 278 | + } | ||
| 279 | + | ||
| 280 | + int output_num = output.size(); | ||
| 281 | + for (int i = 0; i < output_num; i++) { | ||
| 282 | + std::cout << "output " << i << " dtype : " << output[i].GetTensorDesc().GetDataType() << std::endl; | ||
| 283 | + string output_file = "./tc_ge_irrun_test_0008_npu_output_" + std::to_string(i) + ".bin"; | ||
| 284 | + uint8_t* output_data_i = output[i].GetData(); | ||
| 285 | + int64_t output_shape = output[i].GetTensorDesc().GetShape().GetShapeSize(); | ||
| 286 | + std::cout << "this is " << i << "th output, output shape size =" << output_shape << std::endl; | ||
| 287 | + uint32_t data_size = output_shape * GetDataTypeSize(output[i].GetTensorDesc().GetDataType()); | ||
| 288 | + WriteDataToFile((const char*)output_file.c_str(), data_size, output_data_i); | ||
| 289 | + int32_t* resultData = (int32_t*)output_data_i; | ||
| 290 | + for (int64_t j = 0; j < output_shape; j++) { | ||
| 291 | + LOG_PRINT("result[%ld] is: %u\n", j, resultData[j]); | ||
| 292 | + } | ||
| 293 | + } | ||
| 294 | + | ||
| 295 | + ge::AscendString error_msg = ge::GEGetErrorMsgV2(); | ||
| 296 | + std::string error_str(error_msg.GetString()); | ||
| 297 | + std::cout << "Error message: " << error_str << std::endl; | ||
| 298 | + ge::AscendString warning_msg = ge::GEGetWarningMsgV2(); | ||
| 299 | + std::string warning_str(warning_msg.GetString()); | ||
| 300 | + std::cout << "Warning message: " << warning_str << std::endl; | ||
| 301 | + printf("%s - INFO - [XIR]: Start to finalize ir graph session\n", GetTime().c_str()); | ||
| 302 | + ret = ge::GEFinalize(); | ||
| 303 | + if (ret != SUCCESS) { | ||
| 304 | + printf("%s - INFO - [XIR]: Finalize ir graph session failed\n", GetTime().c_str()); | ||
| 305 | + return FAILED; | ||
| 306 | + } | ||
| 307 | + printf("%s - INFO - [XIR]: Finalize ir graph session success\n", GetTime().c_str()); | ||
| 308 | + return SUCCESS; | ||
| 309 | +} | ||
| @@ -0,0 +1,50 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +namespace ge { | ||
| 17 | +/** | ||
| 18 | +* @brief Permutes data from batch into blocks of spatial data and then prunes them. | ||
| 19 | +* The values from the batch dimension are moved in spatial blocks to the height and width dimensions. | ||
| 20 | +* And then prunes the height and width dimensions. | ||
| 21 | + | ||
| 22 | +* @par Inputs: | ||
| 23 | +* @li x: A ND tensor, must be one of the following types: | ||
| 24 | +* float16, float32, double, int64, int32, uint8, uint16, uint32, uint64, int8, | ||
| 25 | +* int16, complex64, complex128, qint8, quint8, qint16, quint16, qint32, bfloat16. | ||
| 26 | +* @li block_shape: A 1D tensor with shape [M], support int32 or int64. | ||
| 27 | +* @li crops: A 2D tensor with shape [M, 2], support int32 or int64. \n | ||
| 28 | + | ||
| 29 | +* @par Outputs: | ||
| 30 | +* y: A ND tensor, the same type as "x". \n | ||
| 31 | + | ||
| 32 | +* @attention Constraints: | ||
| 33 | +* If N is 4 and M is 2: \n | ||
| 34 | +* The size of the first dimension of input "x" must be divisible by the product of all elements in block_shape. \n | ||
| 35 | +* "y" is a 4D shape [batch, height, width, depth], batch = x.shape[0] / (block_shape[0] * block_shape[1]), | ||
| 36 | +* depth = x.shape[3], height = height_pad - crop_top - crop_bottom, width = width_pad - crop_left - crop_right | ||
| 37 | +* where height_pad = x.shape[1] * block_shape[0], width_pad = x.shape[2] * block_shape[1], | ||
| 38 | +* crop_top = crops[0][0], crop_bottom = crops[0][1], crop_left = crops[1][0], crop_right = crops[1][1] | ||
| 39 | +*@par Third-party framework compatibility | ||
| 40 | +* Compatible with the TensorFlow operator BatchToSpaceND. | ||
| 41 | +*/ | ||
| 42 | +REG_OP(BatchToSpaceND) | ||
| 43 | + .INPUT(x, TensorType({BasicType(), DT_BOOL})) | ||
| 44 | + .INPUT(block_shape, TensorType::IndexNumberType()) | ||
| 45 | + .INPUT(crops, TensorType::IndexNumberType()) | ||
| 46 | + .OUTPUT(y, TensorType::BasicType()) | ||
| 47 | + .OP_END_FACTORY_REG(BatchToSpaceND) | ||
| 48 | +} // namespace ge | ||
| 49 | + | ||
| 50 | + | ||
| @@ -0,0 +1,784 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace optiling { | ||
| 23 | +// 属性、索引 | ||
| 24 | +static constexpr size_t INPUT_IDX_X = 0; | ||
| 25 | +static constexpr size_t INPUT_IDX_BLOCK_SHAPE = 1; | ||
| 26 | +static constexpr size_t INPUT_IDX_CROPS = 2; | ||
| 27 | +static constexpr size_t MIN_BLOCK_SHAPE_DIM = 1; | ||
| 28 | +static constexpr size_t MIN_X_RANK = MIN_BLOCK_SHAPE_DIM + 1; | ||
| 29 | +static constexpr size_t BLOCK_SHAPE_RANK = 1; | ||
| 30 | +static constexpr size_t CROPS_RANK = 2; | ||
| 31 | +static constexpr size_t CROPS_DIM_NUM_1 = 2; | ||
| 32 | + | ||
| 33 | +// 公共常量 | ||
| 34 | + | ||
| 35 | +// 大尾轴模板 常量 | ||
| 36 | +// BUFFER分割数量 | ||
| 37 | +static constexpr uint32_t LARGE_C_BUFFER_NUM = 2; | ||
| 38 | +static constexpr uint32_t LARGE_C_MAX_BUFFER_SIZE = 64 * 1024U; | ||
| 39 | +// 能切分的最外层的轴,正负数均可 | ||
| 40 | +static constexpr int32_t LARGE_C_OUTMOST_CUT_AXIS = -3; | ||
| 41 | + | ||
| 42 | +// 小尾轴模板 常量 | ||
| 43 | +// BUFFER分割数量 | ||
| 44 | +static constexpr uint32_t SMALL_C_BUFFER_NUM = 2; | ||
| 45 | +// 输入输出各分一半 | ||
| 46 | +static constexpr uint32_t SMALL_C_BUFFER_FACTOR = 2; | ||
| 47 | +// 最大UB大小 | ||
| 48 | +static constexpr uint32_t SMALL_C_MAX_BUFFER_SIZE = 64 * 1024U; | ||
| 49 | + | ||
| 50 | +// SIMT 常量 | ||
| 51 | +static constexpr size_t MIN_RANK_FOR_SIMT = 6; | ||
| 52 | +static constexpr int64_t MAX_UINT32_NUM = std::numeric_limits<uint32_t>::max(); | ||
| 53 | +static constexpr uint32_t SIMT_DCACHE_SIZE = 32 * 1024U; | ||
| 54 | +static constexpr uint32_t SIMT_MAX_UB_SIZE = 64 * 1024U; | ||
| 55 | +static constexpr uint32_t SIMT_BUFFER_NUM = 2; | ||
| 56 | +static constexpr uint32_t SIMT_THREAD_FACTOR = 1; | ||
| 57 | + | ||
| 58 | +class BatchToSpaceNDTiling { | ||
| 59 | +private: | ||
| 60 | + /* data */ | ||
| 61 | + // soc info | ||
| 62 | + uint32_t ubSize_{0}; | ||
| 63 | + uint32_t ubBlockSize_{0}; | ||
| 64 | + uint32_t coreNum_{0}; | ||
| 65 | + uint32_t cacheLineSize_{0}; | ||
| 66 | + int32_t ubBlockElements_{0}; | ||
| 67 | + int32_t cacheLineElements_{0}; | ||
| 68 | + uint32_t vRegSize_{0}; | ||
| 69 | + uint32_t simtMaxThreads_{0}; | ||
| 70 | + | ||
| 71 | + // tiling key param | ||
| 72 | + uint8_t mode_; | ||
| 73 | + uint8_t blockShapeDimNum_{0}; | ||
| 74 | + bool isBigShape_{false}; | ||
| 75 | + | ||
| 76 | + // 输入参数 | ||
| 77 | + int32_t dSize_{0}; | ||
| 78 | + int64_t xShapeSize_{0}; | ||
| 79 | + int64_t yShapeSize_{0}; | ||
| 80 | + size_t originBlockShapeDim_{0}; | ||
| 81 | + B2SNDInput originInput_; | ||
| 82 | + B2SNDInput mergedInput_; | ||
| 83 | + | ||
| 84 | + // 中间计算结果 | ||
| 85 | + // 实际核数 | ||
| 86 | + uint32_t realCoreNum_{0}; | ||
| 87 | + | ||
| 88 | + // tiling context | ||
| 89 | + gert::TilingContext* context_; | ||
| 90 | + | ||
| 91 | +public: | ||
| 92 | + explicit BatchToSpaceNDTiling(gert::TilingContext* context) : context_(context) {}; | ||
| 93 | + ~BatchToSpaceNDTiling() {}; | ||
| 94 | + | ||
| 95 | + ge::graphStatus DoTiling(); | ||
| 96 | + | ||
| 97 | +private: | ||
| 98 | + // 参数检查,数据获取 | ||
| 99 | + ge::graphStatus ParamCheck(); | ||
| 100 | + ge::graphStatus GetSocInfo(); | ||
| 101 | + ge::graphStatus CheckX(); | ||
| 102 | + ge::graphStatus CheckBlockShape(); | ||
| 103 | + ge::graphStatus CheckCrops(); | ||
| 104 | + ge::graphStatus CheckY(); | ||
| 105 | + ge::graphStatus MergeInput(); | ||
| 106 | + | ||
| 107 | + // tiling 计算 | ||
| 108 | + ge::graphStatus DoOpTiling(); | ||
| 109 | + ge::graphStatus Tiling4LargeC(); | ||
| 110 | + [[maybe_unused]] ge::graphStatus Tiling4SmallC(); | ||
| 111 | + ge::graphStatus Tiling4SIMT(); | ||
| 112 | + | ||
| 113 | + // 辅助函数 | ||
| 114 | + // LargeC | ||
| 115 | + ge::graphStatus moveAlignTilingBlock( | ||
| 116 | + uint32_t maxUBElements, const std::vector<uint64_t>& ubFactorAlign, const std::vector<uint64_t>& leftAlign, | ||
| 117 | + const std::vector<uint64_t>& dimValue, int32_t minCutAxis, B2SNDLargeCTilingData* tilingData); | ||
| 118 | + // SmallC | ||
| 119 | + void SmallCSetInput(B2SNDSmallCTilingData* tilingData, size_t yAxisPerm[]); | ||
| 120 | + void SmallCDoubleTiling(uint32_t inputElements, size_t yAxisPerm[], B2SNDSmallCTilingData* tilingData); | ||
| 121 | + // SIMT | ||
| 122 | + | ||
| 123 | + // 公共方法 | ||
| 124 | + template <typename T> | ||
| 125 | + inline T AlignBlockElement(T elementCount); | ||
| 126 | + | ||
| 127 | + // 打印 | ||
| 128 | + void ShowBaseTilingData(); | ||
| 129 | + void ShowLargeCTilingData(); | ||
| 130 | + void ShowSmallCTilingData(); | ||
| 131 | + void ShowSIMTTilingData(); | ||
| 132 | +}; | ||
| 133 | + | ||
| 134 | +ge::graphStatus BatchToSpaceNDTiling::DoTiling() | ||
| 135 | +{ | ||
| 136 | + // 校验属性 | ||
| 137 | + auto ret = ParamCheck(); | ||
| 138 | + OP_CHECK_IF(ret == ge::GRAPH_FAILED, OP_LOGE(context_, "DoTiling failed"), return ge::GRAPH_FAILED); | ||
| 139 | + | ||
| 140 | + // soc信息获取 | ||
| 141 | + ret = GetSocInfo(); | ||
| 142 | + OP_CHECK_IF(ret == ge::GRAPH_FAILED, OP_LOGE(context_, "DoTiling failed"), return ge::GRAPH_FAILED); | ||
| 143 | + | ||
| 144 | + ret = DoOpTiling(); | ||
| 145 | + OP_CHECK_IF(ret == ge::GRAPH_FAILED, OP_LOGE(context_, "DoTiling failed"), return ge::GRAPH_FAILED); | ||
| 146 | + | ||
| 147 | + const uint64_t tilingKey = GET_TPL_TILING_KEY(mode_, blockShapeDimNum_, isBigShape_); | ||
| 148 | + OP_LOGI( | ||
| 149 | + context_, "tilingKey is %lu, mode %u, blockShapeDimNum %u, isBigShape %d", tilingKey, mode_, blockShapeDimNum_, | ||
| 150 | + isBigShape_); | ||
| 151 | + context_->SetTilingKey(tilingKey); | ||
| 152 | + context_->SetBlockDim(realCoreNum_); | ||
| 153 | + size_t* workSpaceSize = context_->GetWorkspaceSizes(1); | ||
| 154 | + OP_CHECK_NULL_WITH_CONTEXT(context_, workSpaceSize); | ||
| 155 | + workSpaceSize[0] = 0; | ||
| 156 | + return ge::GRAPH_SUCCESS; | ||
| 157 | +} | ||
| 158 | + | ||
| 159 | +template <typename T> | ||
| 160 | +inline T BatchToSpaceNDTiling::AlignBlockElement(T elementCount) | ||
| 161 | +{ | ||
| 162 | + return Ops::Base::CeilAlign(elementCount, static_cast<T>(ubBlockElements_)); | ||
| 163 | +} | ||
| 164 | + | ||
| 165 | +template <typename T> | ||
| 166 | +static std::string ArrayToString(const T* v, size_t size) | ||
| 167 | +{ | ||
| 168 | + std::ostringstream oss; | ||
| 169 | + oss << "["; | ||
| 170 | + if (size > 0) { | ||
| 171 | + for (size_t i = 0; i < size - 1; ++i) { | ||
| 172 | + oss << v[i] << ", "; | ||
| 173 | + } | ||
| 174 | + oss << v[size - 1]; | ||
| 175 | + } | ||
| 176 | + oss << "]"; | ||
| 177 | + return oss.str(); | ||
| 178 | +} | ||
| 179 | + | ||
| 180 | +void BatchToSpaceNDTiling::ShowBaseTilingData() | ||
| 181 | +{ | ||
| 182 | + // 输入信息 | ||
| 183 | + OP_LOGI( | ||
| 184 | + context_, "input: x_shape %s, block_shape %s, crops %s, y_shape %s, data type size %d", | ||
| 185 | + ArrayToString(mergedInput_.inShape, mergedInput_.rank).c_str(), | ||
| 186 | + ArrayToString(mergedInput_.blockShape, mergedInput_.rank - 2).c_str(), | ||
| 187 | + ArrayToString(*mergedInput_.crops, (mergedInput_.rank - 2) * 2).c_str(), | ||
| 188 | + ArrayToString(mergedInput_.outShape, mergedInput_.rank).c_str(), dSize_); | ||
| 189 | + // soc 信息 | ||
| 190 | + OP_LOGI( | ||
| 191 | + context_, "soc info: ubSize %lu, coreNum %u, cacheLineSize %lu, ubBlockSize %lu, simtMaxThreads %lu", ubSize_, | ||
| 192 | + coreNum_, cacheLineSize_, ubBlockSize_, simtMaxThreads_); | ||
| 193 | + // 中间计算结果 | ||
| 194 | + OP_LOGI(context_, "middle data: realCoreNum %lu", realCoreNum_); | ||
| 195 | +} | ||
| 196 | + | ||
| 197 | +void BatchToSpaceNDTiling::ShowLargeCTilingData() | ||
| 198 | +{ | ||
| 199 | + ShowBaseTilingData(); | ||
| 200 | + auto tilingData = context_->GetTilingData<B2SNDLargeCTilingData>(); | ||
| 201 | + OP_LOGI( | ||
| 202 | + context_, "tiling data: ubAxis %lu, ubFactor %lu, outputBufferSize %lu", tilingData->ubAxis, | ||
| 203 | + tilingData->ubFactor, tilingData->outputBufferSize); | ||
| 204 | + OP_LOGI(context_, "\t: totalCount %u, perCoreCount %u", tilingData->totalCount, tilingData->perCoreCount); | ||
| 205 | +} | ||
| 206 | + | ||
| 207 | +void BatchToSpaceNDTiling::ShowSmallCTilingData() | ||
| 208 | +{ | ||
| 209 | + ShowBaseTilingData(); | ||
| 210 | + auto tilingData = context_->GetTilingData<B2SNDSmallCTilingData>(); | ||
| 211 | + OP_LOGI( | ||
| 212 | + context_, "tiling data: oriInShape %s, croppedInShape %s, crops %s", | ||
| 213 | + ArrayToString(tilingData->oriInShape, mergedInput_.rank + blockShapeDimNum_).c_str(), | ||
| 214 | + ArrayToString(tilingData->croppedInShape, mergedInput_.rank + blockShapeDimNum_).c_str(), | ||
| 215 | + ArrayToString(*tilingData->crops, blockShapeDimNum_ * 2).c_str()); | ||
| 216 | + OP_LOGI( | ||
| 217 | + context_, "\t: coreNum %u, inUbAxis %u, outUbAxis %u, inUbFactor %u, outUbFactor %u", tilingData->coreNum, | ||
| 218 | + tilingData->inUbAxis, tilingData->outUbAxis, tilingData->inUbFactor, tilingData->outUbFactor); | ||
| 219 | + OP_LOGI( | ||
| 220 | + context_, "\t: ubTotalCount %u, ubPerCount %u, ubTileSize %u", tilingData->ubTotalCount, tilingData->ubPerCount, | ||
| 221 | + tilingData->ubTileSize); | ||
| 222 | +} | ||
| 223 | + | ||
| 224 | +void BatchToSpaceNDTiling::ShowSIMTTilingData() | ||
| 225 | +{ | ||
| 226 | + ShowBaseTilingData(); | ||
| 227 | + auto tilingData = context_->GetTilingData<B2SNDSimtTilingData>(); | ||
| 228 | + OP_LOGI( | ||
| 229 | + context_, "tiling data: totalBlock %lu, mainCoreBlock %lu", tilingData->totalBlock, tilingData->mainCoreBlock); | ||
| 230 | + OP_LOGI( | ||
| 231 | + context_, "\t: needCoreNum %u, mainCoreNum %u, blockSize %u, tailBlockSize %u", tilingData->needCoreNum, | ||
| 232 | + tilingData->mainCoreNum, tilingData->blockSize, tilingData->tailBlockSize); | ||
| 233 | +} | ||
| 234 | + | ||
| 235 | +ge::graphStatus BatchToSpaceNDTiling::CheckX() | ||
| 236 | +{ | ||
| 237 | + // 获取x | ||
| 238 | + auto inputValueDesc = context_->GetInputDesc(INPUT_IDX_X); | ||
| 239 | + OP_CHECK_NULL_WITH_CONTEXT(context_, inputValueDesc); | ||
| 240 | + auto inputDataType = inputValueDesc->GetDataType(); | ||
| 241 | + dSize_ = ge::GetSizeByDataType(inputDataType); | ||
| 242 | + OP_CHECK_IF(dSize_ <= 0, OP_LOGE(context_, "data size should be positive"), return ge::GRAPH_FAILED); | ||
| 243 | + | ||
| 244 | + // 校验输入shape | ||
| 245 | + auto xInputShape = context_->GetInputShape(INPUT_IDX_X); | ||
| 246 | + OP_CHECK_NULL_WITH_CONTEXT(context_, xInputShape); | ||
| 247 | + auto xShape = xInputShape->GetStorageShape(); | ||
| 248 | + originInput_.rank = xShape.GetDimNum(); | ||
| 249 | + OP_CHECK_IF( | ||
| 250 | + originInput_.rank < MIN_X_RANK, OP_LOGE(context_, "the rank of x should be more than %lu", MIN_X_RANK), | ||
| 251 | + return ge::GRAPH_FAILED); | ||
| 252 | + | ||
| 253 | + // 校验溢出 | ||
| 254 | + xShapeSize_ = xShape.GetShapeSize(); | ||
| 255 | + OP_CHECK_IF(xShapeSize_ <= 0, OP_LOGE(context_, "the shape size of x overflows"), return ge::GRAPH_FAILED); | ||
| 256 | + | ||
| 257 | + // 获取 shape | ||
| 258 | + for (size_t i = 0; i < originInput_.rank; ++i) { | ||
| 259 | + originInput_.inShape[i] = xShape.GetDim(i); | ||
| 260 | + } | ||
| 261 | + return ge::GRAPH_SUCCESS; | ||
| 262 | +} | ||
| 263 | + | ||
| 264 | +ge::graphStatus BatchToSpaceNDTiling::CheckBlockShape() | ||
| 265 | +{ | ||
| 266 | + // 获取block shape | ||
| 267 | + auto bsInputShape = context_->GetInputShape(INPUT_IDX_BLOCK_SHAPE); | ||
| 268 | + OP_CHECK_NULL_WITH_CONTEXT(context_, bsInputShape); | ||
| 269 | + | ||
| 270 | + // 校验shape | ||
| 271 | + auto bsShape = bsInputShape->GetStorageShape(); | ||
| 272 | + size_t bsRank = bsShape.GetDimNum(); | ||
| 273 | + OP_CHECK_IF( | ||
| 274 | + bsRank != BLOCK_SHAPE_RANK, | ||
| 275 | + OP_LOGE(context_, "the rank of block_shape should be %lu, but got %lu", BLOCK_SHAPE_RANK, bsRank), | ||
| 276 | + return ge::GRAPH_FAILED); | ||
| 277 | + | ||
| 278 | + // 获取 block_shape 值 | ||
| 279 | + gert::Shape blockShape; | ||
| 280 | + OP_CHECK_IF( | ||
| 281 | + !Ops::Base::GetConstIntToShape(context_, INPUT_IDX_BLOCK_SHAPE, blockShape), | ||
| 282 | + OP_LOGE(context_, "get block_shape tensor failed"), return ge::GRAPH_FAILED); | ||
| 283 | + | ||
| 284 | + // 校验维度 | ||
| 285 | + originBlockShapeDim_ = blockShape.GetDimNum(); | ||
| 286 | + OP_CHECK_IF( | ||
| 287 | + originBlockShapeDim_ < MIN_BLOCK_SHAPE_DIM, | ||
| 288 | + OP_LOGE(context_, "the dimension of block_shape should be greater than %lu", MIN_BLOCK_SHAPE_DIM), | ||
| 289 | + return ge::GRAPH_FAILED); | ||
| 290 | + OP_CHECK_IF( | ||
| 291 | + originBlockShapeDim_ >= originInput_.rank, | ||
| 292 | + OP_LOGE( | ||
| 293 | + context_, "input rank (%u) should be greater than the dimension of block_shape (%lu)", originInput_.rank, | ||
| 294 | + originBlockShapeDim_), | ||
| 295 | + return ge::GRAPH_FAILED); | ||
| 296 | + | ||
| 297 | + // block_shape 为正数 | ||
| 298 | + for (size_t i = 0; i < originBlockShapeDim_; ++i) { | ||
| 299 | + OP_CHECK_IF( | ||
| 300 | + blockShape[i] <= 0, OP_LOGE(context_, "the value of block_shape must be positive"), | ||
| 301 | + return ge::GRAPH_FAILED); | ||
| 302 | + originInput_.blockShape[i] = static_cast<uint64_t>(blockShape[i]); | ||
| 303 | + } | ||
| 304 | + int64_t block_size = blockShape.GetShapeSize(); | ||
| 305 | + OP_CHECK_IF(block_size <= 0, OP_LOGE(context_, "the product of block_shape overflows"), return ge::GRAPH_FAILED); | ||
| 306 | + | ||
| 307 | + // block_shape 能被batch整除 | ||
| 308 | + int64_t batch = originInput_.inShape[0]; | ||
| 309 | + OP_CHECK_IF( | ||
| 310 | + ((batch % block_size) != 0), | ||
| 311 | + OP_LOGE( | ||
| 312 | + context_, "input batch dimension (%ld) not divisible by product of block size (%ld)", batch, block_size), | ||
| 313 | + return ge::GRAPH_FAILED); | ||
| 314 | + originInput_.outShape[0] = Ops::Base::FloorDiv(batch, block_size); | ||
| 315 | + yShapeSize_ = originInput_.outShape[0]; | ||
| 316 | + return ge::GRAPH_SUCCESS; | ||
| 317 | +} | ||
| 318 | + | ||
| 319 | +ge::graphStatus BatchToSpaceNDTiling::CheckCrops() | ||
| 320 | +{ | ||
| 321 | + // 获取 crops | ||
| 322 | + auto cropsInputShape = context_->GetInputShape(INPUT_IDX_CROPS); | ||
| 323 | + OP_CHECK_NULL_WITH_CONTEXT(context_, cropsInputShape); | ||
| 324 | + auto cropsShape = cropsInputShape->GetStorageShape(); | ||
| 325 | + size_t cropsRank = cropsShape.GetDimNum(); | ||
| 326 | + OP_CHECK_IF( | ||
| 327 | + cropsRank != CROPS_RANK, | ||
| 328 | + OP_LOGE( | ||
| 329 | + context_, "the shape of crops should be (%lu, %lu), but got %s", originBlockShapeDim_, CROPS_DIM_NUM_1, | ||
| 330 | + Ops::Base::ToString(cropsShape).c_str()), | ||
| 331 | + return ge::GRAPH_FAILED); | ||
| 332 | + | ||
| 333 | + // crops 和 block_shape shape 相等 | ||
| 334 | + OP_CHECK_IF( | ||
| 335 | + (cropsShape.GetDim(0) != static_cast<int64_t>(originBlockShapeDim_) || | ||
| 336 | + cropsShape.GetDim(1) != static_cast<int64_t>(CROPS_DIM_NUM_1)), | ||
| 337 | + OP_LOGE( | ||
| 338 | + context_, "the shape of crops should be (%lu, %lu), but got %s", originBlockShapeDim_, CROPS_DIM_NUM_1, | ||
| 339 | + Ops::Base::ToString(cropsShape).c_str()), | ||
| 340 | + return ge::GRAPH_FAILED); | ||
| 341 | + | ||
| 342 | + // 获取 crops 值 | ||
| 343 | + gert::Shape crops; | ||
| 344 | + OP_CHECK_IF( | ||
| 345 | + !Ops::Base::GetConstIntToShape(context_, INPUT_IDX_CROPS, crops), OP_LOGE(context_, "get crops tensor failed"), | ||
| 346 | + return ge::GRAPH_FAILED); | ||
| 347 | + | ||
| 348 | + // crops >= 0 | ||
| 349 | + auto dims = crops.GetDimNum(); | ||
| 350 | + for (size_t i = 0; i < dims; ++i) { | ||
| 351 | + OP_CHECK_IF( | ||
| 352 | + crops[i] < 0, OP_LOGE(context_, "the value of crops must be non-negative"), return ge::GRAPH_FAILED); | ||
| 353 | + originInput_.crops[i / CROPS_DIM_NUM_1][i % CROPS_DIM_NUM_1] = static_cast<uint64_t>(crops[i]); | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + return ge::GRAPH_SUCCESS; | ||
| 357 | +} | ||
| 358 | + | ||
| 359 | +ge::graphStatus BatchToSpaceNDTiling::CheckY() | ||
| 360 | +{ | ||
| 361 | + // spatial shape | ||
| 362 | + size_t i = 1; | ||
| 363 | + for (size_t j = 0; j < originBlockShapeDim_; ++i, ++j) { | ||
| 364 | + // x shape 已判断不会溢出,block_shape已判断整除batch,这里不会翻转 | ||
| 365 | + uint64_t cropedShape = originInput_.inShape[i] * originInput_.blockShape[j]; | ||
| 366 | + // crops 是否溢出 | ||
| 367 | + OP_CHECK_IF( | ||
| 368 | + originInput_.crops[j][0] > std::numeric_limits<uint64_t>::max() - originInput_.crops[j][1], | ||
| 369 | + OP_LOGE(context_, "crops overflows"), return ge::GRAPH_FAILED); | ||
| 370 | + // y shape 不能为负 | ||
| 371 | + uint64_t crops = originInput_.crops[j][0] + originInput_.crops[j][1]; | ||
| 372 | + OP_CHECK_IF( | ||
| 373 | + cropedShape < crops, OP_LOGE(context_, "the croped shape must be non-negative"), return ge::GRAPH_FAILED); | ||
| 374 | + originInput_.outShape[i] = cropedShape - crops; | ||
| 375 | + // 比x shape size 小,不会溢出 | ||
| 376 | + yShapeSize_ *= originInput_.outShape[i]; | ||
| 377 | + } | ||
| 378 | + | ||
| 379 | + // remain shape | ||
| 380 | + for (; i < originInput_.rank; ++i) { | ||
| 381 | + originInput_.outShape[i] = originInput_.inShape[i]; | ||
| 382 | + yShapeSize_ *= originInput_.outShape[i]; | ||
| 383 | + } | ||
| 384 | + return ge::GRAPH_SUCCESS; | ||
| 385 | +} | ||
| 386 | + | ||
| 387 | +ge::graphStatus BatchToSpaceNDTiling::MergeInput() | ||
| 388 | +{ | ||
| 389 | + size_t oldIdx = 0; | ||
| 390 | + size_t newIdx = 0; | ||
| 391 | + // batch不变 | ||
| 392 | + mergedInput_.inShape[newIdx] = originInput_.inShape[oldIdx]; | ||
| 393 | + mergedInput_.outShape[newIdx++] = originInput_.outShape[oldIdx++]; | ||
| 394 | + | ||
| 395 | + // 合 block_shape/crops | ||
| 396 | + uint64_t x = 1, y = 1, crops0 = 0, crops1 = 0; | ||
| 397 | + uint64_t remainShape = 1; | ||
| 398 | + for (; oldIdx <= originBlockShapeDim_; ++oldIdx) { | ||
| 399 | + size_t j = oldIdx - 1; | ||
| 400 | + // 合并 | ||
| 401 | + x *= originInput_.inShape[oldIdx]; | ||
| 402 | + y *= originInput_.outShape[oldIdx]; | ||
| 403 | + // crops如果上一维非0,则本维必为0,扩大 y[i] 倍 | ||
| 404 | + // 如果上一维为0,则赋值为本维 | ||
| 405 | + crops0 = crops0 * originInput_.outShape[oldIdx] + originInput_.crops[j][0]; | ||
| 406 | + crops1 = crops1 * originInput_.outShape[oldIdx] + originInput_.crops[j][1]; | ||
| 407 | + | ||
| 408 | + // 当前 block_shape 为 1 | ||
| 409 | + if (originInput_.blockShape[j] == 1) { | ||
| 410 | + // block_shape 非最后一维,且下一个 crops 为 0,合并到下一维 | ||
| 411 | + if (oldIdx < originBlockShapeDim_ && originInput_.crops[oldIdx][0] == 0 && | ||
| 412 | + originInput_.crops[oldIdx][1] == 0) { | ||
| 413 | + continue; | ||
| 414 | + } | ||
| 415 | + // block_shape 最后一维,且当前 crops 为 0,合并到 remain_shape | ||
| 416 | + if (oldIdx == originBlockShapeDim_ && crops0 == 0 && crops1 == 0) { | ||
| 417 | + remainShape = x; | ||
| 418 | + continue; | ||
| 419 | + } | ||
| 420 | + } | ||
| 421 | + // 写入 | ||
| 422 | + mergedInput_.inShape[newIdx] = x; | ||
| 423 | + mergedInput_.blockShape[newIdx - 1] = originInput_.blockShape[j]; | ||
| 424 | + mergedInput_.crops[newIdx - 1][0] = crops0; | ||
| 425 | + mergedInput_.crops[newIdx - 1][1] = crops1; | ||
| 426 | + mergedInput_.outShape[newIdx++] = y; | ||
| 427 | + // 初始化 | ||
| 428 | + x = 1; | ||
| 429 | + crops0 = 0; | ||
| 430 | + crops1 = 0; | ||
| 431 | + y = 1; | ||
| 432 | + } | ||
| 433 | + | ||
| 434 | + // space维度全被合并,保留1维 | ||
| 435 | + if (newIdx == 1) { | ||
| 436 | + mergedInput_.inShape[newIdx] = 1; | ||
| 437 | + mergedInput_.outShape[newIdx++] = 1; | ||
| 438 | + mergedInput_.blockShape[0] = 1; | ||
| 439 | + mergedInput_.crops[0][0] = 0; | ||
| 440 | + mergedInput_.crops[0][1] = 0; | ||
| 441 | + } | ||
| 442 | + | ||
| 443 | + // 合 remain_shape | ||
| 444 | + for (; oldIdx < originInput_.rank; ++oldIdx) { | ||
| 445 | + remainShape *= originInput_.inShape[oldIdx]; | ||
| 446 | + } | ||
| 447 | + mergedInput_.inShape[newIdx] = remainShape; | ||
| 448 | + mergedInput_.outShape[newIdx] = remainShape; | ||
| 449 | + mergedInput_.rank = newIdx + 1; | ||
| 450 | + | ||
| 451 | + return ge::GRAPH_SUCCESS; | ||
| 452 | +} | ||
| 453 | + | ||
| 454 | +ge::graphStatus BatchToSpaceNDTiling::ParamCheck() | ||
| 455 | +{ | ||
| 456 | + // 获取并校验参数 | ||
| 457 | + auto ret = CheckX(); | ||
| 458 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context_, "Check x failed"), return ret); | ||
| 459 | + ret = CheckBlockShape(); | ||
| 460 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context_, "Check block_shape failed"), return ret); | ||
| 461 | + ret = CheckCrops(); | ||
| 462 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context_, "Check crops failed"), return ret); | ||
| 463 | + ret = CheckY(); | ||
| 464 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context_, "Check y failed"), return ret); | ||
| 465 | + // 合轴 | ||
| 466 | + return MergeInput(); | ||
| 467 | +} | ||
| 468 | + | ||
| 469 | +ge::graphStatus BatchToSpaceNDTiling::moveAlignTilingBlock( | ||
| 470 | + uint32_t maxUBElements, const std::vector<uint64_t>& ubFactorAlign, const std::vector<uint64_t>& leftAlign, | ||
| 471 | + const std::vector<uint64_t>& dimValue, int32_t minCutAxis, B2SNDLargeCTilingData* tilingData) | ||
| 472 | +{ | ||
| 473 | + uint64_t totalCount = 1; | ||
| 474 | + uint32_t restFactor = maxUBElements; | ||
| 475 | + uint32_t ubAxis = 0, ubFactor = 0; | ||
| 476 | + | ||
| 477 | + int32_t rank = static_cast<int32_t>(dimValue.size()); | ||
| 478 | + int32_t tailIdx = rank - 1; | ||
| 479 | + int32_t minIdx = std::max(0, (rank + minCutAxis) % rank); | ||
| 480 | + for (int32_t i = tailIdx; i >= minIdx; --i) { | ||
| 481 | + ubAxis = i; | ||
| 482 | + // 尾轴要ub block对齐 | ||
| 483 | + uint64_t dimVal = (i == tailIdx) ? AlignBlockElement(dimValue[i]) : dimValue[i]; | ||
| 484 | + // 塞得下就直接算,但最小维要做对齐处理 | ||
| 485 | + if (restFactor >= dimVal && i != minIdx) { | ||
| 486 | + // 剩余空间充足,按维度值对齐后赋值 | ||
| 487 | + ubFactor = static_cast<uint32_t>(dimVal); | ||
| 488 | + restFactor /= ubFactor; | ||
| 489 | + continue; | ||
| 490 | + } | ||
| 491 | + // 塞不下 | ||
| 492 | + // 头尾要单独处理 | ||
| 493 | + OP_CHECK_IF( | ||
| 494 | + ubFactorAlign[i] == 0, OP_LOGE(context_, "the ub factor align must be non-zero"), return ge::GRAPH_FAILED); | ||
| 495 | + uint64_t lastLeftAlign = leftAlign[i] % ubFactorAlign[i]; | ||
| 496 | + uint64_t head = 0, tail = 0; | ||
| 497 | + if (lastLeftAlign + dimVal > ubFactorAlign[i]) { | ||
| 498 | + head = lastLeftAlign == 0 ? 0 : ubFactorAlign[i] - lastLeftAlign; | ||
| 499 | + tail = (lastLeftAlign + dimVal) % ubFactorAlign[i]; | ||
| 500 | + } else { | ||
| 501 | + head = dimVal; | ||
| 502 | + } | ||
| 503 | + uint64_t middle = dimVal > (head + tail) ? dimVal - (head + tail) : 0; | ||
| 504 | + OP_LOGI(context_, "split axis %u into head %lu, middle %lu, tail %lu", ubAxis, head, middle, tail); | ||
| 505 | + restFactor = static_cast<uint32_t>(std::min(static_cast<uint64_t>(restFactor), dimVal)); | ||
| 506 | + if (restFactor >= ubFactorAlign[i]) { | ||
| 507 | + // 超过对齐值,按对齐值倍数分组 | ||
| 508 | + ubFactor = Ops::Base::FloorAlign(restFactor, static_cast<uint32_t>(ubFactorAlign[i])); | ||
| 509 | + // 中间部分对齐分组长度 | ||
| 510 | + totalCount = Ops::Base::CeilDiv(middle, static_cast<uint64_t>(ubFactor)); | ||
| 511 | + // 头尾单独分组 | ||
| 512 | + totalCount += (head > 0) + (tail > 0); | ||
| 513 | + } else { | ||
| 514 | + // 不足对齐值,每个分组内再按 ub factor 分组 | ||
| 515 | + ubFactor = restFactor; | ||
| 516 | + totalCount = Ops::Base::CeilDiv(ubFactorAlign[i], static_cast<uint64_t>(ubFactor)) * | ||
| 517 | + Ops::Base::CeilDiv(middle, ubFactorAlign[i]); | ||
| 518 | + totalCount += Ops::Base::CeilDiv(head, static_cast<uint64_t>(ubFactor)); | ||
| 519 | + totalCount += Ops::Base::CeilDiv(tail, static_cast<uint64_t>(ubFactor)); | ||
| 520 | + } | ||
| 521 | + break; | ||
| 522 | + } | ||
| 523 | + // 非切分轴不需要对齐 | ||
| 524 | + for (int32_t i = ubAxis - 1; i >= 0; --i) { | ||
| 525 | + totalCount *= dimValue[i]; | ||
| 526 | + } | ||
| 527 | + | ||
| 528 | + tilingData->ubAxis = ubAxis; | ||
| 529 | + tilingData->totalCount = totalCount; | ||
| 530 | + tilingData->ubFactor = ubFactor; | ||
| 531 | + return ge::GRAPH_SUCCESS; | ||
| 532 | +} | ||
| 533 | + | ||
| 534 | +ge::graphStatus BatchToSpaceNDTiling::Tiling4LargeC() | ||
| 535 | +{ | ||
| 536 | + // tiling key | ||
| 537 | + mode_ = TPL_MODE_LARGE_C; | ||
| 538 | + | ||
| 539 | + // tiling data | ||
| 540 | + auto tilingData = context_->GetTilingData<B2SNDLargeCTilingData>(); | ||
| 541 | + OP_CHECK_NULL_WITH_CONTEXT(context_, tilingData); | ||
| 542 | + tilingData->input = mergedInput_; | ||
| 543 | + | ||
| 544 | + // ub 大小 | ||
| 545 | + tilingData->outputBufferSize = ubSize_ / LARGE_C_BUFFER_NUM; | ||
| 546 | + tilingData->outputBufferSize = std::min(tilingData->outputBufferSize, LARGE_C_MAX_BUFFER_SIZE); | ||
| 547 | + uint32_t maxUBElements = tilingData->outputBufferSize / static_cast<uint32_t>(dSize_); | ||
| 548 | + | ||
| 549 | + // 各轴 ub factor 对齐值 | ||
| 550 | + std::vector<uint64_t> ubFactorAlign; | ||
| 551 | + ubFactorAlign.resize(mergedInput_.rank); | ||
| 552 | + // batch 不对齐 | ||
| 553 | + ubFactorAlign[0] = 1; | ||
| 554 | + // space 对齐 block shape | ||
| 555 | + std::copy(mergedInput_.blockShape, mergedInput_.blockShape + mergedInput_.rank - 2, ubFactorAlign.begin() + 1); | ||
| 556 | + // remain shape 对齐 ub block | ||
| 557 | + ubFactorAlign[mergedInput_.rank - 1] = ubBlockElements_; | ||
| 558 | + | ||
| 559 | + std::vector<uint64_t> dimValue = | ||
| 560 | + std::vector<uint64_t>(mergedInput_.outShape, mergedInput_.outShape + mergedInput_.rank); | ||
| 561 | + std::vector<uint64_t> leftAlign{}; | ||
| 562 | + leftAlign.resize(mergedInput_.rank); | ||
| 563 | + // batch 不对齐 | ||
| 564 | + leftAlign[0] = 0; | ||
| 565 | + // space 要按crop前的大小对齐 block shape | ||
| 566 | + for (size_t i = 1; i < mergedInput_.rank - 1; ++i) { | ||
| 567 | + // 前面补齐crop前的部分 | ||
| 568 | + leftAlign[i] = mergedInput_.crops[i - 1][0]; | ||
| 569 | + } | ||
| 570 | + // remain shape 对齐 ub block | ||
| 571 | + leftAlign[mergedInput_.rank - 1] = 0; | ||
| 572 | + | ||
| 573 | + // 分块 | ||
| 574 | + auto ret = | ||
| 575 | + moveAlignTilingBlock(maxUBElements, ubFactorAlign, leftAlign, dimValue, LARGE_C_OUTMOST_CUT_AXIS, tilingData); | ||
| 576 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context_, "large C tiling failed"), return ret); | ||
| 577 | + | ||
| 578 | + // 分核 | ||
| 579 | + tilingData->perCoreCount = Ops::Base::CeilDiv(tilingData->totalCount, static_cast<uint64_t>(coreNum_)); | ||
| 580 | + realCoreNum_ = Ops::Base::CeilDiv(tilingData->totalCount, tilingData->perCoreCount); | ||
| 581 | + | ||
| 582 | + // 打印 tiling data | ||
| 583 | + ShowLargeCTilingData(); | ||
| 584 | + return ge::GRAPH_SUCCESS; | ||
| 585 | +} | ||
| 586 | + | ||
| 587 | +void BatchToSpaceNDTiling::SmallCSetInput(B2SNDSmallCTilingData* tilingData, size_t yAxisPerm[]) | ||
| 588 | +{ | ||
| 589 | + // 展开 x shape | ||
| 590 | + size_t rank = blockShapeDimNum_ + mergedInput_.rank; | ||
| 591 | + // batch | ||
| 592 | + std::copy(mergedInput_.blockShape, mergedInput_.blockShape + blockShapeDimNum_, tilingData->oriInShape); | ||
| 593 | + tilingData->oriInShape[blockShapeDimNum_] = mergedInput_.outShape[0]; | ||
| 594 | + // space + remain | ||
| 595 | + std::copy( | ||
| 596 | + mergedInput_.inShape + 1, mergedInput_.inShape + mergedInput_.rank, | ||
| 597 | + tilingData->oriInShape + blockShapeDimNum_ + 1); | ||
| 598 | + | ||
| 599 | + // 预crop | ||
| 600 | + for (size_t i = 0; i < blockShapeDimNum_; ++i) { | ||
| 601 | + uint64_t& bs = mergedInput_.blockShape[i]; | ||
| 602 | + uint64_t& x = mergedInput_.inShape[i + 1]; | ||
| 603 | + uint64_t yStart = mergedInput_.crops[i][0]; | ||
| 604 | + uint64_t yEnd = x * bs - mergedInput_.crops[i][1] - 1; | ||
| 605 | + uint64_t xStart = yStart / bs; // 截取前的输出对应 x 的起始坐标 | ||
| 606 | + uint64_t xEnd = yEnd / bs; // 截取前的输出对应 x 的结束坐标 | ||
| 607 | + // 截取后的 space | ||
| 608 | + tilingData->croppedInShape[blockShapeDimNum_ + 1 + i] = xEnd + 1 - xStart; | ||
| 609 | + if (xStart == xEnd) { | ||
| 610 | + // 截取后的 block shape | ||
| 611 | + tilingData->croppedInShape[i] = yEnd + 1 - yStart; | ||
| 612 | + } else { | ||
| 613 | + // 不截取 block shape | ||
| 614 | + tilingData->croppedInShape[i] = bs; | ||
| 615 | + } | ||
| 616 | + } | ||
| 617 | + // y batch | ||
| 618 | + tilingData->croppedInShape[blockShapeDimNum_] = mergedInput_.outShape[0]; | ||
| 619 | + // remain | ||
| 620 | + tilingData->croppedInShape[rank - 1] = mergedInput_.inShape[mergedInput_.rank - 1]; | ||
| 621 | + | ||
| 622 | + // 输出轴映射输入轴 | ||
| 623 | + // batch | ||
| 624 | + yAxisPerm[0] = blockShapeDimNum_; | ||
| 625 | + // remain | ||
| 626 | + yAxisPerm[rank - 1] = rank - 1; | ||
| 627 | + for (size_t i = 0; i < blockShapeDimNum_; ++i) { | ||
| 628 | + // block shape | ||
| 629 | + yAxisPerm[2 + i * 2] = i; | ||
| 630 | + // space | ||
| 631 | + yAxisPerm[1 + i * 2] = blockShapeDimNum_ + 1 + i; | ||
| 632 | + } | ||
| 633 | + | ||
| 634 | + // crops | ||
| 635 | + std::copy(*mergedInput_.crops, (*mergedInput_.crops) + blockShapeDimNum_ * 2, *(tilingData->crops)); | ||
| 636 | +} | ||
| 637 | + | ||
| 638 | +ge::graphStatus BatchToSpaceNDTiling::Tiling4SmallC() | ||
| 639 | +{ | ||
| 640 | + // tiling key | ||
| 641 | + mode_ = TPL_MODE_SMALL_C; | ||
| 642 | + blockShapeDimNum_ = mergedInput_.rank - 2; | ||
| 643 | + | ||
| 644 | + // tiling data | ||
| 645 | + auto tilingData = context_->GetTilingData<B2SNDSmallCTilingData>(); | ||
| 646 | + OP_CHECK_NULL_WITH_CONTEXT(context_, tilingData); | ||
| 647 | + // 处理输入数据 | ||
| 648 | + size_t yAxisPerm[MAX_EXPAND_RANK]{}; | ||
| 649 | + SmallCSetInput(tilingData, yAxisPerm); | ||
| 650 | + | ||
| 651 | + // 可用UB大小 | ||
| 652 | + uint32_t validBufSize = ubSize_ / SMALL_C_BUFFER_NUM; | ||
| 653 | + tilingData->ubTileSize = std::min(validBufSize / SMALL_C_BUFFER_FACTOR, SMALL_C_MAX_BUFFER_SIZE); | ||
| 654 | + uint32_t inputElements = tilingData->ubTileSize / dSize_; | ||
| 655 | + | ||
| 656 | + // 输入输出双切分 | ||
| 657 | + auto tiling = DualSideTiling( | ||
| 658 | + context_, ubBlockElements_, tilingData->croppedInShape, yAxisPerm, blockShapeDimNum_ + mergedInput_.rank); | ||
| 659 | + tiling.DoTiling(inputElements); | ||
| 660 | + tilingData->inUbAxis = tiling.inAxis; | ||
| 661 | + tilingData->inUbFactor = tiling.inFactor; | ||
| 662 | + tilingData->outUbAxis = tiling.outAxis; | ||
| 663 | + tilingData->outUbFactor = tiling.outFactor; | ||
| 664 | + tilingData->ubTotalCount = tiling.totalCount; | ||
| 665 | + | ||
| 666 | + // 分核 | ||
| 667 | + tilingData->ubPerCount = Ops::Base::CeilDiv(tilingData->ubTotalCount, static_cast<uint64_t>(coreNum_)); | ||
| 668 | + realCoreNum_ = Ops::Base::CeilDiv(tilingData->ubTotalCount, tilingData->ubPerCount); | ||
| 669 | + tilingData->coreNum = realCoreNum_; | ||
| 670 | + | ||
| 671 | + // 打印 tiling data | ||
| 672 | + ShowSmallCTilingData(); | ||
| 673 | + return ge::GRAPH_SUCCESS; | ||
| 674 | +} | ||
| 675 | + | ||
| 676 | +ge::graphStatus BatchToSpaceNDTiling::Tiling4SIMT() | ||
| 677 | +{ | ||
| 678 | + // tiling key | ||
| 679 | + mode_ = TPL_MODE_SIMT; | ||
| 680 | + isBigShape_ = xShapeSize_ > MAX_UINT32_NUM; | ||
| 681 | + | ||
| 682 | + // 可用UB大小 | ||
| 683 | + OP_CHECK_IF((ubSize_ < SIMT_DCACHE_SIZE), OP_LOGE(context_, "ub size invalid"), return ge::GRAPH_FAILED); | ||
| 684 | + uint32_t validBufSize = (ubSize_ - SIMT_DCACHE_SIZE) / SIMT_BUFFER_NUM; | ||
| 685 | + uint32_t usedBufSize = std::min(validBufSize, SIMT_MAX_UB_SIZE); | ||
| 686 | + auto ret = context_->SetLocalMemorySize(usedBufSize * SIMT_BUFFER_NUM); | ||
| 687 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context_, "set local memory size failed."), return ret); | ||
| 688 | + | ||
| 689 | + // tiling data | ||
| 690 | + auto tilingData = context_->GetTilingData<B2SNDSimtTilingData>(); | ||
| 691 | + OP_CHECK_NULL_WITH_CONTEXT(context_, tilingData); | ||
| 692 | + tilingData->input = mergedInput_; | ||
| 693 | + | ||
| 694 | + // 按1维分块 | ||
| 695 | + tilingData->blockSize = usedBufSize / dSize_; | ||
| 696 | + // 向下对齐线程数 | ||
| 697 | + uint32_t threadNum = simtMaxThreads_ / SIMT_THREAD_FACTOR; | ||
| 698 | + tilingData->blockSize = Ops::Base::FloorAlign(tilingData->blockSize, threadNum); | ||
| 699 | + // 防止输出为空,至少要1 | ||
| 700 | + tilingData->totalBlock = std::max( | ||
| 701 | + 1UL, Ops::Base::CeilDiv(static_cast<uint64_t>(yShapeSize_), static_cast<uint64_t>(tilingData->blockSize))); | ||
| 702 | + tilingData->tailBlockSize = static_cast<uint32_t>(static_cast<uint64_t>(yShapeSize_) % tilingData->blockSize); | ||
| 703 | + if (tilingData->tailBlockSize == 0) { | ||
| 704 | + tilingData->tailBlockSize = yShapeSize_ == 0 ? 0 : tilingData->blockSize; | ||
| 705 | + } | ||
| 706 | + | ||
| 707 | + // 均分分核 | ||
| 708 | + realCoreNum_ = tilingData->totalBlock > coreNum_ ? coreNum_ : static_cast<uint32_t>(tilingData->totalBlock); | ||
| 709 | + tilingData->needCoreNum = realCoreNum_; | ||
| 710 | + tilingData->mainCoreBlock = Ops::Base::CeilDiv(tilingData->totalBlock, static_cast<uint64_t>(realCoreNum_)); | ||
| 711 | + tilingData->mainCoreNum = static_cast<uint32_t>(tilingData->totalBlock % realCoreNum_); | ||
| 712 | + if (tilingData->mainCoreNum == 0) { | ||
| 713 | + tilingData->mainCoreNum = realCoreNum_; | ||
| 714 | + } | ||
| 715 | + | ||
| 716 | + // 打印 tiling data | ||
| 717 | + ShowSIMTTilingData(); | ||
| 718 | + return ge::GRAPH_SUCCESS; | ||
| 719 | +} | ||
| 720 | + | ||
| 721 | +ge::graphStatus BatchToSpaceNDTiling::DoOpTiling() | ||
| 722 | +{ | ||
| 723 | + cacheLineElements_ = cacheLineSize_ / dSize_; | ||
| 724 | + ubBlockElements_ = ubBlockSize_ / dSize_; | ||
| 725 | + | ||
| 726 | + // 输出空tensor | ||
| 727 | + if (yShapeSize_ == 0) { | ||
| 728 | + return Tiling4SIMT(); | ||
| 729 | + } | ||
| 730 | + | ||
| 731 | + // 维度较多 | ||
| 732 | + if (mergedInput_.rank >= MIN_RANK_FOR_SIMT) { | ||
| 733 | + return Tiling4SIMT(); | ||
| 734 | + } | ||
| 735 | + | ||
| 736 | + // 尾轴 >= cacheline | ||
| 737 | + if (mergedInput_.inShape[mergedInput_.rank - 1] >= static_cast<uint64_t>(cacheLineElements_)) { | ||
| 738 | + return Tiling4LargeC(); | ||
| 739 | + } | ||
| 740 | + return Tiling4SIMT(); | ||
| 741 | +} | ||
| 742 | + | ||
| 743 | +ge::graphStatus BatchToSpaceNDTiling::GetSocInfo() | ||
| 744 | +{ | ||
| 745 | + // 获取soc信息, 如ub大小, core数等 | ||
| 746 | + auto platformInfoPtr = context_->GetPlatformInfo(); | ||
| 747 | + OP_CHECK_NULL_WITH_CONTEXT(context_, platformInfoPtr); | ||
| 748 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr); | ||
| 749 | + coreNum_ = ascendcPlatform.GetCoreNumAiv(); | ||
| 750 | + realCoreNum_ = coreNum_; | ||
| 751 | + OP_CHECK_IF((coreNum_ == 0U), OP_LOGE(context_, "coreNum is 0"), return ge::GRAPH_FAILED); | ||
| 752 | + uint64_t ubSize = 0; | ||
| 753 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize); | ||
| 754 | + OP_CHECK_IF((ubSize == 0U), OP_LOGE(context_, "ubSize is 0"), return ge::GRAPH_FAILED); | ||
| 755 | + OP_CHECK_IF((ubSize > MAX_UINT32_NUM), OP_LOGE(context_, "ub size not support"), return ge::GRAPH_FAILED); | ||
| 756 | + ubSize_ = ubSize; | ||
| 757 | + cacheLineSize_ = Ops::Base::GetCacheLineSize(context_); | ||
| 758 | + OP_CHECK_IF((cacheLineSize_ == 0U), OP_LOGE(context_, "Failed to get cache line size."), return ge::GRAPH_FAILED); | ||
| 759 | + ubBlockSize_ = Ops::Base::GetUbBlockSize(context_); | ||
| 760 | + OP_CHECK_IF((ubBlockSize_ == 0U), OP_LOGE(context_, "Failed to get ub block size."), return ge::GRAPH_FAILED); | ||
| 761 | + vRegSize_ = Ops::Base::GetVRegSize(context_); | ||
| 762 | + OP_CHECK_IF((vRegSize_ == 0U), OP_LOGE(context_, "Failed to get vector register size."), return ge::GRAPH_FAILED); | ||
| 763 | + simtMaxThreads_ = Ops::Base::GetSimtMaxThreadNum(context_); | ||
| 764 | + OP_CHECK_IF((simtMaxThreads_ == 0U), OP_LOGE(context_, "Failed to get simt thread num."), return ge::GRAPH_FAILED); | ||
| 765 | + return ge::GRAPH_SUCCESS; | ||
| 766 | +} | ||
| 767 | + | ||
| 768 | +static ge::graphStatus Tiling4BatchToSpaceND(gert::TilingContext* context) | ||
| 769 | +{ | ||
| 770 | + // DoTiling | ||
| 771 | + BatchToSpaceNDTiling tiling{context}; | ||
| 772 | + return tiling.DoTiling(); | ||
| 773 | +} | ||
| 774 | + | ||
| 775 | +static ge::graphStatus TilingPrepareForBatchToSpaceND([[maybe_unused]] gert::TilingParseContext* context) | ||
| 776 | +{ | ||
| 777 | + return ge::GRAPH_SUCCESS; | ||
| 778 | +} | ||
| 779 | + | ||
| 780 | +IMPL_OP_OPTILING(BatchToSpaceND) | ||
| 781 | + .Tiling(Tiling4BatchToSpaceND) | ||
| 782 | + .TilingInputsDataDependency({INPUT_IDX_BLOCK_SHAPE, INPUT_IDX_CROPS}) | ||
| 783 | + .TilingParse<B2SNDCompileInfo>(TilingPrepareForBatchToSpaceND); | ||
| 784 | +} // namespace optiling | ||
| @@ -0,0 +1,337 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +namespace optiling { | ||
| 19 | + | ||
| 20 | +namespace { | ||
| 21 | +struct CutInfo { // 切分信息 | ||
| 22 | + std::set<size_t> axisSet{}; // 轴集合 | ||
| 23 | + size_t cutAxis{0}; // 切分轴 | ||
| 24 | + uint32_t cutFactor{1}; // 切分轴维度数量 | ||
| 25 | + uint32_t innerProd{1}; // 内轴积 | ||
| 26 | + uint32_t outterProd{1}; // 外轴积 | ||
| 27 | + const size_t* axisPerm; // 轴的排列 | ||
| 28 | + | ||
| 29 | + CutInfo() : axisPerm(nullptr) {}; | ||
| 30 | + CutInfo(const size_t* perm) : axisPerm(perm) {}; | ||
| 31 | + ~CutInfo() {}; | ||
| 32 | + | ||
| 33 | + size_t Idx2Axis(int16_t idx) const | ||
| 34 | + { | ||
| 35 | + return axisPerm == nullptr ? idx : axisPerm[idx]; | ||
| 36 | + } | ||
| 37 | +}; | ||
| 38 | +} // namespace | ||
| 39 | + | ||
| 40 | +class DualSideTiling { | ||
| 41 | +private: | ||
| 42 | + // tiling context | ||
| 43 | + gert::TilingContext* context_; | ||
| 44 | + | ||
| 45 | + // 输入 | ||
| 46 | + const uint32_t ubBlockElements_; // UB block 对应元素个数 | ||
| 47 | + const uint64_t* axisSizeList_; // 每根轴大小 | ||
| 48 | + const size_t* outAxisPerm_; // 输出轴的排列 | ||
| 49 | + const size_t rank_; // 轴的数量 | ||
| 50 | + uint32_t maxBufElements_; // 单侧最大缓存元素个数 | ||
| 51 | + | ||
| 52 | + // 中间变量 | ||
| 53 | + int startIdx_{0}; // 起始轴 | ||
| 54 | + uint32_t commAxisProd_{1}; // 公共轴的积 | ||
| 55 | + uint64_t expectMaxInnerProd_{0}; // 每一侧内轴积期望最大值 | ||
| 56 | + std::set<size_t> commAxisSet_{}; // 公共轴集合 | ||
| 57 | + std::set<size_t> kernelAxisSet_{}; // 所有核间轴集合 | ||
| 58 | + bool isCommAxisUpdated_{false}; // 公共轴是否有更新 | ||
| 59 | +public: | ||
| 60 | + // 输出 | ||
| 61 | + size_t inAxis{0}; // 输入切分轴 | ||
| 62 | + size_t outAxis{0}; // 输出切分轴(按输入索引) | ||
| 63 | + uint32_t inFactor{1}; // 输入切分轴维度数量 | ||
| 64 | + uint32_t outFactor{1}; // 输出切分轴维度数量 | ||
| 65 | + uint64_t totalCount{1}; // 块数 | ||
| 66 | +public: | ||
| 67 | + DualSideTiling( | ||
| 68 | + gert::TilingContext* context, const uint32_t ubBlockElements, const uint64_t* axisSizeList, | ||
| 69 | + const size_t* outAxisPerm, const size_t rank) | ||
| 70 | + : context_(context), | ||
| 71 | + ubBlockElements_(ubBlockElements), | ||
| 72 | + axisSizeList_(axisSizeList), | ||
| 73 | + outAxisPerm_(outAxisPerm), | ||
| 74 | + rank_(rank) {}; | ||
| 75 | + ~DualSideTiling() {}; | ||
| 76 | + | ||
| 77 | + void DoTiling(uint32_t maxBufElements); | ||
| 78 | + | ||
| 79 | +private: | ||
| 80 | + // block 对齐 | ||
| 81 | + template <typename T> | ||
| 82 | + inline T CeilAlignBlockElement(T elementCount) const; | ||
| 83 | + template <typename T> | ||
| 84 | + inline T FloorAlignBlockElement(T elementCount) const; | ||
| 85 | + | ||
| 86 | + // 初始化 | ||
| 87 | + void Init(); | ||
| 88 | + // 计算最大内轴积 | ||
| 89 | + inline uint32_t ComputeActualMaxInnerProd(const CutInfo& currInfo) const; | ||
| 90 | + // 新增公共轴 | ||
| 91 | + inline void AddCommonAxis(size_t axis); | ||
| 92 | + // 计算应该切哪根轴 | ||
| 93 | + inline size_t ComputeCutAxis(int16_t& currIdx, CutInfo& currInfo, CutInfo& otherInfo); | ||
| 94 | + // 计算切分轴上的最大维度数量 | ||
| 95 | + inline uint64_t ComputeMaxFactor(const CutInfo& currInfo, uint64_t maxInnerProd) const; | ||
| 96 | + // 计算切分轴上的维度数量 | ||
| 97 | + inline uint32_t ComputeAxisFactor(const CutInfo& currInfo) const; | ||
| 98 | + // 填满切分轴维度数量 | ||
| 99 | + inline void FillAxisFactor(CutInfo& currInfo, const CutInfo& otherInfo); | ||
| 100 | + // 调整每侧的切分轴维度数量 | ||
| 101 | + inline void AdjustAxisFactor(CutInfo& inputInfo, CutInfo& outputInfo); | ||
| 102 | + // 切轴 | ||
| 103 | + void CutAxis(); | ||
| 104 | + // 计算总块数 | ||
| 105 | + void ComputeTotalCount(); | ||
| 106 | + | ||
| 107 | + // 全载 | ||
| 108 | + bool TryFullLoad(); | ||
| 109 | + // 非全载 | ||
| 110 | + void DoNonFullLoad(); | ||
| 111 | +}; | ||
| 112 | + | ||
| 113 | +template <typename T> | ||
| 114 | +inline T DualSideTiling::CeilAlignBlockElement(T elementCount) const | ||
| 115 | +{ | ||
| 116 | + return Ops::Base::CeilAlign(elementCount, static_cast<T>(ubBlockElements_)); | ||
| 117 | +} | ||
| 118 | + | ||
| 119 | +template <typename T> | ||
| 120 | +inline T DualSideTiling::FloorAlignBlockElement(T elementCount) const | ||
| 121 | +{ | ||
| 122 | + return Ops::Base::FloorAlign(elementCount, static_cast<T>(ubBlockElements_)); | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +void DualSideTiling::Init() | ||
| 126 | +{ | ||
| 127 | + startIdx_ = rank_ - 1; | ||
| 128 | + // 核间轴初始为 0 ~ -2 轴,必不包含 -1 轴 | ||
| 129 | + for (size_t i = 0; i < rank_ - 1; ++i) { | ||
| 130 | + kernelAxisSet_.emplace_hint(kernelAxisSet_.end(), i); | ||
| 131 | + } | ||
| 132 | + // 本模板尾轴小,如果存在公共尾轴则从-2轴开始切 | ||
| 133 | + if (static_cast<size_t>(startIdx_) == outAxisPerm_[startIdx_]) { | ||
| 134 | + AddCommonAxis(startIdx_--); | ||
| 135 | + } else { | ||
| 136 | + expectMaxInnerProd_ = FloorAlignBlockElement(static_cast<uint64_t>(std::sqrt(maxBufElements_))); | ||
| 137 | + } | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +bool DualSideTiling::TryFullLoad() | ||
| 141 | +{ | ||
| 142 | + uint64_t allElements = 1; | ||
| 143 | + for (size_t i = 0; i < rank_; ++i) { | ||
| 144 | + allElements *= axisSizeList_[i]; | ||
| 145 | + } | ||
| 146 | + // 能全载 | ||
| 147 | + if (allElements > maxBufElements_) { | ||
| 148 | + return false; | ||
| 149 | + } | ||
| 150 | + inAxis = 0; | ||
| 151 | + inFactor = axisSizeList_[0]; | ||
| 152 | + outAxis = outAxisPerm_[0]; | ||
| 153 | + outFactor = axisSizeList_[outAxis]; | ||
| 154 | + totalCount = 1; | ||
| 155 | + return true; | ||
| 156 | +} | ||
| 157 | + | ||
| 158 | +inline uint32_t DualSideTiling::ComputeActualMaxInnerProd(const CutInfo& currInfo) const | ||
| 159 | +{ | ||
| 160 | + // 每侧元素数 = 内轴向上block对齐 * 外轴 | ||
| 161 | + // 则每侧的最大值为:最大元素数/当前侧的UB外轴,然后向下block对齐 | ||
| 162 | + return FloorAlignBlockElement(Ops::Base::FloorDiv(maxBufElements_, currInfo.outterProd)); | ||
| 163 | +} | ||
| 164 | + | ||
| 165 | +inline void DualSideTiling::AddCommonAxis(size_t axis) | ||
| 166 | +{ | ||
| 167 | + commAxisProd_ *= axisSizeList_[axis]; | ||
| 168 | + commAxisSet_.insert(axis); | ||
| 169 | + expectMaxInnerProd_ = FloorAlignBlockElement(static_cast<uint64_t>(std::sqrt(maxBufElements_ * commAxisProd_))); | ||
| 170 | + isCommAxisUpdated_ = true; | ||
| 171 | +} | ||
| 172 | + | ||
| 173 | +inline size_t DualSideTiling::ComputeCutAxis(int16_t& currIdx, CutInfo& currInfo, CutInfo& otherInfo) | ||
| 174 | +{ | ||
| 175 | + uint32_t maxInnerProd = ComputeActualMaxInnerProd(currInfo); | ||
| 176 | + size_t currAxis; | ||
| 177 | + for (; currIdx >= 0; --currIdx) { | ||
| 178 | + currAxis = currInfo.Idx2Axis(currIdx); | ||
| 179 | + uint64_t axisSize = axisSizeList_[currAxis]; | ||
| 180 | + // 如果另一边已经放下了这跟轴,则表示为公共轴,必然能放下,跳过 | ||
| 181 | + if (otherInfo.axisSet.find(currAxis) != otherInfo.axisSet.end()) { | ||
| 182 | + // 加入公共轴 | ||
| 183 | + AddCommonAxis(currAxis); | ||
| 184 | + otherInfo.axisSet.erase(currAxis); | ||
| 185 | + // 加入内轴 | ||
| 186 | + currInfo.innerProd *= axisSize; | ||
| 187 | + // 从外轴中去除 | ||
| 188 | + currInfo.outterProd /= std::max(axisSize, 1UL); | ||
| 189 | + maxInnerProd = ComputeActualMaxInnerProd(currInfo); | ||
| 190 | + continue; | ||
| 191 | + } | ||
| 192 | + uint64_t tmpInner = currInfo.innerProd * axisSize; | ||
| 193 | + // 放不下,当前轴即为切分轴 | ||
| 194 | + if (tmpInner > expectMaxInnerProd_ || tmpInner > maxInnerProd) { | ||
| 195 | + return currAxis; | ||
| 196 | + } | ||
| 197 | + currInfo.innerProd = tmpInner; | ||
| 198 | + currInfo.axisSet.emplace(currAxis); | ||
| 199 | + otherInfo.outterProd *= axisSize; // 加入另一侧外轴 | ||
| 200 | + kernelAxisSet_.erase(currAxis); | ||
| 201 | + } | ||
| 202 | + return currInfo.Idx2Axis(0); | ||
| 203 | +} | ||
| 204 | + | ||
| 205 | +inline uint64_t DualSideTiling::ComputeMaxFactor(const CutInfo& currInfo, uint64_t maxInnerProd) const | ||
| 206 | +{ | ||
| 207 | + return Ops::Base::FloorDiv(maxInnerProd, static_cast<uint64_t>(currInfo.innerProd)); | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | +inline uint32_t DualSideTiling::ComputeAxisFactor(const CutInfo& currInfo) const | ||
| 211 | +{ | ||
| 212 | + // 实际最大内轴积 | ||
| 213 | + uint32_t actualMaxInnerProd = ComputeActualMaxInnerProd(currInfo); | ||
| 214 | + uint64_t maxInnerProd = std::min(expectMaxInnerProd_, static_cast<uint64_t>(actualMaxInnerProd)); | ||
| 215 | + uint64_t axisFactor = ComputeMaxFactor(currInfo, maxInnerProd); | ||
| 216 | + return static_cast<uint32_t>(std::clamp(axisFactor, 1UL, axisSizeList_[currInfo.cutAxis])); | ||
| 217 | +} | ||
| 218 | + | ||
| 219 | +inline void DualSideTiling::FillAxisFactor(CutInfo& currInfo, const CutInfo& otherInfo) | ||
| 220 | +{ | ||
| 221 | + uint32_t maxInnerProd = ComputeActualMaxInnerProd(currInfo); | ||
| 222 | + maxInnerProd = Ops::Base::FloorDiv(maxInnerProd, otherInfo.cutFactor); | ||
| 223 | + uint64_t axisFactor = ComputeMaxFactor(currInfo, maxInnerProd); | ||
| 224 | + currInfo.cutFactor = static_cast<uint32_t>(std::clamp(axisFactor, 1UL, axisSizeList_[currInfo.cutAxis])); | ||
| 225 | +} | ||
| 226 | + | ||
| 227 | +inline void DualSideTiling::AdjustAxisFactor(CutInfo& inputInfo, CutInfo& outputInfo) | ||
| 228 | +{ | ||
| 229 | + // 把剩余部分调给小轴 | ||
| 230 | + uint32_t inputInner = inputInfo.cutFactor * inputInfo.innerProd; | ||
| 231 | + uint32_t outputInner = outputInfo.cutFactor * outputInfo.innerProd; | ||
| 232 | + if (inputInner <= outputInner) { | ||
| 233 | + FillAxisFactor(inputInfo, outputInfo); | ||
| 234 | + } else { | ||
| 235 | + FillAxisFactor(outputInfo, inputInfo); | ||
| 236 | + } | ||
| 237 | +} | ||
| 238 | + | ||
| 239 | +void DualSideTiling::CutAxis() | ||
| 240 | +{ | ||
| 241 | + // 起始索引 | ||
| 242 | + int16_t xIdx = startIdx_; | ||
| 243 | + int16_t yIdx = startIdx_; | ||
| 244 | + CutInfo inputInfo{}; // 输入切分信息 | ||
| 245 | + CutInfo outputInfo{outAxisPerm_}; // 输出切分信息 | ||
| 246 | + // 初始内积为公共内积 | ||
| 247 | + inputInfo.innerProd = commAxisProd_; | ||
| 248 | + outputInfo.innerProd = commAxisProd_; | ||
| 249 | + | ||
| 250 | + while (true) { | ||
| 251 | + isCommAxisUpdated_ = false; | ||
| 252 | + // 遍历输入切分轴 | ||
| 253 | + inputInfo.cutAxis = ComputeCutAxis(xIdx, inputInfo, outputInfo); | ||
| 254 | + // 遍历输出切分轴 | ||
| 255 | + outputInfo.cutAxis = ComputeCutAxis(yIdx, outputInfo, inputInfo); | ||
| 256 | + if (isCommAxisUpdated_) { | ||
| 257 | + continue; | ||
| 258 | + } | ||
| 259 | + // 切同一根轴,即当前切分轴为公共轴 | ||
| 260 | + if (inputInfo.cutAxis == outputInfo.cutAxis) { | ||
| 261 | + uint64_t axisElements = axisSizeList_[inputInfo.cutAxis]; | ||
| 262 | + // 输入侧当前轴最大切分值 | ||
| 263 | + uint64_t maxInFactor = ComputeMaxFactor(inputInfo, ComputeActualMaxInnerProd(inputInfo)); | ||
| 264 | + // 输出侧当前轴最大切分值 | ||
| 265 | + uint64_t maxOutFactor = ComputeMaxFactor(outputInfo, ComputeActualMaxInnerProd(outputInfo)); | ||
| 266 | + // 能放下 | ||
| 267 | + if (axisElements <= maxInFactor && axisElements <= maxOutFactor) { | ||
| 268 | + AddCommonAxis(inputInfo.cutAxis); | ||
| 269 | + kernelAxisSet_.erase(inputInfo.cutAxis); | ||
| 270 | + // 加入内轴,不需要更新外轴 | ||
| 271 | + inputInfo.innerProd *= axisElements; | ||
| 272 | + outputInfo.innerProd *= axisElements; | ||
| 273 | + xIdx--; | ||
| 274 | + yIdx--; | ||
| 275 | + continue; | ||
| 276 | + } | ||
| 277 | + // 放不下,就切这根轴 | ||
| 278 | + uint64_t factor = std::min(maxInFactor, maxOutFactor); | ||
| 279 | + factor = std::clamp(factor, 1UL, axisElements); | ||
| 280 | + inputInfo.cutFactor = factor; | ||
| 281 | + outputInfo.cutFactor = factor; | ||
| 282 | + break; | ||
| 283 | + } | ||
| 284 | + // 计算切分大小 | ||
| 285 | + inputInfo.cutFactor = ComputeAxisFactor(inputInfo); | ||
| 286 | + outputInfo.cutFactor = ComputeAxisFactor(outputInfo); | ||
| 287 | + AdjustAxisFactor(inputInfo, outputInfo); | ||
| 288 | + break; | ||
| 289 | + } | ||
| 290 | + // 剔除当前切分轴 | ||
| 291 | + kernelAxisSet_.erase(inputInfo.cutAxis); | ||
| 292 | + kernelAxisSet_.erase(outputInfo.cutAxis); | ||
| 293 | + // 赋值 | ||
| 294 | + inAxis = inputInfo.cutAxis; | ||
| 295 | + inFactor = inputInfo.cutFactor; | ||
| 296 | + outAxis = outputInfo.cutAxis; | ||
| 297 | + outFactor = outputInfo.cutFactor; | ||
| 298 | +} | ||
| 299 | + | ||
| 300 | +void DualSideTiling::ComputeTotalCount() | ||
| 301 | +{ | ||
| 302 | + // 核间轴乘积即为总块数 | ||
| 303 | + totalCount = 1; | ||
| 304 | + // 被切的轴的外轴 | ||
| 305 | + if (inAxis == outAxis) { | ||
| 306 | + totalCount *= Ops::Base::CeilDiv(axisSizeList_[inAxis], static_cast<uint64_t>(inFactor)); | ||
| 307 | + } else { | ||
| 308 | + totalCount *= Ops::Base::CeilDiv(axisSizeList_[inAxis], static_cast<uint64_t>(inFactor)); | ||
| 309 | + totalCount *= Ops::Base::CeilDiv(axisSizeList_[outAxis], static_cast<uint64_t>(outFactor)); | ||
| 310 | + } | ||
| 311 | + // 剩余核间轴 | ||
| 312 | + for (auto i : kernelAxisSet_) { | ||
| 313 | + totalCount *= axisSizeList_[i]; | ||
| 314 | + } | ||
| 315 | +} | ||
| 316 | + | ||
| 317 | +void DualSideTiling::DoNonFullLoad() | ||
| 318 | +{ | ||
| 319 | + Init(); | ||
| 320 | + | ||
| 321 | + CutAxis(); | ||
| 322 | + | ||
| 323 | + // 计算核间轴 | ||
| 324 | + ComputeTotalCount(); | ||
| 325 | +} | ||
| 326 | + | ||
| 327 | +void DualSideTiling::DoTiling(uint32_t maxBufElements) | ||
| 328 | +{ | ||
| 329 | + maxBufElements_ = maxBufElements; | ||
| 330 | + // 全载 | ||
| 331 | + if (TryFullLoad()) { | ||
| 332 | + return; | ||
| 333 | + } | ||
| 334 | + | ||
| 335 | + DoNonFullLoad(); | ||
| 336 | +} | ||
| 337 | +} // namespace optiling | ||
| @@ -0,0 +1,85 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +namespace ops { | ||
| 15 | +// x data type 所有取值 | ||
| 16 | +static constexpr std::array VALUE_DATA_TYPE_ALL{ | ||
| 17 | + ge::DT_INT8, ge::DT_UINT8, ge::DT_INT16, ge::DT_UINT16, ge::DT_INT32, | ||
| 18 | + ge::DT_UINT32, ge::DT_INT64, ge::DT_UINT64, ge::DT_BF16, ge::DT_FLOAT16, | ||
| 19 | + ge::DT_FLOAT, ge::DT_DOUBLE, ge::DT_BOOL, ge::DT_COMPLEX32, ge::DT_COMPLEX64, | ||
F 最后这个逗号看着没有意义 ![]() ![]() | |||
| 20 | +}; | ||
| 21 | +// 索引类型 data type 所有取值 | ||
| 22 | +static constexpr std::array INDEX_DATA_TYPE_ALL{ge::DT_INT32, ge::DT_INT64}; | ||
| 23 | +// 所有组合数量 | ||
| 24 | +static constexpr size_t DATA_TYPE_COMBINE_COUNT = | ||
| 25 | + VALUE_DATA_TYPE_ALL.size() * INDEX_DATA_TYPE_ALL.size() * INDEX_DATA_TYPE_ALL.size(); | ||
| 26 | +// 计算各输入的 data type 组合 | ||
| 27 | +static constexpr std::array<std::array<ge::DataType, DATA_TYPE_COMBINE_COUNT>, 3> CombineDataTypes() | ||
| 28 | +{ | ||
| 29 | + std::array<ge::DataType, DATA_TYPE_COMBINE_COUNT> xDTs{}, blockShapeDTs{}, cropsDTs{}; | ||
| 30 | + | ||
| 31 | + std::size_t idx = 0; | ||
| 32 | + for (std::size_t i3 = 0; i3 < INDEX_DATA_TYPE_ALL.size(); ++i3) { | ||
| 33 | + for (std::size_t i2 = 0; i2 < INDEX_DATA_TYPE_ALL.size(); ++i2) { | ||
| 34 | + for (std::size_t i1 = 0; i1 < VALUE_DATA_TYPE_ALL.size(); ++i1) { | ||
| 35 | + xDTs[idx] = VALUE_DATA_TYPE_ALL[i1]; | ||
| 36 | + blockShapeDTs[idx] = INDEX_DATA_TYPE_ALL[i2]; | ||
| 37 | + cropsDTs[idx] = INDEX_DATA_TYPE_ALL[i3]; | ||
| 38 | + ++idx; | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | + std::array res{xDTs, blockShapeDTs, cropsDTs}; | ||
| 43 | + return res; | ||
| 44 | +} | ||
| 45 | +static constexpr auto DATA_TYPE_LIST = CombineDataTypes(); | ||
| 46 | +static constexpr auto& X_DATA_TYPE_LIST = std::get<0>(DATA_TYPE_LIST); | ||
| 47 | +static constexpr auto& BS_DATA_TYPE_LIST = std::get<1>(DATA_TYPE_LIST); | ||
| 48 | +static constexpr auto& CROPS_DATA_TYPE_LIST = std::get<2>(DATA_TYPE_LIST); | ||
| 49 | +static const auto DATA_FORMAT_LIST = std::vector<ge::Format>(DATA_TYPE_COMBINE_COUNT, ge::FORMAT_ND); | ||
| 50 | + | ||
| 51 | +class BatchToSpaceND : public OpDef { | ||
| 52 | +public: | ||
| 53 | + explicit BatchToSpaceND(const char* name) : OpDef(name) | ||
| 54 | + { | ||
| 55 | + this->Input("x") | ||
| 56 | + .ParamType(REQUIRED) | ||
| 57 | + .DataType(std::vector<ge::DataType>(X_DATA_TYPE_LIST.begin(), X_DATA_TYPE_LIST.end())) | ||
| 58 | + .Format(DATA_FORMAT_LIST); | ||
| 59 | + // block_shape 参数(1D 张量) | ||
| 60 | + this->Input("block_shape") | ||
| 61 | + .ParamType(REQUIRED) | ||
| 62 | + .DataType(std::vector<ge::DataType>(BS_DATA_TYPE_LIST.begin(), BS_DATA_TYPE_LIST.end())) | ||
| 63 | + .Format(DATA_FORMAT_LIST); | ||
| 64 | + // crops 参数(2D 张量) | ||
| 65 | + this->Input("crops") | ||
| 66 | + .ParamType(REQUIRED) | ||
| 67 | + .DataType(std::vector<ge::DataType>(CROPS_DATA_TYPE_LIST.begin(), CROPS_DATA_TYPE_LIST.end())) | ||
| 68 | + .Format(DATA_FORMAT_LIST); | ||
| 69 | + // 输出张量 y | ||
| 70 | + this->Output("y").Follow("x"); | ||
| 71 | + | ||
| 72 | + OpAICoreConfig aicore_config; | ||
| 73 | + aicore_config.DynamicCompileStaticFlag(true) | ||
| 74 | + .DynamicFormatFlag(false) | ||
| 75 | + .DynamicRankSupportFlag(true) | ||
| 76 | + .DynamicShapeSupportFlag(true) | ||
| 77 | + .NeedCheckSupportFlag(false) | ||
| 78 | + .ExtendCfgInfo("opFile.value", "batch_to_space_nd_apt"); | ||
| 79 | + | ||
| 80 | + this->AICore().AddConfig("ascend950", aicore_config); | ||
| 81 | + } | ||
| 82 | +}; | ||
| 83 | + | ||
| 84 | +OP_ADD(BatchToSpaceND); | ||
| 85 | +} // namespace ops | ||
| @@ -0,0 +1,142 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +using namespace ge; | ||
| 18 | +namespace ops { | ||
| 19 | +// 输入索引 | ||
| 20 | +static constexpr size_t INPUT_IDX_X = 0; | ||
| 21 | +static constexpr size_t INPUT_IDX_BLOCK_SHAPE = 1; | ||
| 22 | +static constexpr size_t INPUT_IDX_CROPS = 2; | ||
| 23 | +// 输出索引 | ||
| 24 | +static constexpr size_t OUTPUT_IDX_Y = 0; | ||
| 25 | +// 未知维度值 | ||
| 26 | +static constexpr int64_t UNKNOWN_DIM = -1; | ||
| 27 | +// crops 第二维的长度 | ||
| 28 | +static constexpr size_t CROPS_LENGTH = 2; | ||
| 29 | + | ||
| 30 | +class BatchToSpaceNDInferShapeHelper { | ||
| 31 | +public: | ||
| 32 | + explicit BatchToSpaceNDInferShapeHelper(gert::InferShapeContext* context) : context_(context) | ||
| 33 | + {} | ||
| 34 | + | ||
| 35 | + ge::graphStatus Inference(); | ||
| 36 | + | ||
| 37 | +private: | ||
| 38 | + ge::graphStatus Init(); | ||
| 39 | + | ||
| 40 | +private: | ||
| 41 | + gert::InferShapeContext* context_; | ||
| 42 | + const gert::Shape* xShape_{nullptr}; | ||
| 43 | + gert::Shape* yShape_{nullptr}; | ||
| 44 | + size_t blockNum_; | ||
| 45 | + gert::Shape blockVec_; | ||
| 46 | + gert::Shape cropsVec_; | ||
| 47 | + bool isConstBlock_; | ||
| 48 | + bool isConstCrops_; | ||
| 49 | +}; | ||
| 50 | + | ||
| 51 | +ge::graphStatus BatchToSpaceNDInferShapeHelper::Init() | ||
| 52 | +{ | ||
| 53 | + xShape_ = context_->GetInputShape(INPUT_IDX_X); | ||
| 54 | + OP_CHECK_NULL_WITH_CONTEXT(context_, xShape_); | ||
| 55 | + | ||
| 56 | + const gert::Tensor* blockTensor = context_->GetInputTensor(INPUT_IDX_BLOCK_SHAPE); | ||
| 57 | + OP_CHECK_NULL_WITH_CONTEXT(context_, blockTensor); | ||
| 58 | + blockNum_ = blockTensor->GetShapeSize(); | ||
| 59 | + | ||
| 60 | + const gert::Tensor* cropsTensor = context_->GetInputTensor(INPUT_IDX_CROPS); | ||
| 61 | + OP_CHECK_NULL_WITH_CONTEXT(context_, cropsTensor); | ||
| 62 | + | ||
| 63 | + yShape_ = context_->GetOutputShape(OUTPUT_IDX_Y); | ||
| 64 | + OP_CHECK_NULL_WITH_CONTEXT(context_, yShape_); | ||
| 65 | + | ||
| 66 | + isConstBlock_ = false; | ||
| 67 | + isConstCrops_ = false; | ||
| 68 | + if (IsConstTensor(blockTensor)) { | ||
| 69 | + isConstBlock_ = true; | ||
| 70 | + OP_CHECK_IF( | ||
| 71 | + !Ops::Base::GetConstIntToShape<gert::InferShapeContext>(context_, INPUT_IDX_BLOCK_SHAPE, blockVec_), | ||
| 72 | + OP_LOGE(context_, "get const block_shape data failed!"), return ge::GRAPH_FAILED); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + if (IsConstTensor(cropsTensor)) { | ||
| 76 | + isConstCrops_ = true; | ||
| 77 | + OP_CHECK_IF( | ||
| 78 | + !Ops::Base::GetConstIntToShape<gert::InferShapeContext>(context_, INPUT_IDX_CROPS, cropsVec_), | ||
| 79 | + OP_LOGE(context_, "get const crops data failed!"), return ge::GRAPH_FAILED); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + return ge::GRAPH_SUCCESS; | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +ge::graphStatus BatchToSpaceNDInferShapeHelper::Inference() | ||
| 86 | +{ | ||
| 87 | + auto ret = Init(); | ||
| 88 | + if (ret != ge::GRAPH_SUCCESS) { | ||
| 89 | + return ret; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + if (Ops::Base::IsUnknownRank(*xShape_) || !isConstBlock_) { | ||
| 93 | + Ops::Base::SetUnknownRank(*yShape_); | ||
| 94 | + return ge::GRAPH_SUCCESS; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + yShape_->SetDimNum(0); | ||
| 98 | + | ||
| 99 | + // batch | ||
| 100 | + int64_t batch = xShape_->GetDim(0); | ||
| 101 | + if (batch != UNKNOWN_DIM) { | ||
| 102 | + for (size_t i = 0; i < blockNum_; ++i) { | ||
| 103 | + OP_CHECK_IF( | ||
| 104 | + blockVec_.GetDim(i) == 0, | ||
| 105 | + OP_LOGE( | ||
| 106 | + context_, "block_value has 0 data which is not supported, but get %s", | ||
| 107 | + Ops::Base::ToString(blockVec_).c_str()), | ||
| 108 | + return ge::GRAPH_FAILED); | ||
| 109 | + batch = batch / blockVec_.GetDim(i); | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + yShape_->AppendDim(batch); | ||
| 113 | + | ||
| 114 | + // spatial shape | ||
| 115 | + for (size_t i = 1; i <= blockNum_; ++i) { | ||
| 116 | + size_t j = i - 1; | ||
| 117 | + if (xShape_->GetDim(i) != UNKNOWN_DIM && isConstCrops_) { | ||
| 118 | + int64_t totalCrop = cropsVec_.GetDim(CROPS_LENGTH * j) + cropsVec_.GetDim(CROPS_LENGTH * j + 1); | ||
| 119 | + yShape_->AppendDim(xShape_->GetDim(i) * blockVec_.GetDim(j) - totalCrop); | ||
| 120 | + } else { | ||
| 121 | + yShape_->AppendDim(UNKNOWN_DIM); | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + // remain shape | ||
| 126 | + for (size_t i = blockNum_ + 1; i < xShape_->GetDimNum(); ++i) { | ||
| 127 | + yShape_->AppendDim(xShape_->GetDim(i)); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + return ge::GRAPH_SUCCESS; | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +static ge::graphStatus Infershape4BatchToSpaceND(gert::InferShapeContext* context) | ||
| 134 | +{ | ||
| 135 | + BatchToSpaceNDInferShapeHelper helper(context); | ||
| 136 | + return helper.Inference(); | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +IMPL_OP_INFERSHAPE(BatchToSpaceND) | ||
| 140 | + .InferShape(Infershape4BatchToSpaceND) | ||
| 141 | + .InputsDataDependency({INPUT_IDX_BLOCK_SHAPE, INPUT_IDX_CROPS}); | ||
| 142 | +} // namespace ops | ||
| @@ -0,0 +1,853 @@ | |||
| 1 | +{ | ||
| 2 | + "op_type": "BatchToSpaceND", | ||
| 3 | + "op_list": [ | ||
| 4 | + { | ||
| 5 | + "bin_filename": "BatchToSpaceND_1B_int32_int32", | ||
| 6 | + "inputs": [ | ||
| 7 | + { | ||
| 8 | + "name": "x", | ||
| 9 | + "index": 0, | ||
| 10 | + "dtype": "int8", | ||
| 11 | + "format": "ND", | ||
| 12 | + "paramType": "required", | ||
| 13 | + "shape": [ | ||
| 14 | + -2 | ||
| 15 | + ], | ||
| 16 | + "format_match_mode": "FormatAgnostic", | ||
| 17 | + "dtype_match_mode": "DtypeByte" | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + "name": "block_shape", | ||
| 21 | + "index": 1, | ||
| 22 | + "dtype": "int32", | ||
| 23 | + "format": "ND", | ||
| 24 | + "paramType": "required", | ||
| 25 | + "shape": [ | ||
| 26 | + -2 | ||
| 27 | + ], | ||
| 28 | + "format_match_mode": "FormatAgnostic" | ||
| 29 | + }, | ||
| 30 | + { | ||
| 31 | + "name": "crops", | ||
| 32 | + "index": 2, | ||
| 33 | + "dtype": "int32", | ||
| 34 | + "format": "ND", | ||
| 35 | + "paramType": "required", | ||
| 36 | + "shape": [ | ||
| 37 | + -2 | ||
| 38 | + ], | ||
| 39 | + "format_match_mode": "FormatAgnostic" | ||
| 40 | + } | ||
| 41 | + ], | ||
| 42 | + "outputs": [ | ||
| 43 | + { | ||
| 44 | + "name": "y", | ||
| 45 | + "index": 0, | ||
| 46 | + "dtype": "int8", | ||
| 47 | + "format": "ND", | ||
| 48 | + "paramType": "required", | ||
| 49 | + "shape": [ | ||
| 50 | + -2 | ||
| 51 | + ], | ||
| 52 | + "format_match_mode": "FormatAgnostic", | ||
| 53 | + "dtype_match_mode": "DtypeByte" | ||
| 54 | + } | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + { | ||
| 58 | + "bin_filename": "BatchToSpaceND_1B_int32_int64", | ||
| 59 | + "inputs": [ | ||
| 60 | + { | ||
| 61 | + "name": "x", | ||
| 62 | + "index": 0, | ||
| 63 | + "dtype": "int8", | ||
| 64 | + "format": "ND", | ||
| 65 | + "paramType": "required", | ||
| 66 | + "shape": [ | ||
| 67 | + -2 | ||
| 68 | + ], | ||
| 69 | + "format_match_mode": "FormatAgnostic", | ||
| 70 | + "dtype_match_mode": "DtypeByte" | ||
| 71 | + }, | ||
| 72 | + { | ||
| 73 | + "name": "block_shape", | ||
| 74 | + "index": 1, | ||
| 75 | + "dtype": "int32", | ||
| 76 | + "format": "ND", | ||
| 77 | + "paramType": "required", | ||
| 78 | + "shape": [ | ||
| 79 | + -2 | ||
| 80 | + ], | ||
| 81 | + "format_match_mode": "FormatAgnostic" | ||
| 82 | + }, | ||
| 83 | + { | ||
| 84 | + "name": "crops", | ||
| 85 | + "index": 2, | ||
| 86 | + "dtype": "int64", | ||
| 87 | + "format": "ND", | ||
| 88 | + "paramType": "required", | ||
| 89 | + "shape": [ | ||
| 90 | + -2 | ||
| 91 | + ], | ||
| 92 | + "format_match_mode": "FormatAgnostic" | ||
| 93 | + } | ||
| 94 | + ], | ||
| 95 | + "outputs": [ | ||
| 96 | + { | ||
| 97 | + "name": "y", | ||
| 98 | + "index": 0, | ||
| 99 | + "dtype": "int8", | ||
| 100 | + "format": "ND", | ||
| 101 | + "paramType": "required", | ||
| 102 | + "shape": [ | ||
| 103 | + -2 | ||
| 104 | + ], | ||
| 105 | + "format_match_mode": "FormatAgnostic", | ||
| 106 | + "dtype_match_mode": "DtypeByte" | ||
| 107 | + } | ||
| 108 | + ] | ||
| 109 | + }, | ||
| 110 | + { | ||
| 111 | + "bin_filename": "BatchToSpaceND_1B_int64_int32", | ||
| 112 | + "inputs": [ | ||
| 113 | + { | ||
| 114 | + "name": "x", | ||
| 115 | + "index": 0, | ||
| 116 | + "dtype": "int8", | ||
| 117 | + "format": "ND", | ||
| 118 | + "paramType": "required", | ||
| 119 | + "shape": [ | ||
| 120 | + -2 | ||
| 121 | + ], | ||
| 122 | + "format_match_mode": "FormatAgnostic", | ||
| 123 | + "dtype_match_mode": "DtypeByte" | ||
| 124 | + }, | ||
| 125 | + { | ||
| 126 | + "name": "block_shape", | ||
| 127 | + "index": 1, | ||
| 128 | + "dtype": "int64", | ||
| 129 | + "format": "ND", | ||
| 130 | + "paramType": "required", | ||
| 131 | + "shape": [ | ||
| 132 | + -2 | ||
| 133 | + ], | ||
| 134 | + "format_match_mode": "FormatAgnostic" | ||
| 135 | + }, | ||
| 136 | + { | ||
| 137 | + "name": "crops", | ||
| 138 | + "index": 2, | ||
| 139 | + "dtype": "int32", | ||
| 140 | + "format": "ND", | ||
| 141 | + "paramType": "required", | ||
| 142 | + "shape": [ | ||
| 143 | + -2 | ||
| 144 | + ], | ||
| 145 | + "format_match_mode": "FormatAgnostic" | ||
| 146 | + } | ||
| 147 | + ], | ||
| 148 | + "outputs": [ | ||
| 149 | + { | ||
| 150 | + "name": "y", | ||
| 151 | + "index": 0, | ||
| 152 | + "dtype": "int8", | ||
| 153 | + "format": "ND", | ||
| 154 | + "paramType": "required", | ||
| 155 | + "shape": [ | ||
| 156 | + -2 | ||
| 157 | + ], | ||
| 158 | + "format_match_mode": "FormatAgnostic", | ||
| 159 | + "dtype_match_mode": "DtypeByte" | ||
| 160 | + } | ||
| 161 | + ] | ||
| 162 | + }, | ||
| 163 | + { | ||
| 164 | + "bin_filename": "BatchToSpaceND_1B_int64_int64", | ||
| 165 | + "inputs": [ | ||
| 166 | + { | ||
| 167 | + "name": "x", | ||
| 168 | + "index": 0, | ||
| 169 | + "dtype": "int8", | ||
| 170 | + "format": "ND", | ||
| 171 | + "paramType": "required", | ||
| 172 | + "shape": [ | ||
| 173 | + -2 | ||
| 174 | + ], | ||
| 175 | + "format_match_mode": "FormatAgnostic", | ||
| 176 | + "dtype_match_mode": "DtypeByte" | ||
| 177 | + }, | ||
| 178 | + { | ||
| 179 | + "name": "block_shape", | ||
| 180 | + "index": 1, | ||
| 181 | + "dtype": "int64", | ||
| 182 | + "format": "ND", | ||
| 183 | + "paramType": "required", | ||
| 184 | + "shape": [ | ||
| 185 | + -2 | ||
| 186 | + ], | ||
| 187 | + "format_match_mode": "FormatAgnostic" | ||
| 188 | + }, | ||
| 189 | + { | ||
| 190 | + "name": "crops", | ||
| 191 | + "index": 2, | ||
| 192 | + "dtype": "int64", | ||
| 193 | + "format": "ND", | ||
| 194 | + "paramType": "required", | ||
| 195 | + "shape": [ | ||
| 196 | + -2 | ||
| 197 | + ], | ||
| 198 | + "format_match_mode": "FormatAgnostic" | ||
| 199 | + } | ||
| 200 | + ], | ||
| 201 | + "outputs": [ | ||
| 202 | + { | ||
| 203 | + "name": "y", | ||
| 204 | + "index": 0, | ||
| 205 | + "dtype": "int8", | ||
| 206 | + "format": "ND", | ||
| 207 | + "paramType": "required", | ||
| 208 | + "shape": [ | ||
| 209 | + -2 | ||
| 210 | + ], | ||
| 211 | + "format_match_mode": "FormatAgnostic", | ||
| 212 | + "dtype_match_mode": "DtypeByte" | ||
| 213 | + } | ||
| 214 | + ] | ||
| 215 | + }, | ||
| 216 | + { | ||
| 217 | + "bin_filename": "BatchToSpaceND_2B_int32_int32", | ||
| 218 | + "inputs": [ | ||
| 219 | + { | ||
| 220 | + "name": "x", | ||
| 221 | + "index": 0, | ||
| 222 | + "dtype": "float16", | ||
| 223 | + "format": "ND", | ||
| 224 | + "paramType": "required", | ||
| 225 | + "shape": [ | ||
| 226 | + -2 | ||
| 227 | + ], | ||
| 228 | + "format_match_mode": "FormatAgnostic", | ||
| 229 | + "dtype_match_mode": "DtypeByte" | ||
| 230 | + }, | ||
| 231 | + { | ||
| 232 | + "name": "block_shape", | ||
| 233 | + "index": 1, | ||
| 234 | + "dtype": "int32", | ||
| 235 | + "format": "ND", | ||
| 236 | + "paramType": "required", | ||
| 237 | + "shape": [ | ||
| 238 | + -2 | ||
| 239 | + ], | ||
| 240 | + "format_match_mode": "FormatAgnostic" | ||
| 241 | + }, | ||
| 242 | + { | ||
| 243 | + "name": "crops", | ||
| 244 | + "index": 2, | ||
| 245 | + "dtype": "int32", | ||
| 246 | + "format": "ND", | ||
| 247 | + "paramType": "required", | ||
| 248 | + "shape": [ | ||
| 249 | + -2 | ||
| 250 | + ], | ||
| 251 | + "format_match_mode": "FormatAgnostic" | ||
| 252 | + } | ||
| 253 | + ], | ||
| 254 | + "outputs": [ | ||
| 255 | + { | ||
| 256 | + "name": "y", | ||
| 257 | + "index": 0, | ||
| 258 | + "dtype": "float16", | ||
| 259 | + "format": "ND", | ||
| 260 | + "paramType": "required", | ||
| 261 | + "shape": [ | ||
| 262 | + -2 | ||
| 263 | + ], | ||
| 264 | + "format_match_mode": "FormatAgnostic", | ||
| 265 | + "dtype_match_mode": "DtypeByte" | ||
| 266 | + } | ||
| 267 | + ] | ||
| 268 | + }, | ||
| 269 | + { | ||
| 270 | + "bin_filename": "BatchToSpaceND_2B_int32_int64", | ||
| 271 | + "inputs": [ | ||
| 272 | + { | ||
| 273 | + "name": "x", | ||
| 274 | + "index": 0, | ||
| 275 | + "dtype": "float16", | ||
| 276 | + "format": "ND", | ||
| 277 | + "paramType": "required", | ||
| 278 | + "shape": [ | ||
| 279 | + -2 | ||
| 280 | + ], | ||
| 281 | + "format_match_mode": "FormatAgnostic", | ||
| 282 | + "dtype_match_mode": "DtypeByte" | ||
| 283 | + }, | ||
| 284 | + { | ||
| 285 | + "name": "block_shape", | ||
| 286 | + "index": 1, | ||
| 287 | + "dtype": "int32", | ||
| 288 | + "format": "ND", | ||
| 289 | + "paramType": "required", | ||
| 290 | + "shape": [ | ||
| 291 | + -2 | ||
| 292 | + ], | ||
| 293 | + "format_match_mode": "FormatAgnostic" | ||
| 294 | + }, | ||
| 295 | + { | ||
| 296 | + "name": "crops", | ||
| 297 | + "index": 2, | ||
| 298 | + "dtype": "int64", | ||
| 299 | + "format": "ND", | ||
| 300 | + "paramType": "required", | ||
| 301 | + "shape": [ | ||
| 302 | + -2 | ||
| 303 | + ], | ||
| 304 | + "format_match_mode": "FormatAgnostic" | ||
| 305 | + } | ||
| 306 | + ], | ||
| 307 | + "outputs": [ | ||
| 308 | + { | ||
| 309 | + "name": "y", | ||
| 310 | + "index": 0, | ||
| 311 | + "dtype": "float16", | ||
| 312 | + "format": "ND", | ||
| 313 | + "paramType": "required", | ||
| 314 | + "shape": [ | ||
| 315 | + -2 | ||
| 316 | + ], | ||
| 317 | + "format_match_mode": "FormatAgnostic", | ||
| 318 | + "dtype_match_mode": "DtypeByte" | ||
| 319 | + } | ||
| 320 | + ] | ||
| 321 | + }, | ||
| 322 | + { | ||
| 323 | + "bin_filename": "BatchToSpaceND_2B_int64_int32", | ||
| 324 | + "inputs": [ | ||
| 325 | + { | ||
| 326 | + "name": "x", | ||
| 327 | + "index": 0, | ||
| 328 | + "dtype": "float16", | ||
| 329 | + "format": "ND", | ||
| 330 | + "paramType": "required", | ||
| 331 | + "shape": [ | ||
| 332 | + -2 | ||
| 333 | + ], | ||
| 334 | + "format_match_mode": "FormatAgnostic", | ||
| 335 | + "dtype_match_mode": "DtypeByte" | ||
| 336 | + }, | ||
| 337 | + { | ||
| 338 | + "name": "block_shape", | ||
| 339 | + "index": 1, | ||
| 340 | + "dtype": "int64", | ||
| 341 | + "format": "ND", | ||
| 342 | + "paramType": "required", | ||
| 343 | + "shape": [ | ||
| 344 | + -2 | ||
| 345 | + ], | ||
| 346 | + "format_match_mode": "FormatAgnostic" | ||
| 347 | + }, | ||
| 348 | + { | ||
| 349 | + "name": "crops", | ||
| 350 | + "index": 2, | ||
| 351 | + "dtype": "int32", | ||
| 352 | + "format": "ND", | ||
| 353 | + "paramType": "required", | ||
| 354 | + "shape": [ | ||
| 355 | + -2 | ||
| 356 | + ], | ||
| 357 | + "format_match_mode": "FormatAgnostic" | ||
| 358 | + } | ||
| 359 | + ], | ||
| 360 | + "outputs": [ | ||
| 361 | + { | ||
| 362 | + "name": "y", | ||
| 363 | + "index": 0, | ||
| 364 | + "dtype": "float16", | ||
| 365 | + "format": "ND", | ||
| 366 | + "paramType": "required", | ||
| 367 | + "shape": [ | ||
| 368 | + -2 | ||
| 369 | + ], | ||
| 370 | + "format_match_mode": "FormatAgnostic", | ||
| 371 | + "dtype_match_mode": "DtypeByte" | ||
| 372 | + } | ||
| 373 | + ] | ||
| 374 | + }, | ||
| 375 | + { | ||
| 376 | + "bin_filename": "BatchToSpaceND_2B_int64_int64", | ||
| 377 | + "inputs": [ | ||
| 378 | + { | ||
| 379 | + "name": "x", | ||
| 380 | + "index": 0, | ||
| 381 | + "dtype": "float16", | ||
| 382 | + "format": "ND", | ||
| 383 | + "paramType": "required", | ||
| 384 | + "shape": [ | ||
| 385 | + -2 | ||
| 386 | + ], | ||
| 387 | + "format_match_mode": "FormatAgnostic", | ||
| 388 | + "dtype_match_mode": "DtypeByte" | ||
| 389 | + }, | ||
| 390 | + { | ||
| 391 | + "name": "block_shape", | ||
| 392 | + "index": 1, | ||
| 393 | + "dtype": "int64", | ||
| 394 | + "format": "ND", | ||
| 395 | + "paramType": "required", | ||
| 396 | + "shape": [ | ||
| 397 | + -2 | ||
| 398 | + ], | ||
| 399 | + "format_match_mode": "FormatAgnostic" | ||
| 400 | + }, | ||
| 401 | + { | ||
| 402 | + "name": "crops", | ||
| 403 | + "index": 2, | ||
| 404 | + "dtype": "int64", | ||
| 405 | + "format": "ND", | ||
| 406 | + "paramType": "required", | ||
| 407 | + "shape": [ | ||
| 408 | + -2 | ||
| 409 | + ], | ||
| 410 | + "format_match_mode": "FormatAgnostic" | ||
| 411 | + } | ||
| 412 | + ], | ||
| 413 | + "outputs": [ | ||
| 414 | + { | ||
| 415 | + "name": "y", | ||
| 416 | + "index": 0, | ||
| 417 | + "dtype": "float16", | ||
| 418 | + "format": "ND", | ||
| 419 | + "paramType": "required", | ||
| 420 | + "shape": [ | ||
| 421 | + -2 | ||
| 422 | + ], | ||
| 423 | + "format_match_mode": "FormatAgnostic", | ||
| 424 | + "dtype_match_mode": "DtypeByte" | ||
| 425 | + } | ||
| 426 | + ] | ||
| 427 | + }, | ||
| 428 | + { | ||
| 429 | + "bin_filename": "BatchToSpaceND_4B_int32_int32", | ||
| 430 | + "inputs": [ | ||
| 431 | + { | ||
| 432 | + "name": "x", | ||
| 433 | + "index": 0, | ||
| 434 | + "dtype": "float32", | ||
| 435 | + "format": "ND", | ||
| 436 | + "paramType": "required", | ||
| 437 | + "shape": [ | ||
| 438 | + -2 | ||
| 439 | + ], | ||
| 440 | + "format_match_mode": "FormatAgnostic", | ||
| 441 | + "dtype_match_mode": "DtypeByte" | ||
| 442 | + }, | ||
| 443 | + { | ||
| 444 | + "name": "block_shape", | ||
| 445 | + "index": 1, | ||
| 446 | + "dtype": "int32", | ||
| 447 | + "format": "ND", | ||
| 448 | + "paramType": "required", | ||
| 449 | + "shape": [ | ||
| 450 | + -2 | ||
| 451 | + ], | ||
| 452 | + "format_match_mode": "FormatAgnostic" | ||
| 453 | + }, | ||
| 454 | + { | ||
| 455 | + "name": "crops", | ||
| 456 | + "index": 2, | ||
| 457 | + "dtype": "int32", | ||
| 458 | + "format": "ND", | ||
| 459 | + "paramType": "required", | ||
| 460 | + "shape": [ | ||
| 461 | + -2 | ||
| 462 | + ], | ||
| 463 | + "format_match_mode": "FormatAgnostic" | ||
| 464 | + } | ||
| 465 | + ], | ||
| 466 | + "outputs": [ | ||
| 467 | + { | ||
| 468 | + "name": "y", | ||
| 469 | + "index": 0, | ||
| 470 | + "dtype": "float32", | ||
| 471 | + "format": "ND", | ||
| 472 | + "paramType": "required", | ||
| 473 | + "shape": [ | ||
| 474 | + -2 | ||
| 475 | + ], | ||
| 476 | + "format_match_mode": "FormatAgnostic", | ||
| 477 | + "dtype_match_mode": "DtypeByte" | ||
| 478 | + } | ||
| 479 | + ] | ||
| 480 | + }, | ||
| 481 | + { | ||
| 482 | + "bin_filename": "BatchToSpaceND_4B_int32_int64", | ||
| 483 | + "inputs": [ | ||
| 484 | + { | ||
| 485 | + "name": "x", | ||
| 486 | + "index": 0, | ||
| 487 | + "dtype": "float32", | ||
| 488 | + "format": "ND", | ||
| 489 | + "paramType": "required", | ||
| 490 | + "shape": [ | ||
| 491 | + -2 | ||
| 492 | + ], | ||
| 493 | + "format_match_mode": "FormatAgnostic", | ||
| 494 | + "dtype_match_mode": "DtypeByte" | ||
| 495 | + }, | ||
| 496 | + { | ||
| 497 | + "name": "block_shape", | ||
| 498 | + "index": 1, | ||
| 499 | + "dtype": "int32", | ||
| 500 | + "format": "ND", | ||
| 501 | + "paramType": "required", | ||
| 502 | + "shape": [ | ||
| 503 | + -2 | ||
| 504 | + ], | ||
| 505 | + "format_match_mode": "FormatAgnostic" | ||
| 506 | + }, | ||
| 507 | + { | ||
| 508 | + "name": "crops", | ||
| 509 | + "index": 2, | ||
| 510 | + "dtype": "int64", | ||
| 511 | + "format": "ND", | ||
| 512 | + "paramType": "required", | ||
| 513 | + "shape": [ | ||
| 514 | + -2 | ||
| 515 | + ], | ||
| 516 | + "format_match_mode": "FormatAgnostic" | ||
| 517 | + } | ||
| 518 | + ], | ||
| 519 | + "outputs": [ | ||
| 520 | + { | ||
| 521 | + "name": "y", | ||
| 522 | + "index": 0, | ||
| 523 | + "dtype": "float32", | ||
| 524 | + "format": "ND", | ||
| 525 | + "paramType": "required", | ||
| 526 | + "shape": [ | ||
| 527 | + -2 | ||
| 528 | + ], | ||
| 529 | + "format_match_mode": "FormatAgnostic", | ||
| 530 | + "dtype_match_mode": "DtypeByte" | ||
| 531 | + } | ||
| 532 | + ] | ||
| 533 | + }, | ||
| 534 | + { | ||
| 535 | + "bin_filename": "BatchToSpaceND_4B_int64_int32", | ||
| 536 | + "inputs": [ | ||
| 537 | + { | ||
| 538 | + "name": "x", | ||
| 539 | + "index": 0, | ||
| 540 | + "dtype": "float32", | ||
| 541 | + "format": "ND", | ||
| 542 | + "paramType": "required", | ||
| 543 | + "shape": [ | ||
| 544 | + -2 | ||
| 545 | + ], | ||
| 546 | + "format_match_mode": "FormatAgnostic", | ||
| 547 | + "dtype_match_mode": "DtypeByte" | ||
| 548 | + }, | ||
| 549 | + { | ||
| 550 | + "name": "block_shape", | ||
| 551 | + "index": 1, | ||
| 552 | + "dtype": "int64", | ||
| 553 | + "format": "ND", | ||
| 554 | + "paramType": "required", | ||
| 555 | + "shape": [ | ||
| 556 | + -2 | ||
| 557 | + ], | ||
| 558 | + "format_match_mode": "FormatAgnostic" | ||
| 559 | + }, | ||
| 560 | + { | ||
| 561 | + "name": "crops", | ||
| 562 | + "index": 2, | ||
| 563 | + "dtype": "int32", | ||
| 564 | + "format": "ND", | ||
| 565 | + "paramType": "required", | ||
| 566 | + "shape": [ | ||
| 567 | + -2 | ||
| 568 | + ], | ||
| 569 | + "format_match_mode": "FormatAgnostic" | ||
| 570 | + } | ||
| 571 | + ], | ||
| 572 | + "outputs": [ | ||
| 573 | + { | ||
| 574 | + "name": "y", | ||
| 575 | + "index": 0, | ||
| 576 | + "dtype": "float32", | ||
| 577 | + "format": "ND", | ||
| 578 | + "paramType": "required", | ||
| 579 | + "shape": [ | ||
| 580 | + -2 | ||
| 581 | + ], | ||
| 582 | + "format_match_mode": "FormatAgnostic", | ||
| 583 | + "dtype_match_mode": "DtypeByte" | ||
| 584 | + } | ||
| 585 | + ] | ||
| 586 | + }, | ||
| 587 | + { | ||
| 588 | + "bin_filename": "BatchToSpaceND_4B_int64_int64", | ||
| 589 | + "inputs": [ | ||
| 590 | + { | ||
| 591 | + "name": "x", | ||
| 592 | + "index": 0, | ||
| 593 | + "dtype": "float32", | ||
| 594 | + "format": "ND", | ||
| 595 | + "paramType": "required", | ||
| 596 | + "shape": [ | ||
| 597 | + -2 | ||
| 598 | + ], | ||
| 599 | + "format_match_mode": "FormatAgnostic", | ||
| 600 | + "dtype_match_mode": "DtypeByte" | ||
| 601 | + }, | ||
| 602 | + { | ||
| 603 | + "name": "block_shape", | ||
| 604 | + "index": 1, | ||
| 605 | + "dtype": "int64", | ||
| 606 | + "format": "ND", | ||
| 607 | + "paramType": "required", | ||
| 608 | + "shape": [ | ||
| 609 | + -2 | ||
| 610 | + ], | ||
| 611 | + "format_match_mode": "FormatAgnostic" | ||
| 612 | + }, | ||
| 613 | + { | ||
| 614 | + "name": "crops", | ||
| 615 | + "index": 2, | ||
| 616 | + "dtype": "int64", | ||
| 617 | + "format": "ND", | ||
| 618 | + "paramType": "required", | ||
| 619 | + "shape": [ | ||
| 620 | + -2 | ||
| 621 | + ], | ||
| 622 | + "format_match_mode": "FormatAgnostic" | ||
| 623 | + } | ||
| 624 | + ], | ||
| 625 | + "outputs": [ | ||
| 626 | + { | ||
| 627 | + "name": "y", | ||
| 628 | + "index": 0, | ||
| 629 | + "dtype": "float32", | ||
| 630 | + "format": "ND", | ||
| 631 | + "paramType": "required", | ||
| 632 | + "shape": [ | ||
| 633 | + -2 | ||
| 634 | + ], | ||
| 635 | + "format_match_mode": "FormatAgnostic", | ||
| 636 | + "dtype_match_mode": "DtypeByte" | ||
| 637 | + } | ||
| 638 | + ] | ||
| 639 | + }, | ||
| 640 | + { | ||
| 641 | + "bin_filename": "BatchToSpaceND_8B_int32_int32", | ||
| 642 | + "inputs": [ | ||
| 643 | + { | ||
| 644 | + "name": "x", | ||
| 645 | + "index": 0, | ||
| 646 | + "dtype": "int64", | ||
| 647 | + "format": "ND", | ||
| 648 | + "paramType": "required", | ||
| 649 | + "shape": [ | ||
| 650 | + -2 | ||
| 651 | + ], | ||
| 652 | + "format_match_mode": "FormatAgnostic", | ||
| 653 | + "dtype_match_mode": "DtypeByte" | ||
| 654 | + }, | ||
| 655 | + { | ||
| 656 | + "name": "block_shape", | ||
| 657 | + "index": 1, | ||
| 658 | + "dtype": "int32", | ||
| 659 | + "format": "ND", | ||
| 660 | + "paramType": "required", | ||
| 661 | + "shape": [ | ||
| 662 | + -2 | ||
| 663 | + ], | ||
| 664 | + "format_match_mode": "FormatAgnostic" | ||
| 665 | + }, | ||
| 666 | + { | ||
| 667 | + "name": "crops", | ||
| 668 | + "index": 2, | ||
| 669 | + "dtype": "int32", | ||
| 670 | + "format": "ND", | ||
| 671 | + "paramType": "required", | ||
| 672 | + "shape": [ | ||
| 673 | + -2 | ||
| 674 | + ], | ||
| 675 | + "format_match_mode": "FormatAgnostic" | ||
| 676 | + } | ||
| 677 | + ], | ||
| 678 | + "outputs": [ | ||
| 679 | + { | ||
| 680 | + "name": "y", | ||
| 681 | + "index": 0, | ||
| 682 | + "dtype": "int64", | ||
| 683 | + "format": "ND", | ||
| 684 | + "paramType": "required", | ||
| 685 | + "shape": [ | ||
| 686 | + -2 | ||
| 687 | + ], | ||
| 688 | + "format_match_mode": "FormatAgnostic", | ||
| 689 | + "dtype_match_mode": "DtypeByte" | ||
| 690 | + } | ||
| 691 | + ] | ||
| 692 | + }, | ||
| 693 | + { | ||
| 694 | + "bin_filename": "BatchToSpaceND_8B_int32_int64", | ||
| 695 | + "inputs": [ | ||
| 696 | + { | ||
| 697 | + "name": "x", | ||
| 698 | + "index": 0, | ||
| 699 | + "dtype": "int64", | ||
| 700 | + "format": "ND", | ||
| 701 | + "paramType": "required", | ||
| 702 | + "shape": [ | ||
| 703 | + -2 | ||
| 704 | + ], | ||
| 705 | + "format_match_mode": "FormatAgnostic", | ||
| 706 | + "dtype_match_mode": "DtypeByte" | ||
| 707 | + }, | ||
| 708 | + { | ||
| 709 | + "name": "block_shape", | ||
| 710 | + "index": 1, | ||
| 711 | + "dtype": "int32", | ||
| 712 | + "format": "ND", | ||
| 713 | + "paramType": "required", | ||
| 714 | + "shape": [ | ||
| 715 | + -2 | ||
| 716 | + ], | ||
| 717 | + "format_match_mode": "FormatAgnostic" | ||
| 718 | + }, | ||
| 719 | + { | ||
| 720 | + "name": "crops", | ||
| 721 | + "index": 2, | ||
| 722 | + "dtype": "int64", | ||
| 723 | + "format": "ND", | ||
| 724 | + "paramType": "required", | ||
| 725 | + "shape": [ | ||
| 726 | + -2 | ||
| 727 | + ], | ||
| 728 | + "format_match_mode": "FormatAgnostic" | ||
| 729 | + } | ||
| 730 | + ], | ||
| 731 | + "outputs": [ | ||
| 732 | + { | ||
| 733 | + "name": "y", | ||
| 734 | + "index": 0, | ||
| 735 | + "dtype": "int64", | ||
| 736 | + "format": "ND", | ||
| 737 | + "paramType": "required", | ||
| 738 | + "shape": [ | ||
| 739 | + -2 | ||
| 740 | + ], | ||
| 741 | + "format_match_mode": "FormatAgnostic", | ||
| 742 | + "dtype_match_mode": "DtypeByte" | ||
| 743 | + } | ||
| 744 | + ] | ||
| 745 | + }, | ||
| 746 | + { | ||
| 747 | + "bin_filename": "BatchToSpaceND_8B_int64_int32", | ||
| 748 | + "inputs": [ | ||
| 749 | + { | ||
| 750 | + "name": "x", | ||
| 751 | + "index": 0, | ||
| 752 | + "dtype": "int64", | ||
| 753 | + "format": "ND", | ||
| 754 | + "paramType": "required", | ||
| 755 | + "shape": [ | ||
| 756 | + -2 | ||
| 757 | + ], | ||
| 758 | + "format_match_mode": "FormatAgnostic", | ||
| 759 | + "dtype_match_mode": "DtypeByte" | ||
| 760 | + }, | ||
| 761 | + { | ||
| 762 | + "name": "block_shape", | ||
| 763 | + "index": 1, | ||
| 764 | + "dtype": "int64", | ||
| 765 | + "format": "ND", | ||
| 766 | + "paramType": "required", | ||
| 767 | + "shape": [ | ||
| 768 | + -2 | ||
| 769 | + ], | ||
| 770 | + "format_match_mode": "FormatAgnostic" | ||
| 771 | + }, | ||
| 772 | + { | ||
| 773 | + "name": "crops", | ||
| 774 | + "index": 2, | ||
| 775 | + "dtype": "int32", | ||
| 776 | + "format": "ND", | ||
| 777 | + "paramType": "required", | ||
| 778 | + "shape": [ | ||
| 779 | + -2 | ||
| 780 | + ], | ||
| 781 | + "format_match_mode": "FormatAgnostic" | ||
| 782 | + } | ||
| 783 | + ], | ||
| 784 | + "outputs": [ | ||
| 785 | + { | ||
| 786 | + "name": "y", | ||
| 787 | + "index": 0, | ||
| 788 | + "dtype": "int64", | ||
| 789 | + "format": "ND", | ||
| 790 | + "paramType": "required", | ||
| 791 | + "shape": [ | ||
| 792 | + -2 | ||
| 793 | + ], | ||
| 794 | + "format_match_mode": "FormatAgnostic", | ||
| 795 | + "dtype_match_mode": "DtypeByte" | ||
| 796 | + } | ||
| 797 | + ] | ||
| 798 | + }, | ||
| 799 | + { | ||
| 800 | + "bin_filename": "BatchToSpaceND_8B_int64_int64", | ||
| 801 | + "inputs": [ | ||
| 802 | + { | ||
| 803 | + "name": "x", | ||
| 804 | + "index": 0, | ||
| 805 | + "dtype": "int64", | ||
| 806 | + "format": "ND", | ||
| 807 | + "paramType": "required", | ||
| 808 | + "shape": [ | ||
| 809 | + -2 | ||
| 810 | + ], | ||
| 811 | + "format_match_mode": "FormatAgnostic", | ||
| 812 | + "dtype_match_mode": "DtypeByte" | ||
| 813 | + }, | ||
| 814 | + { | ||
| 815 | + "name": "block_shape", | ||
| 816 | + "index": 1, | ||
| 817 | + "dtype": "int64", | ||
| 818 | + "format": "ND", | ||
| 819 | + "paramType": "required", | ||
| 820 | + "shape": [ | ||
| 821 | + -2 | ||
| 822 | + ], | ||
| 823 | + "format_match_mode": "FormatAgnostic" | ||
| 824 | + }, | ||
| 825 | + { | ||
| 826 | + "name": "crops", | ||
| 827 | + "index": 2, | ||
| 828 | + "dtype": "int64", | ||
| 829 | + "format": "ND", | ||
| 830 | + "paramType": "required", | ||
| 831 | + "shape": [ | ||
| 832 | + -2 | ||
| 833 | + ], | ||
| 834 | + "format_match_mode": "FormatAgnostic" | ||
| 835 | + } | ||
| 836 | + ], | ||
| 837 | + "outputs": [ | ||
| 838 | + { | ||
| 839 | + "name": "y", | ||
| 840 | + "index": 0, | ||
| 841 | + "dtype": "int64", | ||
| 842 | + "format": "ND", | ||
| 843 | + "paramType": "required", | ||
| 844 | + "shape": [ | ||
| 845 | + -2 | ||
| 846 | + ], | ||
| 847 | + "format_match_mode": "FormatAgnostic", | ||
| 848 | + "dtype_match_mode": "DtypeByte" | ||
| 849 | + } | ||
| 850 | + ] | ||
| 851 | + } | ||
| 852 | + ] | ||
| 853 | +} | ||
| @@ -0,0 +1,2 @@ | |||
| 1 | +[BatchToSpaceND] | ||
| 2 | +default=0 | ||


确认所有产品都支持?