已合并
strided_slice算子example补充 #595
hawdonz创建于 2025年12月30日
strided_slice算子example补充 #595
已合并
共 1 个文件变更+237-112
| @@ -7,136 +7,261 @@ | |||
| 7 | * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 7 | * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | - | 10 | + |
| 11 | 11 | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 12 | 15 | ||
| 13 | -#include "acl/acl.h" | 16 | +#include <string> |
| 14 | -#include "aclnnop/aclnn_slice.h" | 17 | +#include <map> |
| 18 | + | ||
| 15 | 19 | ||
| 16 | -#define CHECK_RET(cond, return_expr) \ | 20 | +#include "graph.h" |
| 17 | -do { \ | 21 | +#include "types.h" |
| 18 | - if (!(cond)) { \ | 22 | +#include "tensor.h" |
| 19 | - return_expr; \ | 23 | +#include "ge_error_codes.h" |
| 20 | - } \ | 24 | +#include "ge_api_types.h" |
| 21 | -} while (0) | 25 | +#include "ge_api.h" |
| 26 | + | ||
| 27 | + | ||
| 22 | 28 | ||
| 23 | -#define LOG_PRINT(message, ...) \ | 29 | +#include "experiment_ops.h" |
| 24 | -do { \ | 30 | +#include "nn_other.h" |
| 25 | - printf(message, ##__VA_ARGS__); \ | 31 | +#include "../op_graph/strided_slice_proto.h" |
| 26 | -} while (0) | ||
| 27 | 32 | ||
| 28 | -int64_t GetShapeSize(const std::vector<int64_t>& shape) { | 33 | +#define FAILED -1 |
| 29 | -int64_t shapeSize = 1; | 34 | +#define SUCCESS 0 |
| 30 | -for (auto i : shape) { | 35 | + |
| 31 | - shapeSize *= i; | 36 | +using namespace ge; |
| 32 | -} | 37 | +using std::map; |
| 33 | -return shapeSize; | 38 | +using std::string; |
| 39 | +using std::vector; | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + do { \ | ||
| 43 | + std::string name##inputIndex = "placeholder" + std::to_string(inputIndex); \ | ||
| 44 | + auto placeholder##inputIndex = op::Data(name##inputIndex.c_str()).set_attr_index(0); \ | ||
| 45 | + TensorDesc placeholder##inputIndex##_desc = TensorDesc(ge::Shape(inputShape), FORMAT_ND, inputDtype); \ | ||
| 46 | + placeholder##inputIndex##_desc.SetPlacement(ge::kPlacementHost); \ | ||
| 47 | + placeholder##inputIndex##_desc.SetFormat(FORMAT_ND); \ | ||
| 48 | + Tensor tensor_placeholder##inputIndex; \ | ||
| 49 | + ret = GenOnesDataFloat32(inputShape, tensor_placeholder##inputIndex, placeholder##inputIndex##_desc, 2.3f); \ | ||
| 50 | + if (ret != SUCCESS) { \ | ||
| 51 | + printf("%s - ERROR - [XIR]: Generate input data failed\n", GetTime().c_str()); \ | ||
| 52 | + return FAILED; \ | ||
| 53 | + } \ | ||
| 54 | + placeholder##inputIndex.update_input_desc_x(placeholder##inputIndex##_desc); \ | ||
| 55 | + graph.AddOp(placeholder##inputIndex); \ | ||
| 56 | + input.push_back(tensor_placeholder##inputIndex); \ | ||
| 57 | + stridedslice1.set_input_##inputName(placeholder##inputIndex); \ | ||
| 58 | + inputs.push_back(placeholder##inputIndex); \ | ||
| 59 | + } while (0) | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + do { \ | ||
| 63 | + TensorDesc outputName##outputIndex##_desc = TensorDesc(ge::Shape(outputShape), FORMAT_ND, outputDtype); \ | ||
| 64 | + stridedslice1.update_output_desc_##outputName(outputName##outputIndex##_desc); \ | ||
| 65 | + } while (0) | ||
| 66 | + | ||
| 67 | + | ||
| 68 | + | ||
| 69 | + | ||
| 70 | + do { \ | ||
| 71 | + printf(message, ##__VA_ARGS__); \ | ||
| 72 | + } while (0) | ||
| 73 | + | ||
| 74 | +string GetTime() | ||
| 75 | +{ | ||
| 76 | + time_t timep; | ||
| 77 | + time(&timep); | ||
| 78 | + char tmp[64]; | ||
| 79 | + strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S,000", localtime(&timep)); | ||
| 80 | + return tmp; | ||
| 34 | } | 81 | } |
| 35 | 82 | ||
| 36 | -int Init(int32_t deviceId, aclrtStream* stream) { | 83 | +uint32_t GetDataTypeSize(DataType dt) |
| 37 | -// 固定写法,资源初始化 | 84 | +{ |
| 38 | -auto ret = aclInit(nullptr); | 85 | + if (dt == ge::DT_FLOAT) |
| 39 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 86 | + return 4; |
| 40 | -ret = aclrtSetDevice(deviceId); | 87 | + if (dt == ge::DT_FLOAT16) |
| 41 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 88 | + return 2; |
| 42 | -ret = aclrtCreateStream(stream); | 89 | + if (dt == ge::DT_BF16) |
| 43 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 90 | + return 2; |
| 44 | -return 0; | 91 | + return 4; |
| 45 | } | 92 | } |
| 46 | 93 | ||
| 47 | -template <typename T> | 94 | +int32_t GenOnesDataFloat32(vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& input_tensor_desc, float value) |
| 48 | -int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 95 | +{ |
| 49 | - aclDataType dataType, aclTensor** tensor) { | 96 | + input_tensor_desc.SetRealDimCnt(shapes.size()); |
| 50 | -auto size = GetShapeSize(shape) * sizeof(T); | 97 | + size_t size = 1; |
| 51 | -// 调用aclrtMalloc申请device侧内存 | 98 | + for (uint32_t i = 0; i < shapes.size(); i++) { |
| 52 | -auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 99 | + size *= shapes[i]; |
| 53 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 100 | + } |
| 54 | -// 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 101 | + uint32_t data_len = size * 4; |
| 55 | -ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 102 | + float* pData = new (std::nothrow) float[size]; |
| 56 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 57 | 103 | ||
| 58 | -// 计算连续tensor的strides | 104 | + for (size_t i = 0; i < size; ++i) { |
| 59 | -std::vector<int64_t> strides(shape.size(), 1); | 105 | + pData[i] = value + (i % 3) * 0.4f; // 让数据更有意义 |
| 60 | -for (int64_t i = shape.size() - 2; i >= 0; i--) { | 106 | + } |
| 61 | - strides[i] = shape[i + 1] * strides[i + 1]; | 107 | + input_tensor = Tensor(input_tensor_desc, (uint8_t*)pData, data_len); |
| 108 | + return SUCCESS; | ||
| 62 | } | 109 | } |
| 63 | 110 | ||
| 64 | -// 调用aclCreateTensor接口创建aclTensor | 111 | +int32_t WriteDataToFile(string bin_file, uint64_t data_size, uint8_t* inputData) |
| 65 | -*tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | 112 | +{ |
| 66 | - shape.data(), shape.size(), *deviceAddr); | 113 | + FILE* fp = fopen(bin_file.c_str(), "wb"); |
| 67 | -return 0; | 114 | + if (fp == nullptr) { |
| 115 | + return FAILED; | ||
| 116 | + } | ||
| 117 | + size_t written = fwrite(inputData, 1, data_size, fp); | ||
| 118 | + fclose(fp); | ||
| 119 | + if (written != data_size) { | ||
| 120 | + return FAILED; | ||
| 121 | + } | ||
| 122 | + return SUCCESS; | ||
| 68 | } | 123 | } |
| 69 | 124 | ||
| 70 | -int main() { | 125 | +int CreateOppInGraph(DataType inDtype, std::vector<ge::Tensor> &input, std::vector<Operator> &inputs, |
| 71 | -// 1. (固定写法)device/stream初始化,参考acl API手册 | 126 | + std::vector<Operator> &outputs, Graph &graph) |
| 72 | -// 根据自己的实际device填写deviceId | 127 | +{ |
| 73 | -int32_t deviceId = 0; | 128 | + Status ret = SUCCESS; |
| 74 | -aclrtStream stream; | 129 | + // 自定义代码:添加单算子定义到图中 |
| 75 | -auto ret = Init(deviceId, &stream); | 130 | + auto stridedslice1 = op::StridedSlice("test_geir_strided_slice"); |
| 76 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 131 | + // 输入shape |
| 132 | + std::vector<int64_t> xShape = {1, 1, 1, 1}; | ||
| 133 | + std::vector<int64_t> beginShape = {0, 0, 0}; | ||
| 134 | + std::vector<int64_t> endShape = {1, 1, 1}; | ||
| 135 | + std::vector<int64_t> stridesShape = {1, 1, 1}; | ||
| 136 | + // 输出shape | ||
| 137 | + std::vector<int64_t> yShape = {1, 1, 1, 1}; | ||
| 77 | 138 | ||
| 78 | -// 2. 构造输入与输出,需要根据API的接口自定义构造 | 139 | + ADD_INPUT(1, x, inDtype, xShape); |
| 79 | -std::vector<int64_t> selfShape = {4, 2}; | 140 | + ADD_INPUT(2, begin, inDtype, beginShape); |
| 80 | -std::vector<int64_t> outShape = {2, 2}; | 141 | + ADD_INPUT(3, end, inDtype, endShape); |
| 81 | -void* selfDeviceAddr = nullptr; | 142 | + ADD_INPUT(4, strides, inDtype, stridesShape); |
| 82 | -void* outDeviceAddr = nullptr; | ||
| 83 | -aclTensor* self = nullptr; | ||
| 84 | -aclTensor* out = nullptr; | ||
| 85 | -std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
| 86 | -std::vector<float> outHostData = {0, 0, 0, 0}; | ||
| 87 | -int64_t dim = 0; | ||
| 88 | -int64_t start = 1; | ||
| 89 | -int64_t end = 3; | ||
| 90 | -int64_t step = 1; | ||
| 91 | -// 创建self aclTensor | ||
| 92 | -ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 93 | -CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 94 | -// 创建out aclTensor | ||
| 95 | -ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 96 | -CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 97 | 143 | ||
| 98 | -// 3. 调用CANN算子库API,需要修改为具体的Api名称 | 144 | + // 添加必选属性 |
| 99 | -uint64_t workspaceSize = 0; | 145 | + ADD_INPUT_ATTR(begin_mask, 13); |
| 100 | -aclOpExecutor* executor; | 146 | + ADD_INPUT_ATTR(end_mask, 11); |
| 101 | -// 调用aclnnSlice第一段接口 | 147 | + ADD_INPUT_ATTR(ellipsis_mask, 1); |
| 102 | -ret = aclnnSliceGetWorkspaceSize(self, dim, start, end, step, out, &workspaceSize, &executor); | 148 | + ADD_INPUT_ATTR(new_axis_mask, 9); |
| 103 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSliceGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | 149 | + ADD_INPUT_ATTR(shrink_axis_mask, 0); |
| 104 | -// 根据第一段接口计算出的workspaceSize申请device内存 | 150 | + // 添加输出 |
| 105 | -void* workspaceAddr = nullptr; | 151 | + ADD_OUTPUT(1, y, inDtype, yShape); |
| 106 | -if (workspaceSize > 0) { | ||
| 107 | - ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 108 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 109 | -} | ||
| 110 | -// 调用aclnnSlice第二段接口 | ||
| 111 | -ret = aclnnSlice(workspaceAddr, workspaceSize, executor, stream); | ||
| 112 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSlice failed. ERROR: %d\n", ret); return ret); | ||
| 113 | 152 | ||
| 114 | -// 4. (固定写法)同步等待任务执行结束 | 153 | + outputs.push_back(stridedslice1); |
| 115 | -ret = aclrtSynchronizeStream(stream); | 154 | + // 添加完毕 |
| 116 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | 155 | + return SUCCESS; |
| 117 | - | ||
| 118 | -// 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 119 | -auto size = GetShapeSize(outShape); | ||
| 120 | -std::vector<float> resultData(size, 0); | ||
| 121 | -ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 122 | - size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 123 | -CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 124 | -for (int64_t i = 0; i < size; i++) { | ||
| 125 | - LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 126 | } | 156 | } |
| 127 | 157 | ||
| 128 | -// 6. 释放aclTensor,需要根据具体API的接口定义修改 | 158 | +int main(int argc, char *argv[]) |
| 129 | -aclDestroyTensor(self); | 159 | +{ |
| 130 | -aclDestroyTensor(out); | 160 | + const char *graph_name = "tc_ge_irrun_test"; |
| 161 | + Graph graph(graph_name); | ||
| 162 | + std::vector<ge::Tensor> input; | ||
| 131 | 163 | ||
| 132 | -// 7. 释放device资源,需要根据具体API的接口定义修改 | 164 | + printf("%s - INFO - [XIR]: Start to initialize ge using ge global options\n", GetTime().c_str()); |
| 133 | -aclrtFree(selfDeviceAddr); | 165 | + std::map<AscendString, AscendString> global_options = {{"ge.exec.deviceId", "0"}, {"ge.graphRunMode", "1"}}; |
| 134 | -aclrtFree(outDeviceAddr); | 166 | + Status ret = ge::GEInitialize(global_options); |
| 135 | -if (workspaceSize > 0) { | 167 | + if (ret != SUCCESS) { |
| 136 | - aclrtFree(workspaceAddr); | 168 | + printf("%s - INFO - [XIR]: Initialize ge using ge global options failed\n", GetTime().c_str()); |
| 137 | -} | 169 | + return FAILED; |
| 138 | -aclrtDestroyStream(stream); | 170 | + } |
| 139 | -aclrtResetDevice(deviceId); | 171 | + printf("%s - INFO - [XIR]: Initialize ge using ge global options success\n", GetTime().c_str()); |
| 140 | -aclFinalize(); | 172 | + |
| 141 | -return 0; | 173 | + std::vector<Operator> inputs{}; |
| 174 | + std::vector<Operator> outputs{}; | ||
| 175 | + | ||
| 176 | + std::cout << argv[1] << std::endl; | ||
| 177 | + char *endptr; | ||
| 178 | + | ||
| 179 | + DataType inDtype = DT_INT32; | ||
| 180 | + | ||
| 181 | + std::cout << inDtype << std::endl; | ||
| 182 | + | ||
| 183 | + ret = CreateOppInGraph(inDtype, input, inputs, outputs, graph); | ||
| 184 | + if (ret != SUCCESS) { | ||
| 185 | + printf("%s - ERROR - [XIR]: Create ir session using build options failed\n", GetTime().c_str()); | ||
| 186 | + return FAILED; | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + if (!inputs.empty() && !outputs.empty()) { | ||
| 190 | + graph.SetInputs(inputs).SetOutputs(outputs); | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + std::map<AscendString, AscendString> build_options = { | ||
| 194 | + | ||
| 195 | + }; | ||
| 196 | + printf("%s - INFO - [XIR]: Start to create ir session using build options\n", GetTime().c_str()); | ||
| 197 | + ge::Session *session = new Session(build_options); | ||
| 198 | + | ||
| 199 | + if (session == nullptr) { | ||
| 200 | + printf("%s - ERROR - [XIR]: Create ir session using build options failed\n", GetTime().c_str()); | ||
| 201 | + return FAILED; | ||
| 202 | + } | ||
| 203 | + printf("%s - INFO - [XIR]: Create ir session using build options success\n", GetTime().c_str()); | ||
| 204 | + printf("%s - INFO - [XIR]: Start to add compute graph to ir session\n", GetTime().c_str()); | ||
| 205 | + | ||
| 206 | + std::map<AscendString, AscendString> graph_options = { | ||
| 207 | + | ||
| 208 | + }; | ||
| 209 | + uint32_t graph_id = 0; | ||
| 210 | + ret = session->AddGraph(graph_id, graph, graph_options); | ||
| 211 | + | ||
| 212 | + printf("%s - INFO - [XIR]: Session add ir compute graph to ir session success\n", GetTime().c_str()); | ||
| 213 | + printf("%s - INFO - [XIR]: dump graph to txt\n", GetTime().c_str()); | ||
| 214 | + std::string file_path = "./dump"; | ||
| 215 | + aclgrphDumpGraph(graph, file_path.c_str(), file_path.length()); | ||
| 216 | + printf("%s - INFO - [XIR]: Start to run ir compute graph\n", GetTime().c_str()); | ||
| 217 | + std::vector<ge::Tensor> output; | ||
| 218 | + ret = session->RunGraph(graph_id, input, output); | ||
| 219 | + if (ret != SUCCESS) { | ||
| 220 | + printf("%s - INFO - [XIR]: Run graph failed\n", GetTime().c_str()); | ||
| 221 | + delete session; | ||
| 222 | + GEFinalize(); | ||
| 223 | + return FAILED; | ||
| 224 | + } | ||
| 225 | + printf("%s - INFO - [XIR]: Session run ir compute graph success\n", GetTime().c_str()); | ||
| 226 | + | ||
| 227 | + int input_num = input.size(); | ||
| 228 | + for (int i = 0; i < input_num; i++) { | ||
| 229 | + std::cout << "input " << i << " dtype : " << input[i].GetTensorDesc().GetDataType() << std::endl; | ||
| 230 | + string input_file = "./tc_ge_irrun_test_0008_npu_input_" + std::to_string(i) + ".bin"; | ||
| 231 | + uint8_t *input_data_i = input[i].GetData(); | ||
| 232 | + int64_t input_shape = input[i].GetTensorDesc().GetShape().GetShapeSize(); | ||
| 233 | + std::cout << "this is " << i << "th input, input shape size =" << input_shape << std::endl; | ||
| 234 | + uint32_t data_size = input_shape * GetDataTypeSize(input[i].GetTensorDesc().GetDataType()); | ||
| 235 | + WriteDataToFile((const char *)input_file.c_str(), data_size, input_data_i); | ||
| 236 | + } | ||
| 237 | + | ||
| 238 | + int output_num = output.size(); | ||
| 239 | + for (int i = 0; i < output_num; i++) { | ||
| 240 | + std::cout << "output " << i << " dtype : " << output[i].GetTensorDesc().GetDataType() << std::endl; | ||
| 241 | + string output_file = "./tc_ge_irrun_test_0008_npu_output_" + std::to_string(i) + ".bin"; | ||
| 242 | + uint8_t *output_data_i = output[i].GetData(); | ||
| 243 | + int64_t output_shape = output[i].GetTensorDesc().GetShape().GetShapeSize(); | ||
| 244 | + std::cout << "this is " << i << "th output, output shape size =" << output_shape << std::endl; | ||
| 245 | + uint32_t data_size = output_shape * GetDataTypeSize(output[i].GetTensorDesc().GetDataType()); | ||
| 246 | + WriteDataToFile((const char *)output_file.c_str(), data_size, output_data_i); | ||
| 247 | + float *resultData = (float*)output_data_i; | ||
| 248 | + for (int64_t j = 0; j < output_shape; j++) { | ||
| 249 | + LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 250 | + } | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + ge::AscendString error_msg = ge::GEGetErrorMsgV2(); | ||
| 254 | + std::string error_str(error_msg.GetString()); | ||
| 255 | + std::cout << "Error message: " << error_str << std::endl; | ||
| 256 | + ge::AscendString warning_msg = ge::GEGetWarningMsgV2(); | ||
| 257 | + std::string warning_str(warning_msg.GetString()); | ||
| 258 | + std::cout << "Warning message: " << warning_str << std::endl; | ||
| 259 | + printf("%s - INFO - [XIR]: Start to finalize ir graph session\n", GetTime().c_str()); | ||
| 260 | + ret = ge::GEFinalize(); | ||
| 261 | + if (ret != SUCCESS) { | ||
| 262 | + printf("%s - INFO - [XIR]: Finalize ir graph session failed\n", GetTime().c_str()); | ||
| 263 | + return FAILED; | ||
| 264 | + } | ||
| 265 | + printf("%s - INFO - [XIR]: Finalize ir graph session success\n", GetTime().c_str()); | ||
| 266 | + return SUCCESS; | ||
| 142 | } | 267 | } |