算能BM1684X部署手写数字识别模型

大致流程---------------------------------------------------------------

参考《sophon-sail_zh》

移植步骤------------------------------------------------------------------------

首先搭建好自己的网络模型,并导出为onnx格式--具体可以参照-->

GitHub - warren-wzw/MNIST-pytorch

  1. 将onnx模型使用tpu-mlir工具转化为bmodel格式--具体可以参照---> https://kdocs.cn/l/cdwzqT3Hbyje

拷贝至板端:scp test_output_fp* linaro@10.12.13.66:/data

远程连接另一台linux--->ssh -p 22 linaro@10.12.13.66

  1. 在板端搭建好sophon-sail环境----> https://kdocs.cn/l/ce7T9GNtS3D3

python版----------------------------------------------------------------------------------------

在板端新建一个MNIST文件夹,文件目录如下,其中datasets存放测试数据集train-images-idx3-ubyte,test_output_fp16_1b.bmodel以及test_output_fp32_1b.bmodel为onnx转化后的bmodel模型,test.py为测试代码。

  1. 主要的原理就是使用sophon提供的api加载能够适配于BM1684X的bmodel类型的模型,并使用他们的api进行模型的推理,官方sail的API可以参考-->

3. API 参考 — sophon-sail v23.03.01 文档

  1. 下面讲解一下测试代码
#import cv2
import numpy as np
import sophon.sail as sail
import time

num = -1 
inference_time =[0]
print("--0-5 1-0 2-4 3-1 4-9 5-2 6-1 7-3 8-1 9-4 for example:if num =9 the pic's num is 4")
 
engine = sail.Engine("./test_output_fp32_1b.bmodel",0,sail.IOMode.SYSIO) #load model-use FP32model on tpu-0 and use sys memery
#engine = sail.Engine("./test_output_fp16_1b.bmodel",0,sail.IOMode.SYSIO) #load model-use FP16 on tpu-0 and use sys memery

graph_name =engine.get_graph_names()[0]                      #get_graph_names-test_output
input_tensor_name = engine.get_input_names(graph_name)[0]    #get_input_names-input.1
output_tensor_name = engine.get_output_names(graph_name)[0]  #get_output_names-25_LogSoftmax

batchsize,channel,height,width = engine.get_input_shape(graph_name,input_tensor_name) #get batchsize-1,channel-1,input image's height-28 & width-28

#read image
with open("./datasets/train-images-idx3-ubyte","rb") as f:
    file = f.read()
for i in range(8000): 
    num =num +1  
    i = 16+784*num
    image1 = [int(str(item).encode('ascii'),16) for item in file[i:i+784]]

    #reshap input data
    input_data = np.array(image1,dtype=np.float32).reshape(1,1,28,28)  #reshape the image to 1 1 28 28
    input_data_final = {input_tensor_name:input_data}     #because the process's parmeter(input_data)  must be dictionary so use{}
    start_time = time.time()
    outputs = engine.process(graph_name,input_data_final) #model inference
    end_time = time.time()
    inference_time.append(end_time - start_time)  
 
    result = outputs[output_tensor_name]  #use output_tensor_name to get the tensor
    max_value=np.argmax(result)           #get the index of the best score
    print("----------------------------------the result is ",max_value,"the time is ",inference_time[num]*1000,"ms")

mean = (sum(inference_time) / len(inference_time))*1000
print("-----FP32--","loop ",num+1,"times","average time",mean,"ms")

  1. 测试结果

FP32

FP16

基本稳定在4%峰值可达8%

C++版本---------------------------------------------------------------------------------------------------------

首先安装好c++交叉编译环境

--> https://kdocs.cn/l/cbe77SdEwLKm

1:采用交叉编译的方式进行编译,新建文件夹MNIST

文件结构

CMakeFile.txt

main.cpp

#define USE_FFMPEG 1
#define USE_OPENCV 1
#define USE_BMCV 1
#include <stdio.h>
#include <sail/cvwrapper.h>
#include <iostream>
#include <string>
#include <numeric>
#include <sys/time.h>

#include "spdlog/spdlog.h"
#include "spdlog/fmt/fmt.h"
#include "engine.h"

using namespace std;
using namespace sail;
const std::string& bmodel_path_fp32="./test_output_fp32_1b.bmodel";
const std::string& bmodel_path_fp16="./test_output_fp16_1b.bmodel";
const int MODEL_IN_WIDTH = 28;
const int MODEL_IN_HEIGHT = 28;
const int MODEL_CHANNEL = 1;
const int loop_count = 1000;
int num = -1;

