从0开始做yolov5模型剪枝
文章目录
- 从0开始做yolov5模型剪枝 **·**
- 1 前言
- 2 GitHub取源码
- 3 原理
- 3.1 原理
- 3.2 network slimming过程
- 4 具体实施步骤
- 4.1 安装虚拟环境
- 4.2 配置参数
- 4.2.1 数据集参数
- 4.2.2 模型结构参数
- 4.2.3 train.py中的参数
- 4.3 正常训练
- 4.3.1 准备
- 4.3.2 训练及问题解决
- 4.4 稀疏化训练
- 4.4.1 参数设置
- 4.4.2 稀疏化训练与问题
- 4.5 剪枝
- 4.5.1 参数设置
- 4.5.2 剪枝
- 4.6 finetune剪枝的网络
- 4.6.1 参数设置
- 4.6.2 finetune
- 4.7 循环稀疏训练->剪枝->finetune网络
从0开始做yolov5模型剪枝 ·
1 前言
【整个流程中,在正常train,sparityTrain,prune,finetune遇到10多个的问题,包括AttributeError、ModuleNotFoundError、RuntimeError、SyntaxError、TypeError等问题的解决方法,详见内容】
为了将现有模型移植到ARM平台,同时保证模型准确率的基础上,减少模型的算力消耗和推理时间。
之前有做实验对比了YOLOv5、 YOLOv7、 YOLOv8,结合不同版本模型推理时间和准确率,并查了很多资料,包括大部分人博客描述,结合大部分人经验,我们觉的yolov5的泛化能力较好。故在考虑训练自己的模型且在X86和ARM平台上部署,我们针对yolov5做模型的训练和剪枝,以便轻量化小模型的部署。
当然,我们还需要对最终的模型执行INT8量化的操作,以便降低目标检测的推理时间。
2 GitHub取源码
下载如下路径的源码:
https://github.com/midasklr/yolov5prune/tree/v6.0
本文为 上面GitHub上取6.0的版本做剪枝
3 原理
【根据一些博客/文章对yolov5剪枝的介绍,简单总结一下yolov5模型剪枝的原理】
3.1 原理
原理论文:Learning Efficient Convolutional Networks through Network Slimming
ref: Pruning Filters for Efficient ConvNets( https://arxiv.org/abs/1608.08710 )
ref: https://blog.csdn.net/qq_42835363/article/details/129125376?spm=1001.2014.3001.5501
ref: https://blog.csdn.net/IEEE_FELLOW/article/details/117236025
ref: Yolov5_5.0上做模型剪枝
输入经过BN(Batch Normalization)层获得归一化后的分布。BN层存在两个可训练参数γ(gamma)、β(beta)。
当gamma和betaγ趋于0时,输入相当于乘以了0,此时该channel上的卷积将输出0,这是无意义的。因此,可以认为剔除这样冗余的channel对模型性能没有影响。
普通网络训练时,由于初始化,gamma一般分布在1附近。为了使gamma趋于0,可以通过添加L1正则来约束,使得系数稀疏化。论文中把添加gammaL1正则的训练称为稀疏训练。
稀疏训练后,裁剪掉稀疏很小的层,对应激活也很小,所以对后面的影响非常小,反复迭代这个过程,可以获得小型的模型,步骤如图1。
图1
3.2 network slimming过程
① 先初始化网络,对BN层的参数添加L1正则并对网络训练。
② 统计网络中的γ(gamma),设置剪枝率对网络进行裁剪。
③ 将裁减完的网络finetune,完成剪枝工作。
4 具体实施步骤
4.1 安装虚拟环境
解压下载的源码,进入yolov5prune_6.0目录下,依次执行下面的操作
# 1 创建虚拟环境
conda create -n yolov5prune
# 2 激活虚拟环境
conda activate yolov5prune
# 3 安装虚拟环境(根据yolov5prune_6.0根目录下的requirements.txt安装)
pip install -r requirements.txt
4.2 配置参数
4.2.1 数据集参数
自己的数据集结构如下
--datasTrain
------images
----------train # 存放训练数据集的图片(.jpg)
----------val
----------test
------labels
----------train # 存放训练图片对应的标签文件(.txt)
----------val
----------tes
在/yolov5prune_6.0/data/目录下,仿照coco128.yaml中的结构创建my_yolov5.yaml文件。其中内容如下
# Train/val/test sets as
# 1) dir: path/to/imgs,
# 2) file: path/to/imgs.txt, or
# 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: /home/user/hlj/MyTrain/datasTrain3_More/ # dataset root dir
train: images/train/ # train images (relative to 'path') 128 images
val: images/val/ # val images (relative to 'path') 128 images
test: images/test/ # test images (optional)nc: 11 # number of classes
names: ['pedes', 'car', 'bus', 'truck', 'bike', 'elec', 'tricycle', 'coni', 'warm', 'tralight', 'specVehi']
4.2.2 模型结构参数
修改yolov5prune_6.0/models/yolov5s.yaml中的目标检测类型,使其适配自己数据集的目标检测类型数量。如下
nc: 11
4.2.3 train.py中的参数
设置train.py中的参数,主要包括如下:
'--weights', default='./yolov5s.pt' # 由于我要从头训练,所以注释了此参数
'--cfg', default='./models/yolov5s.yaml'
'--data', default='./data/my_yolov5.yaml'
'--epochs', default=300 # 由于从头训练,所以epochs值设的比较大
'--batch-size', default=-1
'--imgsz', default=640 # 考虑部署
4.3 正常训练
4.3.1 准备
由于我是SSH链接,所以先创建/打开tmux会话
tmux new -s prunesession
若【先按下ctrl+b,然后再单独按d】退出会话的话,下次再进入会话,需要使用命令
tmux a -t prunesession
进入会话,先进入项目目录下,并激活虚拟环境(若已激活,可忽略)
cd ../yolov5prune_6.0/
source activate yolov5prune
训练结束之后要删除会话
tmux kill-session -t prunesession
4.3.2 训练及问题解决
执行如下命令,进行训练
python3 train.py
【问题1】
运行train.py文件后,报了如下错误
ModuleNotFoundError: No module named 'utils.loggers.wandb'
提示缺包,根据别人的攻略,下载U神对应yolov5_6.0版本的代码,然后把yolov5_6.0\utils\loggers\目录下的整个wandb文件夹拷贝到yolov5prune_6.0\utils\loggers目录下。
【问题2】
重新输入 python3 train.py 后,报如下问题,由此可见,设置train.py中的参数的时候,'–weights’参数不可以被注释掉。
AttributeError: 'Namespace' object has no attribute 'weights'
故将’weights’参数设置如下,表示不使用预训练权重,模型将从头开始训练。
'--weights', default=''
【问题3】
不知道为什么,ubuntu上又报了一个numpy的问题如下,本地运行是没有这个问题的
raise AttributeError(__former_attrs__[attr])
AttributeError: module 'numpy' has no attribute 'int'.
原来是因为 新版本的numpy里面没有np.int,可以修改源码解决。
修改yolov5prune_6.0/utils/ 目录下datasets.py中所有的…astype(np.int) 为 …astype(int),如下所示:
441 bi = np.floor(np.arange(n) / batch_size).astype(int) # batch index
483 self.batch_shapes = np.ceil(np.array(shapes) * img_size / stride + pad).astype(int) * stride
854 b = xywh2xyxy(b.reshape(-1, 4)).ravel().astype(int)
修改yolov5prune_6.0/utils/ 目录下general.py中所有的…astype(np.int) 为 …astype(int),如下所示:
510 classes = labels[:, 0].astype(int) # labels = [class xywh]
525 class_counts = np.array([np.bincount(x[:, 0].astype(int), minlength=nc) for x in labels])
【问题4】
File "/home/user/hlj/MyTrain/yolov5prune_6.0/utils/loss.py", line 217, in build_targets
indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1)))
RuntimeError: result type Float can't be cast to the desired output type long int
参考 ref: https://blog.csdn.net/Thebest_jack/article/details/125649451 执行如下操作:
修改yolov5prune_6.0/utils/ 目录下loss.py源码,
#(1) 183行左右
for i in range(self.nl):anchors, shape = self.anchors[i], p[i].shape # anchors = self.anchors[i]gain[2:6] = torch.tensor(p[i].shape)[[3, 2, 3, 2]] # xyxy gain
#(2)218行后
# indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1)))
上一行代码改为如下
indices.append((b, a, gj.clamp_(0, shape[2] - 1), gi.clamp_(0, shape[3] - 1))) # image, anchor, grid indices
【问题5】
epoch的时候,报如下问题
File "..../yolov5prune_6.0/utils/plots.py", line 116, in text
w, h = self.font.getsize(text) # text width, height
AttributeError: 'FreeTypeFont' object has no attribute 'getsize'
这是因为安装了新版本的 Pillow,pip install tf-models-official删除了该getsize功能
,降级到 Pillow 9.5 解决了该问题。可以尝试以下方法进行解决,参见【问题8】:
pip install Pillow==9.5
【问题6】
epoch 0 结束,val结束后,报如下问题
File ".....\yolov5prune_6.0\utils\callbacks.py", line 77, in runlogger['callback'](*args, **kwargs)
TypeError: on_fit_epoch_end() missing 1 required positional argument: 'fi'
找一下官方源码,把yolov5_6.0/utils/下的整个loggers文件复制进去,应该就行了,可能是版本不一致导致的。
【问题7】
yolov5prune_6.0/utils/general.py line471
return re.sub(pattern="[|@#!?·$€%&()=??^*;:,¨′><+]", repl="_", string=s)
SyntaxError:(unicoda error)'utf-8' code can't decode byte 0xal in position 6: invalid start byte。
应该是’utf-8’ code不支持的问题,添加了下面的编码格式,但最后也没解决。看了一下对应函数的功能,只是为了清理字符串(用下划线替代特殊字符),所以就直接改了那一行的代码,对整个程序是没有影响的。
# -*- coding: utf-8 -*-
【总结】
虽然各种问题不断,而且【问题5】我也没管它 但是,最后总算是python3 train.py正常跑起来了。
4.4 稀疏化训练
4.4.1 参数设置
对train_sparity.py的参数进行设置
'--st', action='store_true',default=True,
'--sr', type=float, default=0.0001,
'--weights', type=str, default=ROOT / '',
'--cfg', type=str, default='./models/yolov5s.yaml',
'--data', type=str, default='./data/my_yolov5.yaml',
'--epochs', type=int, default=300
'--batch-size', type=int, default=-1, # 注意【问题8】的发生
'--imgsz', '--img', '--img-size', type=int, default=640,
'--adam', action='store_true', default=True,
4.4.2 稀疏化训练与问题
执行如下命令,进行稀疏化训练
python train_sparity.py
【问题8】
loggers.on_params_update({"batch_size": batch_size})
AttributeError: 'Loggers' object has no attribute 'on_params_update'
貌似是autobatch的原因,所以把参数’–batch-size’, type=int, default=-1, 先改为固定值 default=2,此后,可以正常epoch0。但是仍然存在【问题5】的问题,虽然不影响训练,但是觉的还是应该把它解决,毕竟是AttributeError的问题。解决办法如下:
# pillow版本太新的原因,新版的getsize属性被删除掉了。
pip3 uninstall pillow
pip3 nstall pillow==9.5
【问题9】
Epoch0的val结束之后,报了如下问题
File "/home/user/hlj/MyTrain/yolov5prune_6.0/utils/callbacks.py", line 77, in run
logger['callback'](*args, **kwargs)
TypeError: Loggers.on_fit_epoch_end() takes 5 positional arguments but 6 were given
这个问题是由于自己为了解决【问题6】,把项目中的utils/loggers/init .py文件换成了官方的文件了,发现init.py文件中def on_fit_epoch_end(self, vals, bn_weights, epoch, best_fitness, fi)少bn_weights,在这个项目中把prune项目下这个文件重新拷贝一下好了。
4.5 剪枝
4.5.1 参数设置
设置裁剪比例参数,可以从小到大试。注意cfg的模型文件需要和weights对应上,否则会出现运行prune 过程中出现键值不对应的问题,裁剪完成会保存对应的模型pruned_model.pt。
在prune.py文件中,修改如下参数
'--data', type=str, default=ROOT / 'data/my_yolov5.yaml',
'--weights', nargs='+', type=str, default=ROOT / 'runs/train/spaweight/last.pt'
'--cfg', type=str, default='./models/yolov5s.yaml',
'--percent', type=float, default=0.1,
'--batch-size', type=int, default=16,
'--imgsz', '--img', '--img-size', type=int, default=640,
运行
python prune.py
【问题10】
SyntaxError: Non-UTF-8 code starting with '\xe5' in file /home/user/hlj/MyTrain/yolov5prune_6.0/prune.py on line 400, but no encoding declared; see https://peps.python.org/pep-0263/ for details
解决方法:找到对应的行,发现是注释的内容code的格式的问题,把它删掉或者把中文改成英文即可。
【问题11】
return func(*args, **kwargs)
TypeError: run() got an unexpected keyword argument 'cfg'
解决方式在prune.py的源码run()函数中,增加参数如下
cfg = './model/yolov5s.yaml'
4.5.2 剪枝
对稀疏化训练后的模型best.pt进行剪枝。
若参数已设置好了,直接执行python prune.py
python prune.py
否则,传入的weight为稀疏化训练得到的权重。
python prune.py --weights runs/train/exp_sparity/weights/best.pt --percent 0.5 --cfg models/yolov5s.yaml
裁剪完成会在根目录下保存对应的模型pruned_model.pt。
4.6 finetune剪枝的网络
4.6.1 参数设置
更改finetune_pruned.py的相关参数如下
'--weights', type=str, default=ROOT / 'pruned_model.pt',
'--cfg', type=str, default='./models/yolov5s.yaml',
'--data', type=str, default=ROOT / 'data/my_yolov5.yaml',
'--epochs', type=int, default=100
'--batch-size', type=int, default=16,
'--imgsz', '--img', '--img-size', type=int, default=640,
'--adam', action='store_true', default=True,
'--workers', type=int, default=8,
'--project', default=ROOT / 'runs/finetune',
4.6.2 finetune
若没有修改finetune_pruned.py中的参数,如下执行。
python finetune_pruned.py --weights pruned_model.pt --adam --epochs 100
由于直接修改了finetune_pruned.py中的参数,直接执行
python finetune_pruned.py
执行时,报了【问题9】,按照相关解决方法可fine_tune正常开始。
4.7 循环稀疏训练->剪枝->finetune网络
相关文章:

