AT800(3000) +昇腾300V 之 第一个例子图片分类

news2024/9/23 19:20:07

第一个列子

  • 背景
  • 开发流程
    • 准备模型
    • 开发
      • 推理流程
      • 编码
    • 编译与运行

背景

第一个例子是 图片分类的应用

因第一个,直接获取已训练好的开源模型,选择Caffe框架的ResNet-50模型。

ResNet-50模型的基本介绍如下:

输入数据:RGB格式、224*224分辨率的输入图片
输出数据:图片的类别标签及其对应置信度

开发流程

AscendCL(Ascend Computing Language)是一套用于在CANN(Compute Architecture for Neural Networks)上开发深度神经网络推理应用的C语言API库,提供模型加载与执行、媒体数据处理、算子加载与执行等API,能够实现在昇腾CANN平台上进行深度学习推理计算、图形图像预处理、单算子加速计算等能力。

图片流程来自昇腾社区
在这里插入图片描述

准备模型

昇腾 需要专用的模型,第一步 需要对开源模型进行转换。
使用ATC(Ascend Tensor Compiler)工具将开源框架的网络模型转换为适配昇腾AI处理器的离线模型(*.om文件)。

ATC 参数说明

  • – model:ResNet-50网络的模型文件(*.prototxt)的路径。
  • –weight:ResNet-50网络的权重文件(*.caffemodel)的路径。
  • –framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。
  • –output:resnet50.om模型文件的路径。请注意,记录保存该om模型文件的路径,后续开发应用时需要使用。
  • –soc_version:昇腾AI处理器的版本。
 npu-smi info
+--------------------------------------------------------------------------------------------------------+
| npu-smi 23.0.rc2                                 Version: 23.0.rc2                                     |
+-------------------------------+-----------------+------------------------------------------------------+
| NPU     Name                  | Health          | Power(W)     Temp(C)           Hugepages-Usage(page) |
| Chip    Device                | Bus-Id          | AICore(%)    Memory-Usage(MB)                        |
+===============================+=================+======================================================+
| 0       310P3                 | OK              | NA           44                0     / 0             |
| 0       0                     | 0000:01:00.0    | 0            1698 / 21527                            |
+===============================+=================+======================================================+
| 32      310P3                 | OK              | NA           41                0     / 0             |
| 0       1                     | 0000:02:00.0    | 0            1699 / 21527                            |
+===============================+=================+======================================================+
| 32800   310P3                 | OK              | NA           45                0     / 0             |
| 0       2                     | 0000:82:00.0    | 0            1697 / 21527                            |
+===============================+=================+======================================================+
| 32896   310P3                 | OK              | NA           47                0     / 0             |
| 0       3                     | 0000:85:00.0    | 0            1698 / 21527                            |
+===============================+=================+======================================================+

Name 310P3
即soc_version 为Ascend310P3

下载文件:

  • ResNet-50网络的模型文件(*.prototxt):单击Link下载该文件。
  • ResNet-50网络的权重文件(*.caffemodel):单击Link下载该文件。
atc --model=model/resnet50.prototxt --weight=model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=Ascend310P3

非root用户转换 失败 这里一定要用root


root# atc --model=model/resnet50.prototxt --weight=model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=Ascend310P3
ATC start working now, please wait for a moment.
...
ATC run success, welcome to the next use.

开发