static inline int64_t getCurrentTimeUs()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000 + tv.tv_usec;
}
void Load_data(int num,unsigned char * input_image)
{
    int j=16+784*num;
    FILE *file = fopen("./datasets/train-images-idx3-ubyte", "rb");
    if (file == NULL) {
        printf("can't open the file!\n");
    }
    fseek(file,j,SEEK_SET);
    fread(input_image,sizeof(char),784,file);
/*     for(int i=0;i<MODEL_IN_WIDTH;i++){
        for(int j=0;j<MODEL_IN_WIDTH;j++){
            printf("%4d",input_image[i*28+j]);
        }
        printf("\n");
    } */ 
    fclose(file);
}

void Array_change(float input_aray[][MODEL_CHANNEL][MODEL_IN_WIDTH][MODEL_IN_HEIGHT],unsigned char *input_image)
{
   int index=0;
    for (int i = 0; i < 1; i++) {
        for (int j = 0; j < MODEL_CHANNEL; j++) {
            for (int k = 0; k < MODEL_IN_HEIGHT; k++) {
                for (int l = 0; l < MODEL_IN_WIDTH; l++) {
                    input_aray[i][j][k][l] = (float)input_image[index++];
                    //cout<<input_aray[i][j][k][l]<<" ";
                }
                //cout<<endl;
            }
        }
        //cout<<endl;
    } 
}

void Bubble_sort(float *buffer,int num)
{
    float temp;
    for(int i=0; i<num;i++){
        for(int j=0; j<num-i-1;j++){
            if(buffer[j]>buffer[j+1]){
                temp = buffer[j];
                buffer[j]=buffer[j+1];
                buffer[j+1]=temp;
            }
        }
    }
}

void dump_shape(std::vector<int> shape)
{
    cout<<"[  ";
    for (const int& value : shape) {
        std::cout << value << " ";
    }
     cout<<"]"<<endl;
}
bool inference(int device_id)
{
    int64_t time[loop_count] = {};
    unsigned char input_image[784]={};
    float input_aray[1][MODEL_CHANNEL][MODEL_IN_HEIGHT][MODEL_IN_WIDTH]={};
    int64_t sum=0;
    float buffer_copy[]={};
    // init Engine
    sail::Engine engine(device_id);    
    // load bmodel without builtin input and output tensors
    engine.load(bmodel_path_fp32);
    // get model info
    auto graph_name = engine.get_graph_names().front();
    auto input_name = engine.get_input_names(graph_name).front();
    auto output_name = engine.get_output_names(graph_name).front();
    std::vector<int> input_shape = {1, 1, 28, 28};
    std::map<std::string, std::vector<int>> input_shapes;
    input_shapes[input_name] = input_shape;
    auto output_shape = engine.get_output_shape(graph_name, output_name);
    auto input_dtype = engine.get_input_dtype (graph_name, input_name);
    auto output_dtype = engine.get_output_dtype(graph_name, output_name);
    cout<<"----------------graph_name is "<<graph_name<<endl;
    cout<<"----------------input_name is "<<input_name<<endl;
    cout<<"----------------output_name is "<<output_name<<endl;
    cout<<"----------------input_dtype is "<<input_dtype<<endl;
    cout<<"----------------output_dtype is "<<output_dtype<<endl;
    cout<<"output shape is ";
    dump_shape(output_shape);
    cout<<"input shape is ";
    dump_shape(input_shape);
    // get handle to create input and output tensors
    sail::Handle handle = engine.get_handle();

    // allocate input and output tensors with both system and device memory
    sail::Tensor in(handle, input_shape, input_dtype, true, true);
    sail::Tensor out(handle, output_shape, output_dtype, true, true);
    std::map<std::string, sail::Tensor*> input_tensors = {{input_name, &in}};
    std::map<std::string, sail::Tensor*> output_tensors = {{output_name, &out}};
    // prepare input and output data in system memory with data type of float32
    float* input = nullptr;
    float* output = nullptr;
    int in_size = std::accumulate(input_shape.begin(), input_shape.end(),
                                    1, std::multiplies<int>());
    int out_size = std::accumulate(output_shape.begin(), output_shape.end(),
                                    1, std::multiplies<int>());
    if (input_dtype == BM_FLOAT32) {
        input = reinterpret_cast<float*>(in.sys_data());
    } 
    else {
        input = new float[in_size];
    }
    if (output_dtype == BM_FLOAT32) {
        output = reinterpret_cast<float*>(out.sys_data());
    } 
    else {
        output = new float[out_size];
    }
    //loop 
    for(int times=0;times<loop_count;times++) {
        num++;
        Load_data(num,input_image);
        Array_change(input_aray,input_image);
        bool status=in.own_dev_data();
        cout<<"own_dev_data "<<status<<endl;
        status=in.own_sys_data();
        cout<<"own_sys_data "<<status<<endl;
        in.reset_sys_data(input_aray,input_shape);
         
        // set io_mode SYSO:Both input and output tensors are in system memory.
        engine.set_io_mode(graph_name, sail::  SYSIO);

        bm_data_type_t ret =in.dtype();
        printf("in.dtype is %d\n", ret);

        //inference
        int64_t start_time = getCurrentTimeUs();
        engine.process(graph_name, input_tensors, input_shapes, output_tensors);
        int64_t end_time = getCurrentTimeUs();
        time[times]=end_time-start_time;
        sum = sum+time[times];
        //post process
        auto real_output_shape = engine.get_output_shape(graph_name, output_name);
        float* output_data = reinterpret_cast<float*>(out.sys_data());
        for(int i = 0; i < 10;i++){
            buffer_copy[i]=output_data[i];
            //printf("output_data is %f \n",output_data[i]);
        }
        Bubble_sort(output_data,10);
        for(int i =0;i<10;i++){
            if(buffer_copy[i]==output_data[9]){
                printf("------------------------------------------the pic value is %d \n",i);
            }
        }

        /* cout<<"real_output_shape is "<<"[  ";
        dump_shape(real_output_shape);*/
        printf(": Elapse Time = %.3f ms \n", time[times] / 1000.f);
    }
    printf("--------loop %d times sum is %.4f ms average time is %.3f ms\n", loop_count,sum / 1000.f,(sum / 1000.f)/loop_count);
    return true;
}
int main()
{
    int device_id = 0;
    int tpu_num=get_available_tpu_num();
    printf("the tpu number is %d\n", tpu_num);
    
    bool status = inference(device_id);
    return 0;    
}

