从零构建深度学习推理框架-1 简介和Tensor
源代码作者:https://github.com/zjhellofss
本文仅作为个人学习心得领悟 ,将原作品提炼,更加适合新手
什么是推理框架?
深度学习推理框架用于对已训练完成的神经网络进行预测,也就是说,能够将深度训练框架例如Pytorch、Tensorflow中定义的算法移植到中心侧和端侧,并高效执行。与训练框架不同的是,深度学习推理框架没有梯度反向传播功能,因为算法模型文件中的权重系数已经被固化,推理框架只需要读取、加载并完成对新数据的预测即可。
模型加载阶段
训练完成的模型被放置在两个文件中,一个是模型定义文件,一个是权重文件。
ONNX文件是将模型定义文件和权重文件合二为一的文件格式。
关于维度的预备知识
在Tensor张量中,共有三维数据进行顺序存放,分别是Channels(维度),Rows(行高), Cols(行宽),
三维矩阵我们可以看作多个连续的二维矩阵组成,最简单的方法就是std::vector<std::vector<std::vector<float>>>,但是这种方法非常不利于数据的访问(尤其是内存不连续的问题) 、修改以及查询,特别是在扩容的时候非常不方便。不能满足使用需求
不连续会造成数组访问慢的问题,在这里我用chrono做了测试:
#include<iostream> #include <gtest/gtest.h> #include <armadillo> #include <glog/logging.h> #include <vector> #include <chrono> #define TICK(x) auto bench_##x = std::chrono::steady_clock::now(); #define TOCK(x) std::cout << #x ": " << std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - bench_##x).count() *1000000<< "ns" << std::endl; using namespace std; int m = 10000 , n = 10000 , channel = 2; TEST(test_compare_vector , speed2D){LOG(INFO)<<"Test of vector & cube"<<endl;vector<vector<float>> matA (m , vector<float>(n , 1));TICK(2D);for (int i = 0; i <matA.size(); i++){for (int j = 0; j < matA[0].size(); j++){matA[i][j] = matA[i][j]*matA[j][i];}}TOCK(2D);arma::fcube matB( m , n , 1 , arma::fill::ones);TICK(cube);for (int i = 0; i <m; i++){for (int j = 0; j < n; j++){matB(i , j , 0) = matB(i , j , 0)*matB( j , i , 0);}}TOCK(cube);}
因此,综合考虑灵活性和开发的难易度,作者在这里以Armadillo类中的arma::mat(矩阵 matrix)类和arma::cube 作为数据管理(三维矩阵)类来实现Tensor 库中类的主体,一个cube由多个matrix组成,cube又是Tensor类中的数据实际管理者。一块连续的大内存分配开始写一个tensor,工作量会特别大,折中!
作者设计的类是以arma::cube为基础实现了Tensor类,我们主要是提供了更方便的访问方式和对外接口。

上图即为Tensor与cube的对应关系。

cube一般有多个维度,在channel维度上有多个matrix。
arma::cube(2,5,3),表示当前的三维矩阵共有2个矩阵构成,每个矩阵都是5行3列的。如果放在我们项目中会以这形式提供 Tensor tensor(2,5,3)
下图是这种情况下的三维结构图,可以看出一个Cube一共有两个Matrix,也就是共有两个Channel。一个Channel放一个Matrix. Matrix的行宽均为Rows和Cols.

Tensor类方法总览