推理流程

  • 初始化

    • 调用aclInit接口初始化AscendCL配置。
    • 调用aclFinalize接口实现AscendCL去初始化。
  • Device管理

    • 调用aclrtSetDevice接口指定用于运算的Device。
    • 调用aclrtGetRunMode接口获取昇腾AI软件栈的运行模式,根据运行模式的不同,内部处理流程不同。
    • 调用aclrtResetDevice接口复位当前运算的Device,回收Device上的资源。
  • Context管理

    • 调用aclrtCreateContext接口创建Context。
    • 调用aclrtSetCurrentContext接口设置线程的Context。
    • 调用aclrtDestroyContext接口销毁Context。
  • Stream管理

    • 调用aclrtCreateStream接口创建Stream。
    • 调用aclrtDestroyStream接口销毁Stream。
  • 内存管理

    • 调用aclrtMallocHost接口申请Host上内存。
    • 调用aclrtFreeHost释放Host上的内存。
    • 调用aclrtMalloc接口申请Device上的内存。
    • 调用aclrtFree接口释放Device上的内存。
  • 数据传输

    调用aclrtMemcpy接口通过内存复制的方式实现数据传输。

  • 模型推理

    • 调用aclmdlLoadFromFileWithMem接口从*.om文件加载模型。
    • 创建新线程(例如t1),在线程函数内调用aclrtProcessReport接口,等待指定时间后,触发回调函数(例如CallBackFunc,用于处理模型推理结果)。
    • 调用aclrtSubscribeReport接口,指定处理Stream上回调函数(CallBackFunc)的线程(t1)。
    • 调用aclmdlExecuteAsync接口执行模型推理,异步接口。
    • 调用aclrtLaunchCallback接口,在Stream的任务队列中增加一个需要在Host/Device上执行的回调函数(CallBackFunc)。
    • 调用aclrtSynchronizeStream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成。
    • 调用aclrtUnSubscribeReport接口,取消线程注册,Stream上的回调函数(CallBackFunc)不再由指定线程(t1)处理。
    • 模型推理结束后,调用aclmdlUnload接口卸载模型。

编码

创建main.cpp

#include "acl/acl.h"
#include <iostream>
#include <fstream>
#include <cstring>
#include <map>
using namespace std;

int32_t deviceId = 0;
void InitResource()
{
 aclError ret = aclInit(nullptr);
 ret = aclrtSetDevice(deviceId);
}

uint32_t modelId;
void LoadModel(const char* modelPath)
{
 aclError ret = aclmdlLoadFromFile(modelPath, &modelId);
}
size_t pictureDataSize = 0;
void *pictureHostData;

void *pictureDeviceData;
//申请内存,使用C/C++标准库的函数将测试图片读入内存
void ReadPictureTotHost(const char *picturePath)
{
 string fileName = picturePath;
 ifstream binFile(fileName, ifstream::binary);
 binFile.seekg(0, binFile.end);
 pictureDataSize = binFile.tellg();
 binFile.seekg(0, binFile.beg);
 aclError ret = aclrtMallocHost(&pictureHostData, pictureDataSize);
 binFile.read((char*)pictureHostData, pictureDataSize);
 binFile.close();
}
//申请Device侧的内存,再以内存复制的方式将内存中的图片数据传输到Device
void CopyDataFromHostToDevice()
{
 aclError ret = aclrtMalloc(&pictureDeviceData, pictureDataSize, ACL_MEM_MALLOC_HUGE_FIRST);
 ret = aclrtMemcpy(pictureDeviceData, pictureDataSize, pictureHostData, pictureDataSize, 
ACL_MEMCPY_HOST_TO_DEVICE);
}
void LoadPicture(const char* picturePath)
{
 ReadPictureTotHost(picturePath);
 CopyDataFromHostToDevice();
}

aclmdlDataset *inputDataSet;
aclDataBuffer *inputDataBuffer;
aclmdlDataset *outputDataSet;
aclDataBuffer *outputDataBuffer;
aclmdlDesc *modelDesc;
size_t outputDataSize = 0;
void *outputDeviceData;
// 准备模型推理的输入数据结构
void CreateModelInput()
{
 // 创建aclmdlDataset类型的数据,描述模型推理的输入
 inputDataSet = aclmdlCreateDataset();
 inputDataBuffer = aclCreateDataBuffer(pictureDeviceData, pictureDataSize);
 aclError ret = aclmdlAddDatasetBuffer(inputDataSet, inputDataBuffer);
}
// 准备模型推理的输出数据结构
void CreateModelOutput()
{
 // 创建模型描述信息
 modelDesc = aclmdlCreateDesc();
 aclError ret = aclmdlGetDesc(modelDesc, modelId);
 // 创建aclmdlDataset类型的数据,描述模型推理的输出
 outputDataSet = aclmdlCreateDataset();
 // 获取模型输出数据需占用的内存大小,单位为Byte
 outputDataSize = aclmdlGetOutputSizeByIndex(modelDesc, 0);
 // 申请输出内存
 ret = aclrtMalloc(&outputDeviceData, outputDataSize, ACL_MEM_MALLOC_HUGE_FIRST);
 outputDataBuffer = aclCreateDataBuffer(outputDeviceData, outputDataSize);
 ret = aclmdlAddDatasetBuffer(outputDataSet, outputDataBuffer);
}
// 执行模型
void Inference()
{
 CreateModelInput();
 CreateModelOutput();
 aclError ret = aclmdlExecute(modelId, inputDataSet, outputDataSet);
}