从0开始做yolov5模型剪枝
文章目录 从0开始做yolov5模型剪枝 ****1 前言2 GitHub取源码3 原理3.1 原理3.2 network slimming过程 4 具体实施步骤4.1 安装虚拟环境4.2 配置参数4.2.1 数据集参数4.2.2 模型结构参数4.2.3 train.py中的参数 4.3 正常训练4.3.1 准备4.3.2 训练及问题解决 4.4 稀疏化训练4.4.…...

飞天使-k8s基础组件分析-安全
文章目录 名称空间解释访问kubernetes API的控制RBAC的介绍 kubeconfig用户的创建集群默认角色 给组创建授权针对pod配置服务账户参考文档 名称空间解释 名字是啥? 答:集群中每个对象的名称对于该类型的资源都是唯一的。并且每一个对象在整个集群中也有…...

Mysql安装使用
Mysql下载: MySQL :: Download MySQL Community Server Mysql解压: 解压后在根目录新建data文件夹和新建my.ini文件 my.ini文件内容如下: 注意:记得修改目录位置 [mysqld] # 设置3306端口 port3306 # 设置mysql的安装目录 basedirD:\\mysql-5.7.30…...

聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化
聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化 目录 聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化,聚类结果可视化,MATLAB程…...
uniapp 使用 mui-player 插件播放 m3u8/flv 视频流
在UniApp中使用mui-player插件播放M3U8/FLV视频流,可以按照以下步骤进行操作: 1. 安装mui-player插件 :在UniApp项目根目录下,使用命令行工具执行以下命令安装mui-player插件: npm install mui-player --save2. 在需…...