这里的很多都不需要我们重新去造轮子
比如Fill(float value)就可以直接调用cube里的fill:
void Tensor<float>::Fill(float value) {CHECK(!this->data_.empty());this->data_.fill(value); }
再比如这个at:
float &Tensor<float>::at(uint32_t channel, uint32_t row, uint32_t col) {CHECK_LT(row, this->rows());CHECK_LT(col, this->cols());CHECK_LT(channel, this->channels());return this->data_.at(row, col, channel); }
再难一些的就需要我们自己去实现了:
Fill(vector)方法实现:
TEST(test_tensor, fill) {using namespace kuiper_infer;Tensor<float> tensor(3, 3, 3);ASSERT_EQ(tensor.channels(), 3);ASSERT_EQ(tensor.rows(), 3);ASSERT_EQ(tensor.cols(), 3);std::vector<float> values;for (int i = 0; i < 27; ++i) {values.push_back((float) i);}tensor.Fill(values);LOG(INFO) << tensor.data();int index = 0;for (int c = 0; c < tensor.channels(); ++c) {for (int r = 0; r < tensor.rows(); ++r) {for (int c_ = 0; c_ < tensor.cols(); ++c_) {ASSERT_EQ(values.at(index), tensor.at(c, r, c_));index += 1;}}}LOG(INFO) << "Test1 passed!";
}
padding功能实现:
TEST(test_tensor, padding1) {using namespace kuiper_infer;Tensor<float> tensor(3, 3, 3);ASSERT_EQ(tensor.channels(), 3);ASSERT_EQ(tensor.rows(), 3);ASSERT_EQ(tensor.cols(), 3);tensor.Fill(1.f); // 填充为1tensor.Padding({1, 1, 1, 1}, 0); // 边缘填充为0ASSERT_EQ(tensor.rows(), 5);ASSERT_EQ(tensor.cols(), 5);int index = 0;// 检查一下边缘被填充的行、列是否都是0for (int c = 0; c < tensor.channels(); ++c) {for (int r = 0; r < tensor.rows(); ++r) {for (int c_ = 0; c_ < tensor.cols(); ++c_) {if (c_ == 0 || r == 0) {ASSERT_EQ(tensor.at(c, r, c_), 0);}index += 1;}}}LOG(INFO) << "Test2 passed!";
}
再谈谈Tensor类中数据的排布
我们以具体的图片作为例子,来讲讲Tensor中数据管理类arma::cube的数据排布方式,Tensor类是arma::cube对外更方便的接口,所以说armadillo::cube怎么管理内存的,Tensor类就是怎么管理内存的。希望大家的能理解到位。如下图中的一个Cube,Cube的维度是2,每个维度上存放的是一个Matrix,一个Matrix中的存储空间被用来存放一张图像(lena) 。一个框内(channel)是一个Matrix,Matrix1存放在Cube第1维度(channel 1)上,Matrix2存放在Cube的第2维度上(channel 2). Matrix1和Matrix2的Rows和Cols均代表着图像的高和宽,在本例中就是512和384。