void *outputHostData;
void PrintResult()
{
 // 获取推理结果数据
 aclError ret = aclrtMallocHost(&outputHostData, outputDataSize);
 ret = aclrtMemcpy(outputHostData, outputDataSize, outputDeviceData, outputDataSize, 
ACL_MEMCPY_DEVICE_TO_HOST);
 // 将内存中的数据转换为float类型
 float* outFloatData = reinterpret_cast<float *>(outputHostData);
 
 // 屏显测试图片的top5置信度的类别编号
 map<float, unsigned int, greater<float>> resultMap;
 for (unsigned int j = 0; j < outputDataSize / sizeof(float);++j)
 {
 resultMap[*outFloatData] = j;
 outFloatData++;
 }
 
 int cnt = 0;
 for (auto it = resultMap.begin();it != resultMap.end();++it)
 {
 if(++cnt > 5)
 {
 break;
 }
 printf("top %d: index[%d] value[%lf] \n", cnt, it->second, it->first);
 }
}

void UnloadModel()
{
 // 释放模型描述信息
 aclmdlDestroyDesc(modelDesc);
 // 卸载模型
 aclmdlUnload(modelId);
}

void UnloadPicture()
{
 aclError ret = aclrtFreeHost(pictureHostData);
 pictureHostData = nullptr;
 ret = aclrtFree(pictureDeviceData);
 pictureDeviceData = nullptr;
 aclDestroyDataBuffer(inputDataBuffer);
 inputDataBuffer = nullptr;
 aclmdlDestroyDataset(inputDataSet);
 inputDataSet = nullptr;
 
 ret = aclrtFreeHost(outputHostData);
 outputHostData = nullptr;
 ret = aclrtFree(outputDeviceData);
 outputDeviceData = nullptr;
 aclDestroyDataBuffer(outputDataBuffer);
 outputDataBuffer = nullptr;
 aclmdlDestroyDataset(outputDataSet);
 outputDataSet = nullptr;
}


void DestroyResource()
{
 aclError ret = aclrtResetDevice(deviceId);
 aclFinalize();
}

int main()
{ 
 // 1.定义一个资源初始化的函数,用于AscendCL初始化、运行管理资源申请(指定计算设备)
 InitResource();
 
 // 2.定义一个模型加载的函数,加载图片分类的模型,用于后续推理使用
 const char *modelPath = "../model/resnet50.om";
 LoadModel(modelPath);
 
 // 3.定义一个读图片数据的函数,将测试图片数据读入内存,并传输到Device侧,用于后续推理使用
 const char *picturePath = "../data/dog1_1024_683.bin";
 LoadPicture(picturePath);
 
 // 4.定义一个推理的函数,用于执行推理
 Inference();

  // 5.定义一个推理结果数据处理的函数,用于在终端上屏显测试图片的top5置信度的类别编号
 PrintResult();
 
 // 6.定义一个模型卸载的函数,卸载图片分类的模型
 UnloadModel();
 
 // 7.定义一个函数,用于释放内存、销毁推理相关的数据类型,防止内存泄露
 UnloadPicture();
 
 // 8.定义一个资源去初始化的函数,用于AscendCL去初始化、运行管理资源释放(释放计算设备)
 DestroyResource();
}

编译与运行