大数据课程K4——Spark的DAGRDD依赖关系
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Spark的DAG; ⚪ 掌握Spark的RDD的依赖关系; ⚪ 了解Spark对于DAG的Stage的划分; 一、DAG概念 1. 概述 Spark会根据用户提交的计算逻辑中的RDD的转换和动作来生成RDD之间的依赖关…...
disable 禁用元素后无法触发点击事件
业务需求点击被禁用的输入框触发事件 在被禁用元素上套一层div div上绑定事件 原本是不需要加事件穿透即可触发 但是最近谷歌更新触发不了 加一个事件穿透就好了 核心代码 style"pointer-events:none"style“pointer-events:none” 事件穿透 整体代码 <el-table-…...
uni-app开启gzip配置
指令:npm install webpack4.46.0 --save-dev 指令:npm install compression-webpack-plugin6.1.1 --save-dev vue.config.js const CompressionWebpackPlugin require(compression-webpack-plugin);module.exports {configureWebpack: config > {…...

房屋结构健康监测,科技助力让建筑更安全
房屋建筑是人们赖以生存的场所,然而当前我国许多房屋已经达到了使用寿命的中期,房屋的安全系数逐年降低,风险也随着时间的推移而累积。长期以来,我国的房屋普遍存在寿命短、隐患多的问题,“重建设,轻管理”…...

Android 面试之Glide做了哪些优化?
前言 Glide可以说是最常用的图片加载框架了,Glide链式调用使用方便,性能上也可以满足大多数场景的使用,Glide源码与原理也是面试中的常客。 但是Glide的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点.…...

【韩顺平 零基础30天学会Java】数组、排序和查找(2days)
数组、排序、查找和多维数组 数组可以存放多个同一类型的数据。数组也是一种数据类 型,是引用数据类型。 定义一个数组 double[] hens {3,5,1,3.4,2,50} 遍历数组得到数组所有元素的和 hens[下标],下标是从0开始编号的。 可以通过数组名.lenght得到数组…...

VUE笔记(一)初识vue
一、vue的简介 1、什么是vue 官网地址:Vue.js Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。 构建用户界面:之前在学习vue之前通过原生js对DOM操作进行构建用户界面的 使用原生js构建用户界面的不足 - 没有规范,…...
3D点云处理:学习总结(更新整理中)
文章目录 开发工具个人看法 微信:dhlddx B站演示视频 前置说明:仅是个人在使用pcl开发过程中的总结(点云处理顺序或比较实用的功能),不喜勿喷; 开发工具 开发IDE:Qt Creator(Windo…...

Day45|leetcode 70. 爬楼梯、322. 零钱兑换、279.完全平方数
leetcode 70. 爬楼梯 题目链接:70. 爬楼梯 - 力扣(LeetCode) 本题可以用背包问题来解决,就相当于楼顶是背包,台阶是物品,相当于之前写法的进阶版。 代码实现 class Solution { public:int climbStairs(in…...

arm:day9
1。思维导图 2..I2C实验,检测温度和湿度 iic.h #ifndef __IIC_H__ #define __IIC_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" #include "gpio.h" /* 通过程序模拟实现I2C总线的时序和协议* GPIOF ---> AHB4…...
【大模型AIGC系列课程 1-2】创建并部署自己的ChatGPT机器人
OpenAI API 调用 获取 openai api api-key https://platform.openai.com/account/api-keys 利用 python requests 请求 openai 参考 openai 接口说明:https://platform.openai.com/docs/api-reference/chat/create import json # 导入json包 import requests # 导入req…...

启动metastore服务报错
启动Metastore的时候报错: 简略的报错信息: MetaException(message:Error creating transactional connection factory)Caused by: MetaException(message:Error creating transactional connection factory)Caused by: javax.jdo.JDOFatalInternalExce…...
c 语言 算法 技巧 之 用移位来代替乘除
除法 当你需要计算一个数的一半时,通常我们会考虑使用除法运算(/)来实现。然而,计算机内部的运算中,除法通常比加法和乘法运算慢得多,因为除法需要更多的处理步骤。 位运算在这种情况下可以提供一个快速的…...

python爬虫实战零基础(3)——某云音乐
爬取某些云网页音乐,无需app 分析网页第二种方式批量爬取 声明:仅供参考学习,参考,若有不足,欢迎指正 你是不是遇到过这种情况,在pc端上音乐无法下载,必须下载客户端才能下载? 那么&…...

渗透测试漏洞原理之---【XSS 跨站脚本攻击】
文章目录 1、跨站 脚本攻击1.1、漏洞描述1.2、漏洞原理1.3、漏洞危害1.4、漏洞验证1.5、漏洞分类1.5.1、反射性XSS1.5.2、存储型XSS1.5.3、DOM型XSS 2、XSS攻防2.1、XSS构造2.1.1、利用<>2.1.2、JavaScript伪协议2.1.3、时间响应 2.2、XSS变形方式2.2.1、大小写转换2.2.2…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...