相关文章:
从零构建深度学习推理框架-1 简介和Tensor
源代码作者:https://github.com/zjhellofss 本文仅作为个人学习心得领悟 ,将原作品提炼,更加适合新手 什么是推理框架? 深度学习推理框架用于对已训练完成的神经网络进行预测,也就是说,能够将深度训练框…...
使用WGCLOUD监测安卓(Android)设备的运行状态
WGCLOUD是一款开源运维监控软件,除了能监控各种服务器、主机、进程应用、端口、接口、docker容器、日志、数据等资源 WGCLOUD还可以监测安卓设备,比如安卓手机、安卓设备等 我们只要下载对应的安卓客户端,部署运行即可,如下是下…...
C++笔记之迭代器失效问题处理
C笔记之迭代器失效问题处理 code review! 参考博文:CSTL迭代器失效的几种情况总结 文章目录 C笔记之迭代器失效问题处理一.使用返回新迭代器的插入和删除操作二.对std::vector 来说,擦除(erase)元素会导致迭代器失效 一.使用返回…...
Tomcat的startup.bat文件出现闪退问题
对于双击Tomcat的startup.bat文件出现闪退问题,您提供的分析是正确的。主要原因是Tomcat需要Java Development Kit (JDK)的支持,而如果没有正确配置JAVA_HOME环境变量,Tomcat将无法找到JDK并启动,从而导致闪退。 以下是解决该问题…...
JAVA8-lambda表达式8:在设计模式-模板方法中的应用
传送门 JAVA8-lambda表达式1:什么是lambda表达式 JAVA8-lambda表达式2:常用的集合类api JAVA8-lambda表达式3:并行流,提升效率的利器? JAVA8-lambda表达式4:Optional用法 java8-lambda表达式5…...
React之组件间通信
React之组件间通信 组件通信: 简单讲就是组件之间的传值,包括state、函数等 1、父子组件通信 父组件给子组件传值 核心:1、自定义属性;2、props 父组件中: 自定义属性传值 import Header from /components/Headerconst Home ()…...
【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比
【MATLAB第58期】基于MATLAB的PCA-Kmeans、PCA-LVQ与BP神经网络分类预测模型对比 一、数据介绍 基于UCI葡萄酒数据集进行葡萄酒分类及产地预测 共包含178组样本数据,来源于三个葡萄酒产地,每组数据包含产地标签及13种化学元素含量,即已知类…...
CF1833 A-E
A题 题目链接:https://codeforces.com/problemset/problem/1833/A 基本思路:for循环遍历字符串s,依次截取字符串s的子串str,并保存到集合中,最后输出集合内元素的数目即可 AC代码: #include <iostrea…...
【深度学习】【Image Inpainting】Generative Image Inpainting with Contextual Attention
Generative Image Inpainting with Contextual Attention DeepFillv1 (CVPR’2018) 论文:https://arxiv.org/abs/1801.07892 论文代码:https://github.com/JiahuiYu/generative_inpainting 论文摘录 文章目录 效果一览摘要介绍论文贡献相关工作Image…...
二维深度卷积网络模型下的轴承故障诊断
1.数据集 使用凯斯西储大学轴承数据集,一共有4种负载下采集的数据,每种负载下有10种 故障状态:三种不同尺寸下的内圈故障、三种不同尺寸下的外圈故障、三种不同尺寸下的滚动体故障和一种正常状态 2.模型(二维CNN) 使…...
redis突然变慢问题定位
CPU 相关:使用复杂度过高命令、O(N)的这个N,数据的持久化,都与耗费过多的 CPU 资源有关 内存相关:bigkey 内存的申请和释放、数据过期、数据淘汰、碎片整理、内存大页、内存写时复制都与内存息息相关 磁盘…...
React井字棋游戏官方示例
在本篇技术博客中,我们将介绍一个React官方示例:井字棋游戏。我们将逐步讲解代码实现,包括游戏的组件结构、状态管理、胜者判定以及历史记录功能。让我们一起开始吧! 项目概览 在这个井字棋游戏中,我们有以下组件&am…...
七大经典比较排序算法
1. 插入排序 (⭐️⭐️) 🌟 思想: 直接插入排序是一种简单的插入排序法,思想是是把待排序的数据按照下标从小到大,依次插入到一个已经排好的序列中,直至全部插入,得到一个新的有序序列。例如:…...
【点云处理教程】03使用 Python 实现地面检测
一、说明 这是我的“点云处理”教程的第3篇文章。“点云处理”教程对初学者友好,我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中,我们在不使用 Open3D 库的情况下从深度数据计算点云。在本教程中,我们将首先…...
Python 日志记录:6大日志记录库的比较
Python 日志记录:6大日志记录库的比较 文章目录 Python 日志记录:6大日志记录库的比较前言一些日志框架建议1. logging - 内置的标准日志模块默认日志记录器自定义日志记录器生成结构化日志 2. Loguru - 最流行的Python第三方日志框架默认日志记录器自定…...
最近遇到一些问题的解决方案
最近遇到一些问题的解决方案 SpringBoot前后端分离参数传递方式总结Java8版本特性讲解idea使用git更新代码 : update project removeAll引发得java.lang.UnsupportedOperationException异常Java的split()函数用多个不同符号分割 Aspect注解切面demo 抽取公共组件,使…...
封装hutool工具生成JWT token
private static final String KEY "abcdef";/*** 生成token** param payload 可以存放用户的一些信息,不要存放敏感字段* return*/public static String createToken(Map<String, Object> payload) {//十分重要,不禁用发布到生产环境无…...
【手机】三星手机刷机解决SecSetupWizard已停止
三星手机恢复出厂设置之后,出现SecSetupWizard已停止的解决方案 零、问题 我手上有一部同学给的三星 GT-S6812I,这几天搞了张新卡,多余出的卡就放到这个手机上玩去了。因为是获取了root权限的(直接使用KingRoot就可以࿰…...
GDAL C++ API 学习之路 OGRGeometry 抽象曲线基类 OGRCurve
OGRCurve class "ogrsf_frmts.h" OGRCurve 是 OGR(OpenGIS Simple Features Reference Implementation)几何库中的一个基类,表示曲线几何对象。它是 OGRLineString 和 OGRCircularString 的抽象基类,用于表示曲…...
etcd底层支持的数据库有哪些
etcd底层的数据库可以更换。在当前版本的etcd中,它使用的是BoltDB作为默认的后端存储引擎。但是,etcd提供了接口允许您更换数据库后端,以便根据需要选择更合适的存储引擎。 以下是etcd支持的一些后端数据库选项: BoltDBÿ…...
Insomnia终极指南:构建高效API测试与协作的完整工作流
Insomnia终极指南:构建高效API测试与协作的完整工作流 【免费下载链接】insomnia The open-source, cross-platform API client for GraphQL, REST, WebSockets, SSE and gRPC. With Cloud, Local and Git storage. 项目地址: https://gitcode.com/gh_mirrors/in/…...
3分钟搞定Windows 11系统优化:Win11Debloat开源工具完整指南
3分钟搞定Windows 11系统优化:Win11Debloat开源工具完整指南 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter …...
【Anaconda】使用指南及问题汇总(自用)
安装 1. Anaconda的下载与安装 除了安装路径修改,其他的一路默认就好 2. Anaconda修改环境变量 因为我们这一步才手动添加环境变量,所以第一步安装的时候不要让它自动配置环境变量了。 用户变量或者系统变量都可以。建议系统变量,方便后…...
军规零外源设备要求,无感定位完全替代UWB硬件堆叠方案
军规零外源设备要求,无感定位完全替代UWB硬件堆叠方案军队营区管控、战备执勤、野外演训、涉密阵地等场景,严格遵循军规装备管理准则,奉行零外源附加设备硬性管控标准,严禁额外加装大量外置终端、基站、线缆类附属设施。传统UWB定…...
MatterGen完整指南:如何用AI在5分钟内生成高性能无机材料
MatterGen完整指南:如何用AI在5分钟内生成高性能无机材料 【免费下载链接】mattergen Official implementation of MatterGen -- a generative model for inorganic materials design across the periodic table that can be fine-tuned to steer the generation to…...
如何用t3mujinpack为你的Darktable照片添加经典胶片质感:新手完整指南
如何用t3mujinpack为你的Darktable照片添加经典胶片质感:新手完整指南 【免费下载链接】t3mujinpack Collection of film emulation presets for open-source RAW developer software Darktable. 项目地址: https://gitcode.com/gh_mirrors/t3/t3mujinpack 你…...
深度解析抖音直播回放下载架构设计:从FLV流捕获到多线程存储优化
深度解析抖音直播回放下载架构设计:从FLV流捕获到多线程存储优化 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fall…...
抖音批量下载终极指南:5分钟学会无水印视频下载与智能归档
抖音批量下载终极指南:5分钟学会无水印视频下载与智能归档 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback s…...
JMeter登录Cookie提取与传递全链路实战指南
1. 为什么“提取登录Cookie”是接口测试里最常卡壳的一步做JMeter接口测试的人,十有八九在登录环节栽过跟头——明明登录请求返回了200,Header里也明明白白写着Set-Cookie: JSESSIONIDabc123; Path/; HttpOnly,可后续所有带权限的接口全报401…...
小白进阶挖洞大神 SRC 漏洞挖掘全流程实战指南
凌晨两点,大学生张三盯着电脑屏幕突然跳出的「高危漏洞奖励到账」提示,手抖得差点打翻泡面——这是他挖到人生第一个SRC漏洞(某电商平台的越权访问漏洞)后收到的第一笔奖金,金额足够支付三个月生活费。这样的故事&…...

