调用CBLAS接口执行算子示例代码【免费下载链接】geGEGraph Engine是面向昇腾的图编译器和执行器提供了计算图优化、多流并行、内存复用和模型下沉等技术手段加速模型执行效率减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge本节介绍基于单算子模型执行的方式调用CBLAS算子的关键接口、示例代码。基本原理接口调用流程请参见单算子模型执行总体说明。目前GEMM算子用于矩阵-向量乘、矩阵-矩阵乘已被封装成aclblas接口目前支持以下两种执行方式不以handle方式执行算子接口名称中不包含“Handle”关键字例如调用aclblasGemmEx接口封装GEMM算子执行算子。以handle方式执行算子接口名称中包含“Handle”关键字例如调用aclblasCreateHandleForGemmEx接口、创建handle后还需要调用aclopExecWithHandle接口执行算子。说明不以handle方式执行算子时每次执行算子时系统内部都会根据算子描述信息匹配内存中的模型。 以handle方式执行算子时系统内部将算子描述信息匹配到内存中的模型并缓存在handle中每次执行算子时无需重复匹配算子与模型因此在涉及多次执行同一个算子时效率更高但该方式不支持动态Shape算子且handle使用结束后需调用aclopDestroyHandle接口释放。示例代码本章以aclblasGemmEx接口为例该接口封装的是GEMM算子该接口中矩阵乘的计算公式为C αAB βC表示矩阵A和矩阵B相乘后得到矩阵Cα和β表示乘积的系数。调用CBLAS接口封装GEMM算子分为以下几步准备GEMM算子的模型文件。构造GEMM算子的描述文件*.json文件描述输入输出Tensor描述、算子属性等。GEMM算子的描述文件示例如下[ { op: GEMM, input_desc: [ { format: ND, shape: [16, 16], type: float16 }, { format: ND, shape: [16, 16], type: float16 }, { format: ND, shape: [16, 16], type: float16 }, { format: ND, shape: [], type: float16 }, { format: ND, shape: [], type: float16 } ], output_desc: [ { format: ND, shape: [16, 16], type: float16 } ], attr: [ { name: transpose_a, type: bool, value: false }, { name: transpose_b, type: bool, value: false } ] } ]借助ATC工具将该算子描述文件编译成单算子模型文件*.om文件再分别调用acl接口加载om模型文件、执行算子。ATC工具的命令示例如下atc --singleop$HOME/singleop/gemm.json --output$HOME/singleop/out/op_model --soc_versionsoc_version关键参数解释如下详细参数取值及约束说明请参见《ATC离线模型编译工具》--singleop单算子描述文件json格式的路径。--output存放单算子模型文件的目录。--soc_versionAI处理器的版本。_soc_version_请根据实际情况替换。编写调用CBLAS的代码逻辑。以下是关键步骤的代码示例不能直接拷贝编译运行仅供参考。调用接口后需增加异常处理的分支并记录报错日志、提示日志此处不一一列举。您可以单击gemm获取样例。// 1.初始化 aclRet aclInit(nullptr); // 2.运行时资源申请使用默认Context、默认Stream默认Stream在作为其它接口入参时可传空指针 aclRet aclrtSetDevice(0); // 获取软件栈的运行模式不同运行模式影响后续的接口调用流程例如是否进行数据传输等 aclrtRunMode runMode; bool g_isDevice false; aclError aclRet aclrtGetRunMode(runMode); g_isDevice (runMode ACL_DEVICE); // 3. 设置单算子模型文件所在的目录 // 该目录相对可执行文件所在的目录例如编译出来的可执行文件存放在run/out目录下此处就表示run/out/op_models目录 aclopSetModelDir(op_models); // 4. 申请内存 // 申请Device上的内存存放执行算子的输入数据 // 对于该矩阵乘示例依次申请存放矩阵A数据、矩阵B数据、矩阵C数据、标量α数据、标量β数据的内存 aclrtMalloc((void **) devMatrixA_, sizeA_, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc((void **) devMatrixB_, sizeB_, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc((void **) devMatrixC_, sizeC_, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc((void **) devAlpha_, sizeAlphaBeta_, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc((void **) devBeta_, sizeAlphaBeta_, ACL_MEM_MALLOC_HUGE_FIRST); // 申请Host上的内存此处根据软件栈的运行模式判断是否需要申请Host上的内存 // 如果运行模式为ACL_DEVICE则g_isDevice参数值为true表示软件栈运行在Device侧无需申请Host内存无需传输图片数据或在Device内传输数据 // 如果运行模式为ACL_HOST则g_isDevice参数值为false表示软件栈运行在Host侧需要申请Host内存涉及Host和Device之间的数据传输 if (g_isDevice) { hostMatrixA_ devMatrixA_; hostMatrixB_ devMatrixB_; hostMatrixC_ devMatrixC_; } else { aclrtMallocHost((void **) hostMatrixA_, sizeA_); aclrtMallocHost((void **) hostMatrixB_, sizeB_); aclrtMallocHost((void **) hostMatrixC_, sizeC_); } // 5. 准备输入数据ReadFile为自定义函数由用户自行管理从文件中读入数据到内存中 size_t fileSize; // Read matrix A char *fileData ReadFile(test_data/data/matrix_a.bin, fileSize, hostMatrixA_, sizeA_); // Read matrix B fileData ReadFile(test_data/data/matrix_b.bin, fileSize, hostMatrixB_, sizeB_); // Read matrix C fileData ReadFile(test_data/data/matrix_c.bin, fileSize, hostMatrixC_, sizeC_); // 根据软件栈的运行模式判断是否涉及Host与Device之间的数据传输 if (!g_isDevice) { aclError ret aclrtMemcpy(devMatrixA_, sizeA_, hostMatrixA_, sizeA_, ACL_MEMCPY_HOST_TO_DEVICE); ret aclrtMemcpy(devMatrixB_, sizeB_, hostMatrixB_, sizeB_, ACL_MEMCPY_HOST_TO_DEVICE); ret aclrtMemcpy(devMatrixC_, sizeC_, hostMatrixC_, sizeC_, ACL_MEMCPY_HOST_TO_DEVICE); } aclrtMemcpyKind kind g_isDevice ? ACL_MEMCPY_DEVICE_TO_DEVICE : ACL_MEMCPY_HOST_TO_DEVICE; ret aclrtMemcpy(devAlpha_, sizeAlphaBeta_, hostAlpha_, sizeAlphaBeta_, kind); ret aclrtMemcpy(devBeta_, sizeAlphaBeta_, hostBeta_, sizeAlphaBeta_, kind); // 6. 执行单算子 // 对于该示例调用aclblasGemmEx接口异步接口实现矩阵-矩阵的乘法 aclblasGemmEx(ACL_TRANS_N, ACL_TRANS_N, ACL_TRANS_N, m_, n_, k_, devAlpha_, devMatrixA_, k_, inputType_, devMatrixB_, n_, inputType_, devBeta_, devMatrixC_, n_, outputType_, ACL_COMPUTE_HIGH_PRECISION, stream); // 调用aclrtSynchronizeStream接口阻塞Host运行直到指定Stream中的所有任务都完成 aclrtSynchronizeStream(nullptr); // 7. 传输算子执行结果根据软件栈的运行模式判断是否涉及Host与Device之间的数据传输 if (!g_isDevice) { auto ret aclrtMemcpy(hostMatrixC_, sizeC_, devMatrixC_, sizeC_, ACL_MEMCPY_DEVICE_TO_HOST); } // 8. 是否直接在终端屏幕上显示算子执行结果由用户自行管理代码逻辑 // 9. 释放运行时资源默认Context、Stream无需用户释放调用aclrtResetDevice接口后自动释放 aclRet aclrtResetDevice(0); // 10.去初始化 aclRet aclFinalize(); // ......【免费下载链接】geGEGraph Engine是面向昇腾的图编译器和执行器提供了计算图优化、多流并行、内存复用和模型下沉等技术手段加速模型执行效率减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的友好接入能力并同时支持 onnx、pb 等主流模型格式的解析与编译。项目地址: https://gitcode.com/cann/ge创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考