网站开发销售话术,呼和浩特住房和城乡建设部网站,印刷厂网站模板,python做网站的案例文章目录 【2024第一期CANN训练营】4、AscendCL推理应用开发1. 创建代码目录2. 构建模型2.1 下载原始模型文件2.2 使用ATC工具转换模型2.3 注意事项 3. 模型加载3.1 示例代码 4. 模型执行4.1 获取模型描述信息4.2 准备输入/输出数据结构4.3 执行模型推理4.4 释放内存和数据类型… 文章目录 【2024第一期CANN训练营】4、AscendCL推理应用开发1. 创建代码目录2. 构建模型2.1 下载原始模型文件2.2 使用ATC工具转换模型2.3 注意事项 3. 模型加载3.1 示例代码 4. 模型执行4.1 获取模型描述信息4.2 准备输入/输出数据结构4.3 执行模型推理4.4 释放内存和数据类型 5. 模型卸载6. 多种模型推理方式可选 【2024第一期CANN训练营】4、AscendCL推理应用开发
本教程将介绍如何使用AscendCL接口开发一个基于昇腾AI处理器的基础推理应用。昇腾社区提供了全栈AI计算基础设施包括硬件、软件架构、计算框架等为AI应用开发提供强大支持。
1. 创建代码目录
创建一个项目目录结构用于存放代码文件、模型文件、测试数据等。以下是一个示例目录结构
MyInferenceApp
├── model/ # 存放模型文件
│ ├── model.om # 昇腾AI处理器的离线模型文件├── data/ # 存放测试数据
│ ├── input.jpg # 测试图片数据├── inc/ # 存放头文件
│ ├── app.h # 应用声明的头文件├── src/ # 存放源代码和编译脚本
│ ├── CMakeLists.txt # 编译脚本
│ ├── main.cpp # 主要的源代码文件├── out/ # 存放输出结果2. 构建模型
首先需要一个适配昇腾AI处理器的离线模型.om文件。
可以使用ATCAscend Tensor Compiler工具将开源框架的网络模型转换为适配昇腾AI处理器的离线模型*.om文件。以ONNX框架的ResNet-50网络为例我们将一步步进行说明。
2.1 下载原始模型文件
cd SAMPLE_DIR/MyFirstApp_ONNX/model
wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/resnet50/resnet50.onnx2.2 使用ATC工具转换模型
执行以下命令将ONNX模型转换为昇腾AI处理器能识别的*.om模型文件。请确保具有命令中相关路径的可读、可写权限并根据实际情况替换SAMPLE_DIR和soc_version。
atc --modelresnet50.onnx --framework5 --outputresnet50 --input_shapeactual_input_1:1,3,224,224 --soc_versionsoc_version--model: 指定ResNet-50网络的模型文件路径。--framework: 指定原始框架类型ONNX框架的值为5。--output: 指定输出的模型文件名这里是resnet50.om。--input_shape: 指定模型输入数据的shape。--soc_version: 指定昇腾AI处理器的版本。执行npu-smi info命令查询在查询到的“Name”前增加Ascend信息如Ascend910A
如果想快速体验使用转换后的om离线模型文件进行推理请准备好环境、om模型文件、符合模型输入要求的*.bin格式的输入数据并参考msame工具的README进行体验。可选
2.3 注意事项
如果模型转换时提示有不支持的算子请参考TBEAI CPU自定义算子开发指南完成自定义算子后再重新转换模型。如果模型转换时提示有算子编译相关问题无法定位问题时需设置环境变量DUMP_GE_GRAPH和DUMP_GRAPH_LEVEL重新模型转换收集模型转换过程中的图描述信息提供给华为工程师定位问题。如果模型的输入Shape是动态的请参考模型动态Shape输入推理的说明。如果现有网络不满足需求可以使用昇腾AI处理器支持的算子、调用Ascend Graph接口自行构建网络再编译成om离线模型文件。详细说明请参见Ascend Graph开发指南。
3. 模型加载
模型加载的接口调用流程可以分为两种方式
通过接口中的配置参数区分加载方式这种方式适用于从文件加载、从内存加载等不同加载方式但涉及多个接口配合使用。 使用aclmdlSetConfigOpt接口、aclmdlLoadWithConfig接口通过设置各属性的取值直接一次性配置是从文件加载还是从内存加载以及内存是由系统内部管理还是由用户管理。 通过不同接口区分加载方式这种方式根据不同的加载方式选择不同的接口操作简单但需要记住各种方式的加载接口。 当输入数据的Shape确定时由用户自行管理内存。需要调用aclmdlQuerySizeaclrtMalloc接口查询和申请模型运行时所需工作内存、权值内存的大小然后再从文件或内存进行加载。 aclmdlLoadFromFileWithMem从文件加载离线模型数据由用户自行管理内存。aclmdlLoadFromMemWithMem从内存加载离线模型数据由用户自行管理内存。 当输入数据的Shape不确定时由系统内部管理内存。 aclmdlLoadFromFile从文件加载离线模型数据由系统内部管理内存。aclmdlLoadFromMem从内存加载离线模型数据由系统内部管理内存。 3.1 示例代码
以下是一个关键步骤的代码示例用于从文件加载模型并自行管理内存。
// 1.初始化变量。
const char* omModelPath ../model/resnet50.om;// 2.根据模型文件获取模型执行时所需的权值内存大小、工作内存大小。
size_t modelMemSize_ 0, modelWeightSize_ 0;
aclError ret aclmdlQuerySize(omModelPath, modelMemSize_, modelWeightSize_);// 3.根据工作内存大小申请Device上模型执行的工作内存。
void* modelMemPtr_ nullptr;
ret aclrtMalloc(modelMemPtr_, modelMemSize_, ACL_MEM_MALLOC_HUGE_FIRST);// 4.根据权值内存的大小申请Device上模型执行的权值内存。
void* modelWeightPtr_ nullptr;
ret aclrtMalloc(modelWeightPtr_, modelWeightSize_, ACL_MEM_MALLOC_HUGE_FIRST);// 5.加载离线模型文件由用户自行管理模型运行的内存(包括权值内存、工作内存)。
// 模型加载成功返回标识模型的ID。
aclmdlDesc* modelId_ nullptr;
ret aclmdlLoadFromFileWithMem(omModelPath, modelId_, modelMemPtr_, modelMemSize_, modelWeightPtr_, modelWeightSize_);4. 模型执行
模型执行的接口调用流程可以分为以下几个步骤
在模型加载之后模型执行之前需要准备输入、输出数据结构并将输入数据传输到模型输入数据结构的对应内存中。模型执行结束后若无需使用输入数据、aclmdlDesc类型、aclmdlDataset类型、aclDataBuffer类型等相关资源需及时释放内存、销毁对应的数据类型防止内存异常。
4.1 获取模型描述信息 调用aclmdlCreateDesc接口创建描述模型基本信息的数据类型。 调用aclmdlGetDesc接口根据模型加载中返回的模型ID获取模型基本信息。
// 1. 获取模型描述信息
aclmdlDesc* modelDesc_ aclmdlCreateDesc();
aclError ret aclmdlGetDesc(modelDesc_, modelId_);4.2 准备输入/输出数据结构
// 2. 准备模型推理的输入数据结构
// 申请输入内存
size_t modelInputSize;
void *modelInputBuffer nullptr;
aclRet aclrtMalloc(modelInputBuffer, modelInputSize, ACL_MEM_MALLOC_NORMAL_ONLY);// 准备模型推理的输入数据结构
input_ aclmdlCreateDataset();
aclDataBuffer *inputData aclCreateDataBuffer(modelInputBuffer, modelInputSize);
ret aclmdlAddDatasetBuffer(input_, inputData);// 准备模型推理的输出数据结构
output_ aclmdlCreateDataset();
size_t outputSize aclmdlGetNumOutputs(modelDesc_);
for (size_t i 0; i outputSize; i) {size_t buffer_size aclmdlGetOutputSizeByIndex(modelDesc_, i);void *outputBuffer nullptr;aclError ret aclrtMalloc(outputBuffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);aclDataBuffer* outputData aclCreateDataBuffer(outputBuffer, buffer_size);ret aclmdlAddDatasetBuffer(output_, outputData);
}4.3 执行模型推理
根据实际场景选择同步推理或异步推理。
对于同步推理直接获取模型推理的输出数据即可。对于异步推理在实现Callback功能时在回调函数内获取模型推理的结果。
string testFile[] {../data/dog1_1024_683.bin,../data/dog2_1024_683.bin};// 3. 模型推理
for (size_t index 0; index sizeof(testFile) / sizeof(testFile[0]); index) {// 读取图片文件void *inputBuff nullptr;uint32_t inputBuffSize 0;auto ret Utils::ReadBinFile(fileName, inputBuff, inputBuffSize);// 准备模型推理的输入数据if (!g_isDevice) {aclError aclRet aclrtMemcpy(modelInputBuffer, modelInputSize, inputBuff, inputBuffSize, ACL_MEMCPY_HOST_TO_DEVICE);(void)aclrtFreeHost(inputBuff);} else {aclError aclRet aclrtMemcpy(modelInputBuffer, modelInputSize, inputBuff, inputBuffSize, ACL_MEMCPY_DEVICE_TO_DEVICE);(void)aclrtFree(inputBuff);}// 执行模型推理ret aclmdlExecute(modelId_, input_, output_);// 输出模型推理的结果输出top5置信度的类别编号 for (size_t i 0; i aclmdlGetDatasetNumBuffers(output_); i) {// 获取每个输出的内存地址和内存大小aclDataBuffer* dataBuffer aclmdlGetDatasetBuffer(output_, i);void* data aclGetDataBufferAddr(dataBuffer);size_t len aclGetDataBufferSizeV2(dataBuffer);// 将内存中的数据转换为float类型float *outData NULL;outData reinterpret_castfloat*(data);// 屏显每张图片的top5置信度的类别编号mapfloat, int, greaterfloat resultMap;for (int j 0; j len / sizeof(float); j) {resultMap[*outData] j;outData;}int cnt 0;for (auto it resultMap.begin(); it ! resultMap.end(); it) {if (cnt 5)break;INFO_LOG(top %d: index[%d] value[%lf], cnt, it-second, it-first);}
}4.4 释放内存和数据类型
在模型推理结束后需依次调用aclDestroyDataBuffer接口、aclmdlDestroyDataset接口及时释放描述模型输入、输出数据类型的数据。
// 4. 释放模型推理的输入、输出资源
for (size_t i 0; i aclmdlGetDatasetNumBuffers(input_); i) {aclDataBuffer *dataBuffer aclmdlGetDatasetBuffer(input_, i);(void)aclDestroyDataBuffer(dataBuffer);
}
(void)aclmdlDestroyDataset(input_);
input_ nullptr;
aclrtFree(modelInputBuffer);for (size_t i 0; i aclmdlGetDatasetNumBuffers(output_); i) {aclDataBuffer* dataBuffer aclmdlGetDatasetBuffer(output_, i);void* data aclGetDataBufferAddr(dataBuffer);(void)aclrtFree(data);(void)aclDestroyDataBuffer(dataBuffer);
}
(void)aclmdlDestroyDataset(output_);
output_ nullptr;5. 模型卸载
模型推理完成后您需要通过aclmdlUnload接口来卸载模型。此外还需要销毁aclmdlDesc类型的模型描述信息并释放模型运行所需的工作内存和权值内存。
// 1. 卸载模型
aclError ret aclmdlUnload(modelId_);// 2. 释放模型描述信息
if (modelDesc_ ! nullptr) {(void)aclmdlDestroyDesc(modelDesc_);modelDesc_ nullptr;
}// 3. 释放模型运行的工作内存
if (modelWorkPtr_ ! nullptr) {(void)aclrtFree(modelWorkPtr_);modelWorkPtr_ nullptr;modelWorkSize_ 0;
}// 4. 释放模型运行的权值内存
if (modelWeightPtr_ ! nullptr) {(void)aclrtFree(modelWeightPtr_);modelWeightPtr_ nullptr;modelWeightSize_ 0;
}6. 多种模型推理方式可选 多Batch模型推理LINK 异步模型推理LINK 队列模型推理LINK 动态AIPP模型推理 单个动态AIPP输入LINK多个动态AIPP输入LINK 动态Shape输入模型推理 动态Batch/动态分辨率/动态维度LINK动态Shape输入LINK