打印结果

fp32

fp16

int8

bm-smi

基本稳定在2%,峰值为4

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是P2P?

P2P (Peer-to-Peer) 是一种分布式的网络架构&#xff0c;其中各个节点&#xff08;通常被称为“peers”或“节点”&#xff09;直接进行数据共享和交换&#xff0c;而无需依赖中央服务器。P2P 网络强调平等的参与和共享&#xff0c;每个节点既可以是数据的消费者&#xff08;下…

Python数据分析实战-列表字符串、字符串列表、字符串的转化(附源码和实现效果)

实现功能 str([None,master,hh]) ---> [None,"master","hh"] ---> "None,master,hh" 实现代码 import re import astx1 str([None,master,hh]) print(x1)x2 ast.literal_eval(x1) print(x2)x3 ",".join(str(item) for item…

ARTS 挑战打卡的第1天,我学到了这些~

关于 ARTS 的释义 —— 每周完成一个 ARTS&#xff1a; ● Algorithm: 每周至少做一个 LeetCode 的算法题 ●Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一个技术技巧 ● Share: 分享一篇有观点和思考的技术文章 深度学习 深度学习概念崛起框架 主页传送门&…

最大交换(力扣)枚举 JAVA

给定一个非负整数&#xff0c;你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。 示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。 注意: 给定数字的范围是 [0, 10^8] 解题思路&#xff1a; 1、数最…

学习笔记-JVM监控平台搭建

SpringBoot Actuator 1 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>2 开启配置 # 暴露所有的监控点【含Prometheus】 management.endpoin…

C语言 冒泡排序

目录 一、原理 二、代码演示 三、代码优化 一、原理 假设&#xff1a; int arr[] { 9,8,7,6,5,4,3,2,1,0 }; 将 arr 内的元素进行升序排列&#xff0c;得到一个新的数组 int arr[] { 0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;…

SAP从入门到放弃系列之BOM组-Part1

目录 BOM组两种模式&#xff1a; 创建BOM的方式 方式一&#xff1a;直接在每个工厂分别创建BOM。 方式二&#xff1a;创建BOM组&#xff0c;然后每个工厂参考创建 方式三&#xff1a;创建BOM组&#xff0c;每个工厂参考创建&#xff0c;针对有特殊的工厂复制BOM组后进行调…

【Java】数据交换 Json 和 异步请求 Ajax

&#x1f384;欢迎来到边境矢梦的csdn博文&#xff0c;本文主要讲解Java 中 数据交换和异步请求 Json&Ajax 的相关知识&#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#…

PCL 计算外接圆的半径

目录 一、算法原理1、计算公式2、主要函数3、源码解析二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。爬虫自重。 一、算法原理 1、计算公式

函数的模拟实现

题一&#xff1a; 模拟实现strncpy #include <stdio.h>void my_strncpy(char* arr2, char* arr1, size_t num){int i 0;for (i 0; i < num; i){*(arr2 i) *(arr1 i);}}int main(){char arr1[] "hello liangzai";char arr2[10] { 0 };//strncpy(ar…

【Spring Boot】构建RESTful服务 — 使用Swagger生成Web API文档

使用Swagger生成Web API文档 高质量的API文档在系统开发的过程中非常重要。本节介绍什么是Swagger&#xff0c;如何在Spring Boot项目中集成Swagger构建RESTful API文档&#xff0c;以及为Swagger配置Token等通用参数。 1.什么是Swagger Swagger是一个规范和完整的框架&…

怎么快速搭建BI?奥威BI系统做出了表率

搭建BI系统有两大关键&#xff0c;分别是环境搭建和数仓建设。这两点不管是哪一个都相当地费时费力&#xff0c;那要怎么才能快速搭建BI平台&#xff0c;顺利实现全企业数字化运营决策&#xff1f;奥威BI系统方案&#xff0c;你值得拥有&#xff01; 奥威BI系统方案&#xff0…

12.Eclipse导入Javaweb项目

同事复制一份他的项目给我ekp.rar (懒得从SVN上拉取代码了)放在workspace1目录下 新建一个文件夹 workspace2,Eclipse切换到workspace2工作空间 选择Import导入 选择导入的项目(这里是放到workspace1里面) 拷贝一份到workspace2里面 例子 所有不是在自己电脑上开发的web项目…

haproxy基本编译环境部署

前提&#xff1a;haproxy支持基于lua实现功能扩展&#xff08;需要安装比较新的lua语言&#xff0c;方便进行haproxy编译&#xff09;。 wget http://www.lua.org/ftp/lua-5.3.5.tar.gz lua -v # 检查环境 yum list lua # 查看可以安装环境 同时还需要gcc&#xff0c;gcc-c&…

Transformer(一)简述(注意力机制,NLP,CV通用模型)

目录 1.Encoder 1.1简单理解Attention 1.2.什么是self-attention 1.3.怎么计算self-attention 1.4.multi-headed 1.5.位置信息表达 2.decorder&#xff08;待补充&#xff09; 参考文献 1.Encoder 1.1简单理解Attention 比方说&#xff0c;下图中的热度图中我们希望专注于…

基础篇-环境搭建

JDK安装 https://www.oracle.com/java/technologies/downloads/ 安装完成后&#xff0c;一直点下一步就行 打开控制面板输入cmd运行&#xff0c;控制台输入java -version。如果看到版本号就说明我们安装成功了 JDK的组成 1. JVM JAVA虚拟机&#xff0c;JAVA真正运行的地方 …

喜报!诚恒科技与赛时达科技达成BI金蝶云星空项目合作

随着全球数字化浪潮轰轰烈烈袭来&#xff0c;仅仅凭借手工处理的方式难以在庞大的数据海洋中精准获取信息、把握市场需求、了解目标用户&#xff0c;为企业创新提供强有力的支持。深圳赛时达科技有限公司&#xff08;简称赛时达科技&#xff09;希望通过数字化转型实现从手工处…

虚拟世界探索:科技之下的未来可能性

随着科技的飞速发展&#xff0c;人们对于虚拟世界的憧憬和探索也日益加深。虚拟世界&#xff0c;那是一个超越现实的概念&#xff0c;一个充满想象力和创造力的领域。然而&#xff0c;虚拟世界究竟有可能实现吗&#xff1f;这是一个引人深思的问题。 虚拟世界&#xff0c;首先让…

SQL | 高级数据过滤

5-高级数据过滤 通过组合WHERE子句&#xff0c;建立功能更强的检索语句。 5.1-组合WHERE子句 前面写的都是单一条件下的WHERE子句&#xff0c;SQL语句允许给出多个WHERE子句来组合检索&#xff0c;这些WHERE子句通过AND子句或者OR子句进行连接。 操作符&#xff08;operato…

【数据结构与算法】稀疏数组

文章目录 一&#xff1a;为什么会使用稀疏数组1.1 先看一个实际的需求1.2 基本介绍1.2.1 稀疏数组的处理方法1.2.2 数组的举例说明1.2.3 应用实例1.2.4 整体思路分析二维数组转稀疏数组的思路稀疏数组转原始的二维数组的思路 二&#xff1a;代码实现2.1 创建一个原始的11*11二维…
最新文章