bash sample_build.sh 
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/g++
-- Check for working CXX compiler: /usr/bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- env INC_PATH: /usr/local/Ascend/ascend-toolkit/latest
-- env LIB_PATH: /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/devlib
-- Configuring done
-- Generating done
-- Build files have been written to: /home/shaolin/demo/build/intermediates/host
Scanning dependencies of target main
[ 50%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable /home/shaolin/demo/out/main
[100%] Built target main
make for app MyFirstApp_build Successfully
bash sample_run.sh 
top 1: index[161] value[0.766602] 
top 2: index[162] value[0.155762] 
top 3: index[167] value[0.038452] 
top 4: index[163] value[0.021576] 
top 5: index[166] value[0.011642] 

参考

有疑问 欢迎加公众号 讨论

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1143651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【微服务开篇-RestTemplate服务调用、Eureka注册中心、Nacos注册中心】

1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。 1.1.单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 单体架构的优缺点如下&am…

4.Mbtiles瓦片包加载

愿你出走半生,归来仍是少年&#xff01; 1.Mbtiles mbtiles是在GIS开发中最常用的瓦片包格式&#xff0c;在移动端、桌面端都是常用的格式。 2.代码 通过OsgEarth的MBTilesImageLayer图层进行加载&#xff0c;也是封装成了一个静态的方法方便调用。 /// <summary&g…

PC5080USB适配器充电芯片5V/1A输入具有0V充电功能

概要&#xff1a; PC5080 是一款 5V USB 适配器输入&#xff0c;高精度双节锂离子电池充电管理芯片。具有0V充电功能&#xff0c;涓流充电、恒流充电、恒压充电和自动截止、自动再充等一套完整充电循环的充电管理芯片。芯片内部特设 9V 抗浪涌&#xff0c;芯片应用更安全可靠。…

Redis快速上手篇七(集群-六台虚拟机)

Redis集群 主从复制的场景无法吗满足主机单点故障时需要引入集群配置 一般数据库要处理的读请求远大于写请求 &#xff0c;针对这种情况&#xff0c;我们优化数据库可以采用读写分离的策略。我们可以部 署一台主服务器主要用来处理写请求&#xff0c;部署多台从服务器 &#…

vue笔记(二)

7、事件处理 7.1、事件的基本处理 事件的使用 使用v-on&#xff1a;xxx或者用xxx绑定事件&#xff0c;其中XXX是事件名事件的回调需要配置在methods对象中&#xff0c;最终出现在VM上methods配置的函数&#xff0c;不需要箭头函数 <div id"root"><h1>…

创建一个Keil项目

1、创建项目 2、选择存放的文件夹&#xff0c;还有设置项目名 3、选择型号&#xff08;因为没有STC,用下面这个替代&#xff0c;功能差不多&#xff09; 4、选择不用启动文件 5、就会得到下面这个&#xff0c;可以在Source Group 1下面编写代码了 6、右键source Group 1,添加c语…

Python 编写确定个位、十位以上方法及各数位的和程序

Python 编写确定数字位方法 Python 编写确定个位、十位Python 编写确定个位、十位、百位方法解析&#xff1a;Python 各数位的和程序 利用%&#xff08;取余符号&#xff09;、//&#xff08;整除&#xff09;符号。 Python 编写确定个位、十位 num 17 a num % 10 b num /…

【点云】有序/无序点云区别(详细详解)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Linux安装frp并实现内网穿透

准备 一台公网服务器&#xff08;配置无要求网络稳定就行&#xff09; 内网客户端&#xff08;准备要穿透出去的设备&#xff09; 服务端&#xff08;公网服务器&#xff09; 这里是为服务端配置frp 只关注frps和frps.ini即可 frp项目地址 &#xff1a;https://github.com/f…

一文详解汽车电CAN总线

1.什么是CAN总线 CAN总线(控制器区域网络)是一个中央网络系统&#xff0c;连接不同的电子控制单元(ECU)&#xff0c;车辆中的其他设备。现代汽车可以有100个ECU&#xff0c;因此CAN总线通信变得非常重要。 2.CAN总线流行的背景 集中式:CAN总线系统允许对连接到网络的ECU进行集…

完整攻防知识体系-你值得拥有

文章目录 前言内容简介目录 前言 根据中国互联网络信息中心&#xff08;CNNIC&#xff09;发布的第51次《中国互联网络发展状况统计报告》&#xff0c;截至2022年12月&#xff0c;我国网民规模为10.67亿&#xff0c;互联网普及率达75.6%。 我国有潜力建设全球规模最大、应用渗透…

springCore完整学习教程2,入门级别

上集说到&#xff1a;2. 3&#xff0c;咱们从2.3集开始 2. Externalized Configuration 2.3. External Application Properties Spring Boot会自动找到并加载应用程序。属性和应用程序。当应用程序启动时&#xff0c;从以下位置获取Yaml文件: 从类路径 类路径root 类路径/…

Android开发知识学习——编码、加密、Hash、序列化和字符集

文章目录 学习资源来自&#xff1a;扔物线加密古代密码学现代密码学对称加密非对称加密密码学密钥和登录密码Base64URL 使用的百分号编码压缩与解压缩图片与音频、视频编解码 序列化Hash字符集课后题 学习资源来自&#xff1a;扔物线 加密 古代密码学 起源&#xff1a;古代战…

微信公众号如何通过迁移变更主体?

公众号迁移后原来内容还在么&#xff1f;通过公众号迁移&#xff0c;可以实现这些目的&#xff1a;主体变更、开通留言功能、多号合并、订阅号升级为服务号、服务号转为订阅号。公众号迁移流程&#xff1a;①办理公证&#xff1b;②提交迁移申请&#xff1b;③第三方审核&#…

14. 机器学习 - KNN 贝叶斯

Hi&#xff0c;你好。我是茶桁。 咱们之前几节课的内容&#xff0c;从线性回归开始到最后讲到了数据集的处理。还有最后补充了SOFTMAX。 这些东西&#xff0c;都挺零碎的&#xff0c;但是又有着相互之间的关系&#xff0c;并且也都蛮重要的。并且是在学习机器学习过程当中比较…

Unity点乘的实战案例1

向量的点乘,也叫向量的内积、数量积&#xff0c;对两个向量执行点乘运算&#xff0c;就是对这两个向量对应位一一相乘之后求和的操作&#xff0c;点乘的结果是一个标量。点乘&#xff0c;也叫数量积。结果是一个向量在另一个向量方向上投影的长度&#xff0c;是一个标量。 • …

JVM进阶(3)

一)什么是垃圾&#xff1f; 垃圾指的是在应用程序中没有任何指针指向的对象&#xff0c;这个对象就是需要被回收的垃圾&#xff0c;如果不及时的针对内存中的垃圾进行清理&#xff0c;那么这些垃圾对象所占用的内存空间可能一直保留到应用程序结束&#xff0c;被保留的空间无法…

前端开发---在vue项目中使用openLayers

前端开发之在vue项目中使用openLayers 前言效果图在vue中渲染地图安装ol插件1、调用插件2、 初始话地图3、地图点击事件4、重置坐标5、通过坐标改变视图6、保存坐标点 vue中使用的源码 前言 本篇文章主要讲解openLayers的初步使用&#xff0c;包括渲染地图、获取点坐标、标记点…

Data Analysis With Python

文章目录 Data Analysis With PythonAnalyzing Numerical Data with NumPyCreating NumPy ArrayNumPy Array SlicingNumPy Array BroadcastingAnalyzing Data Using Pandas In this article, we will discuss how to do data analysis with Python. We will discuss all sorts …

平衡二叉树AVL的插入删除

在AVL树的插入操作中&#xff0c;假设插入一个结点后&#xff0c;当前节点p的平衡因子是&#xfe63;2&#xff0c;其左子结点的平衡因子是&#xff0b;1&#xff0c;左子结点的右子结点的平衡因子是&#xfe63;1。如图所示&#xff0c;请给出票转调整之后的结构。