tensorRT从零起步高性能部署:课程总结

news2024/11/26 20:32:25

目录

    • 前言
    • 1. cuda驱动API
    • 2. cuda运行时API
    • 3. tensorRT基础
    • 4. tensorRT高级
    • 5. tensorRT封装
    • 6. 自动驾驶案例项目
    • 总结

前言

杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记。

本次课程主要是课程总结,对之前学习的知识的一个复习

课程大纲可看下面的思维导图

在这里插入图片描述

1. cuda驱动API

这个章节我们主要了解了 CUDA Driver API 这个与 GPU 沟通的驱动级底层 API,在 Driver API 中我们主要学习了 CUDA 系列接口的开发习惯、Context 的管理机制和内存模型

我们在调用 CUDA Driver API 时都会去对 API 返回值的结果进行一个检查,这样做的目的当然是便于我们发现错误,方便调试,具体实现我们是通过函数封装+宏的方式提供一个统一的接口,并根据返回值判断 API 执行是否成功,从而进行相应的处理。以后的诸如 Runtime API、Kernel 核函数都是这样做的,为各种 CUDA API 函数添加 check 功能,方便定位错误信息,有利于后续开发。

接着我们了解了 context,它是一种上下文,可以关联对 GPU 的所有操作。使用 context 的目的是可以将一系列相关的 CUDA 操作关联到一个 context 中,而不用每次在执行诸如 cuMalloccuMemcpy 时都需要显式的制定设备标识符 device。此外,关于上下文的创建更推荐使用 cuDevicePrimaryCtxRetain,它不需要显式地管理上下文栈,代码更简洁。

最后我们简单地学习了 device memory、page-locked memory 的内存分配,分别使用的是 cuMemAlloccuMemAllocHost

2. cuda运行时API

这个章节我们主要学习了 CUDA Runtime API,它是封装了 CUDA Driver 的高级别更友好的 API,在 Runtime API 中主要的知识点有内存模型、流的使用、线程束布局、核函数的使用

Runtime API 使用时,当调用需要 context 的 API 时,它会自动创建管理 context 无需我们手动操作管理,此外,在 Runtime API 中我们也需要添加 check 功能,方便我们调试和排查问题。


接着我们学习了内存模型,主要了解 pinned memory(Host Memory)、global memory(Device Memory)以及 shared memory(Device Memory)

Host Memory 物理上对应的是内存条内存,它分为 pageable memory 和 page lock memory/pinned memory(逻辑上区别,物理上指同一个东西),对应到代码中,由 new、malloc 分配的是 pageable memory,而由 cudaMallocHost 分配的是 pinned memory

Device Memory 物理上对应的是显存,它拥有片上内存(shared memory)和片外内存(global memory),对应到代码中,由 cudaMalloc 分配的是 global memory,而 shared memory 则常用于同一个线程块内的线程之间共享数据,我们在启动 Kernel 核函数时需要指定共享内存 shared memory 的大小

GPU 可以直接访问 pinned memory,其轨迹主要是通过 PCIE 接口到主板再到内存条,称之为 DMA(Direct Memory Access)技术,而 GPU 要访问 pageable memory 中的数据必须通过 pinned memeory。

对于 GPU 访问而言,距离计算单元越近,效率越高,即 pageable memory<pinned memory<global memory<shared memory,由此我们得出一个结论:尽量多用 pinned memory 储存 host 数据或者显式处理 Host 到 Device 时用 pinned memory 做缓存都是提高性能的关键


随后我们学习了流(stram),stream 是 CUDA 中用于异步控制的主要方式,例如在进行内存拷贝时我们经常使用 cudaMemcpyAsync 异步复制的方式,并把 stream 作为参数填入,最后使用 cudaStreamSynchronize 同步流,确保异步复制操作全部完成。通过使用 stream,可以将数据传输和内存操作与主线程的计算异步进行,从而提高并行性和性能。

然后我们学习了 CUDA 编程中的关键部分 —— 核函数,我们通过 xxx.cu 创建一个 cudac 程序文件后,要把 .cu 文件交给 nvcc 编译才能识别 cuda 语法,而 nvcc 是 nvidia 的一个 c++ 编译器,专门用来编译 cudac 程序的。

cu 文件一般是用来写 CUDA 核函数的,可以把它当作正常 cpp 写即可,它是 cpp 的超级,兼容支持 cpp 的所有特性,只是在 cu 文件中引入了一些新的符号和语法。

在 CUDA 编程中有一些特殊标识符需要我们注意:

  • __global__:表示核函数,由 host 调用
  • __device__:表示设备函数,由 device 调用
  • __host__:表示主机函数,由 host 调用

核函数的调用语法如下:

function<<<gridDim,blockDim,sharedMemorySize,stream>>>(args…)
  • function:要执行的核函数的名称
  • <<<…>>>:这是启动和函数执行的语法接口,有三个 < 和 > 组成
  • gridDim:表示要启动的 grid 的维度,一个 grid 由多个 block 组成。gridDim 定义了每个维度上的 block 数目。例如,如果 grid 的维度是 dim3(4, 4, 1) 则表示启动了一个 4x4 的 2-dim grid
  • blockDim:表示要启动的 block 的线程块维度。一个 block 由多个 thread 组成,blockDim 定义了每个维度上的 thread 数目。例如,如果 block 的维度是 dim3(32, 32, 1),则表示每个 block 中有 32x32 个线程
  • sharedMemorySize:可选参数,表示 block 中共享内存 shared memory 的大小
  • stream:可选参数,CUDA 流用于异步控制
  • args…:核函数的实际参数

核函数在执行时实际上会启动很多线程,这些线程在逻辑上是并行的,但是在物理层不一定。GPU 硬件的一个核心组件就是流式多处理器(streaming Multi-processor,SM),当一个 Kernel 核函数被执行时,它的 grid 中的线程块就被分配到 SM 上。值得注意的是一个线程块只能在一个 SM 上被调度,而一个 SM 一般可以调度多个线程块,这要看 SM 本身的能力。一个 Kernel 的各个线程块被分配到多个 SM 中去执行,因此我们说 grid 只是逻辑层,而 SM 才是执行的物理层

SM 的基本执行单元是线程束(warps),线程束包含 32 个线程,一个 SM 同时并发的线程束数也是有限的。由于 SM 的基本执行单元是包含 32 个线程的线程束,因此 block 大小一般设置为 32 的倍数,如 256、512、1024

总之就是网格(grid)和线程块(block)只是逻辑划分,一个 Kernel 的所有线程其实在物理层不一定同时并发的。所以 Kernel 的 grid 和 block 的配置不同,性能会出现差异。


接着我们学习了共享内存的使用,shared memory 可以在同一个 block 中的线程之间共享数据,它通常与 __syncthreads 同时出现,为了同步 block 中的所有线程。

在 CUDA 编程中,共享内存可以通过两种方式进行定义:静态共享内存和动态共享内存。静态共享内存定义使用 __shared__ 关键字,动态共享内存定义使用 extern __shared__ 关键字,静态共享变量定义几个地址随之叠加,而动态共享变量无论定义多少个地址都一样。定义的共享变量并不能给初始值,必须由线程或者其它方式赋值。

接下来我们学习了 warpAffine 并实现了 CUDA 核函数来进行加速,warpAffine 是对图像做平移缩放旋转变换进行综合统一描述的方法,在深度学习领域通常需要对图像做预处理,比如缩放,颜色通道转换,减均值除以标准差,通过 CUDA 对 warpAffine 进行并行加速实现可以对整个预处理进行统一。因为我们在核函数中是对每个像素进行操作,因此可以非常轻易的实现诸如 BGR->RGB、减均值除标准差等操作,此外通过 warpAffine 和双线性插值可以实现图像的缩放,并通过仿射变换的逆矩阵可以用于后处理中的 decode 解码操作

然后我们也学习了 CUDA 核函数来加速后处理,我们以 YOLOv5 检测模型的后处理为例,我们先在 CPU 上实现 decode 和 nms,一些关键的性能优化点如下:

  • 预测框过滤:在 decode 过程中先利用置信度阈值过滤,避免不必要的后续计算和处理
  • 预测框排序:在 lambda 函数中传引用,同时对 box_result 利用 reserve 进行预分配提升性能
  • 使用标志位:在 nms 过程中,使用 remove_flags 标志位来标记需要移除的预测框,相比于两两预测框比较提高了效率

杜老师提供的 CPU 版本的后处理性能已经非常好了,我们根据 cpu_decode 以及 cpu_nms 在 GPU 上也完成了同样的操作

最后我们简单了解了下 CUDA 编程中的错误处理以及错误的传播特性

3. tensorRT基础

这个章节我们主要学习了 tensorRT 的一些基础知识,在 tensorRT 基础篇中主要的知识点有模型结构定义方式、编译过程配置、推理过程实现、插件实现、onnx 理解

我们首先学习了利用 tensorRT 的 C++ API 构建了一个简单的神经网络模型,大致流程可以分为以下四个部分:

  • 1. 定义 builder、config 和 network
  • 2. 构建网络所需输入、模型结构和输出的基本信息
  • 3. 生成 engine 模型文件
  • 4. 序列化模型文件并存储

接下来我们使用了 C++ API 进行了推理,大致流程如下:

  • 1. 准备模型并加载
  • 2. 创建 runtime 反序列化模型创建 engine
  • 3. 创建 context 和 CUDA stream
  • 4. 准备数据执行推理
  • 5. 释放内存

在完成了利用 tensorRT 的 C++ API 进行模型构建和推理后,我们学习了动态 shape 模型的构建和推理。在构建网络时,对于输入维度需要给定 -1,否则该维度不会动态,此外还需要设置 profile 对象,确定 kMin、kOPT 以及 kMAX 等。在推理阶段,动态 shape 模型只需要在每次推理前设置输入数据的 shape 即可,而大多时候我们只关心 batch 维度的动态,而对宽、高动态并不关心


接着我们学习了 onnx 文件的导出、读取、创建和编辑。onnx 是 Microsoft 开发的一种中间格式的模型,它的本质是一种 protobuf 格式的文件。我们需要理解 onnx 模型结构的储存、权重的储存、常量的储存、netron 的解读对应到代码,学习 onnx 的各种操作有利于我们后续 tensorRT 的部署工作

随后我们学习了导出 onnx 时的一些注意事项,确保导出的 onnx 在生成 engine 的时候问题尽可能的少。我们还学习了 libonnxparser.so 和源代码两种不同的方式来解析 onnx 模型,使用源代码的目的是为了更好的进行自定义封装,简化插件开发或者模型编译的过程,更加具有定制化,遇到问题也可以调试。

在学习完利用 onnxparser 构建网络模型后,我们还学习了 tensorRT 中插件的实现并对其进行了封装。最后我们学习了模型的 INT8 量化,我们以分类模型 resnet18 为例演示了 PTQ 隐式量化,

4. tensorRT高级

这个章节我们以实际项目为例,演示了 tensorRT 的综合运用,在 tensorRT 高级篇中主要的案例有分类器案例、Yolov5检测案例、Unet场景分割案例、Alphapose关键点检测案例、mmdetection案例、onnxruntime案例

首先我们学习了 resnet18 分类器案例,在这个案例中我们学习使用了 shared_ptr 对 tensorrt 对象的返回值进行了封装,防止内存的泄露。同时我们在 CPU 上也实现了一个高性能的预处理方法,直接对像素进行操作,将颜色通道转换、减均值除标准差一并做了。

接着我们学习了 yolov5 检测器案例,在这里我们重点学习了 yolov5 中 onnx 模型的导出,并详细分析了 yolov5 CPU 版本的预处理和后处理。我们还学习了场景分割网络 Unet 的导出、编译到推理,分割网络和检测网络略有不同,模型的预测可以看作对每个像素点进行分类

随后我们学习了 alphapose 姿态点估计案例,在这里我们体会了要将复杂的后处理放到 onnx,同时学习了如何从拉取一个官方代码到导出我们想要的 onnx,我们在理解完别人的代码后一定要自己实现一个版本,这样才能更好的去消化吸收变成我们自己的知识。

然后我们学习了调试分析 mmdet 代码,把 yolox 模型导出并在 tensorrt 上推理得到了结果。由于 mmdetection 封装得太死,导出 onnx 非常费劲,但是习惯后问题总是可以解决得,不至于束手无策。无论遇到多么复杂的框架、代码,我们首先需要对模型有一定了解,同时具备一定的代码功底,能完成解读、按照自己的理解重写,这样将大大锻炼动手能力。

接下来我们学习了使用不同的推理框架完成部署工作,包括 onnxruntime、openvino 等,这些框架其实大差不差,无非是准备数据塞到框架中,拿到推理后的解决进行后处理,我们能把握的其实就是数据的预处理和后处理部分,至于中间的推理部分我们其实是没办法控制的,因此为了实现高性能,我们就要想办法把数据的预处理和后处理部分尽可能的高效处理,这才是我们需要学习的核心。


在学习完了一系列的案例之后,我们了解了深度学习中涉及的线程知识,目的是方便后面我们的封装工作。

深度学习中的线程知识主要包括 thread、mutex、condition_varaiable、lock、promise、future

mutex 互斥锁的存在主要是为了解决共享资源访问问题,当线程不是安全的时候,需要对其资源访问加上锁

condition_variabel 条件变量的存在主要是解决在生产者消费者模式中消费者如何通知生产者以及生产者如何去等待消费者,分别使用的是 cv_.wait 和 cv_notify_one 方法,它们被用来同步生产者和消费者,以确保队列的大小不超过给定的限制。当生产者试图添加到队列时,如果队列已满,它会等待直到消费者从队列中取出一张图片。

promise、future 用于在线程间传递数据,消费者通过 promise.set 方法设置值,而生产者则可以通过 future.get 方法可以拿到消费者的反馈。这种方式在线程间传递数据非常有效,因为它允许生产者线程异步地等待消费者线程处理的结果,而不必使用复杂的同步机制。而且,由于 promise 和 future 之间的紧密关系,这种方法也是线程安全的。

在学习线程知识的过程中我们还了解了一种设计模式,即生产者-消费者设计模式,它在深度学习模型推理中非常常见,生产者线程负责不断生成新的图片任务,将其放入队列中,而消费者线程则负责从队列中获取图片任务并进行处理。通过这种方式,使得图片采集和模型推理过程可以并行进行,提高了系统的吞吐量和效率。

5. tensorRT封装

这个章节我们主要是学习对 tensorRT 的逐步封装,在 tensorRT 封装篇主要的封装有代码的封装、内存分配的封装、tensor 的封装、build 的封装,infer 的封装

首先我们学习了使用 RAII + 接口模式对代码进行了有效的封装,RAII 将资源在构造函数中就进行初始化,避免了外部获取资源后还要调用相关函数去做初始化,接口模式则将接口纯虚类与具体实现类分离开,让使用者只考虑具体的接口,而不必关心具体的实现。这种封装方式为代码提供了更大的灵活性和可维护性,十分推荐使用

然后我们学习了 tensorRT 中的 build 的封装,重点是 compile 函数的实现;我们还学习了 memory 的封装,使得内存分配复制自动管理,避免手动管理的繁琐,主要是通过 MixMemory 实现的内存的分配和释放以及内存的复用,其中复用思想在于申请分配的内存大于之前已经分配的内存才去释放并重新分配,否则直接返回之前已经分配好的内存,这样可以避免频繁的内存分配和释放操作,从而提高性能。

接着我们学习了 tensor 的封装,对 tensor 的封装重点考虑了四个方面:内存的管理、内存的复用、内存的拷贝以及索引的计算,其中前面两个可以用 MixMemory 来解决,内存的拷贝通过定义内存的状态,懒分配原则实现的,而索引的计算则是通过左乘右加原则完成的。tensor 的封装使得输入和输出的操作更加的便捷,索引的计算也更加的方便。随后我们还学习了 infer 的封装,通过一个 commit 函数即可完成整个推理过程。

在完成上述各个部件的封装后,我们使用这些封装好的组件,配合生产者和消费者模式实现了一个完整的 yolov5 推理,并对其进行了优化完善。最后我们探讨了模型的调试技巧,要学会善于使用 python 工作流,联合 python/cpp 一起进行问题调试。

6. 自动驾驶案例项目

这个章节我们主要是学习自动驾驶案例的各个项目,包括道路分割、深度估计、车道线检测

我们学习了自动驾驶场景中的模型案例,对不同的任务进行了了解。

道路分割案例是将道路分割成可行驶区域、车道线、不可行驶区域等,深度估计是从图像中获取车辆与目标的深度信息,而车道线检测是利用位置概率来对点进行回归

最后我们学习了使用 pybind11 为 python 写 c++ 的扩展模块,利用 c++ 的计算性能和 python 的便利性有利于我们平时的开发。

总结

这次重撸视频前前后后花了将近两个月的时间,不容易吖😂,从最开始的 Driver API、Runtime API 到 tensorRT 的模型构建推理,再到各个实际场景应用案例,再到各个模块的封装,最后到自动驾驶项目,一路走来,收获颇丰。感谢杜老师,也感谢一路坚持的自己😄

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

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

相关文章

1、Flutter移动端App实战教程【环境配置】

一、概述 Flutter是Google用以帮助开发者在IOS和Android 两个平台开发高质量原生UI的移动SDK&#xff0c;一份代码可以同时生成IOS和Android两个高性能、高保真的应用程序。 二、渲染机制 之所以说Flutter能够达到可以媲美甚至超越原生的体验&#xff0c;主要在于其拥有高性…

自然语言处理:提取长文本进行文本主要内容(文本意思)概括 (两种方法,但效果都一般)

本文主要针对长文本进行文本提取和中心思想概括&#xff0c;原文档放在了附件里面&#xff1a;<科大讯飞公告> -----------------------------------方法一&#xff1a;jieba分词提取文本&#xff08;句子赋分法&#xff09;------------------------- 1、首先导入相关…

docker笔记7:Docker微服务实战

1.通过IDEA新建一个普通微服务模块 建Module docker_boot 改POM <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

【聚类】K-Means聚类

cluster&#xff1a;簇 原理&#xff1a; 这边暂时没有时间具体介绍kmeans聚类的原理。简单来说&#xff0c;就是首先初始化k个簇心&#xff1b;然后计算所有点到簇心的欧式距离&#xff0c;对一个点来说&#xff0c;距离最短就属于那个簇&#xff1b;然后更新不同簇的簇心&a…

nginx中模块的设置以及反向代理

nginx设置 nginx http 模块的配置文件位于 "/apps/nginx/conf/nginx.conf"&#xff08;以自己安装时选择的目录为准&#xff0c;若使用yum安装&#xff0c;则在 /etc/nginx/nginx.conf&#xff09;。在该文件中&#xff0c;需要定义一些常见的配置项&#xff0c;包括…

《Communicative Agents for Software Development》全文翻译

《Communicative Agents for Software Development》- 沟通性智能主体促进软件开发 论文信息Abstract1. Introduction2. CHATDEV2.1 聊天链2.2 设计2.3 编码2.4 测试2.5 记录 3. 实验4. 讨论5. 相关工作6. 结论 论文信息 题目&#xff1a;《Communicative Agents for Software…

TienChin 渠道管理-查看渠道接口

自定义 hasPermission 校验规则 自定义一个 Spring Security hasPermission 校验规则&#xff1a; 在 tienchin-framework 模块当中进行自定义&#xff0c;新建 CustomSecurityExpressionRoot.java 自定义 hasPermission 判断逻辑类&#xff1a; /*** author BNTang* version 1…

SSM框架-Spring框架核心知识梳理

目录 一、SpringIoC 1.1认识SpringIoC容器 1.2基于xml配置SpringIoC容器 1.3基于xml配置下Bean的生命周期和作用域 1.4 基于xml与注解配置SpringIoC容器 1.5 基于完全注解类配置SpringIoc容器 二、SpringAop面对切面编程 2.1认识SpringAop面向切面编程 2.2SpringAop基…

list【2】模拟实现(含迭代器实现超详解哦)

模拟实现list 引言&#xff08;实现概述&#xff09;list迭代器实现默认成员函数operator* 与 operator->operator 与 operator--operator 与 operator!迭代器实现概览 list主要接口实现默认成员函数构造函数析构函数赋值重载 迭代器容量元素访问数据修改inserterasepush_ba…

数学建模--二维插值函数模型的Python实现

目录 1.算法实现步骤 2.算法核心代码 3.算法效果展示 1.算法实现步骤 #二维插值函数的展示通过Axes3D函数来进行实现 #我们需要绘制出20*20的插值效果和500*500的插值效果,进行比较. 具体步骤如下所示: 1.将x-y分为20*20并且绘制网格图 2.进行20*20的插值计算并且绘制可视化图…

使用SimPowerSystems并网光伏阵列研究(Simulink实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

9.4.tensorRT高级(4)封装系列-使用pybind11为python开发扩展模块

目录 前言1. pybind112. 补充知识2.1 pybind11 介绍 总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-使用p…

《网络是怎样连接的》(六)

本文主要取材于 《网络是怎样连接的》 第六章。 目录 6.1 服务器概览 6.2 服务器的接收操作 6.3 Web服务器程序解释请求消息并作出响应 6.4 浏览器接收响应消息并显示内容 简述&#xff1a;本文主要内容是解释 网络包到达服务器之后&#xff0c;如何给客户端响应的。 服务…

电商实战项目(java)知识点整理(持续更新)《苍穹外卖》

一、重要知识点精讲 1.1 nginx反向代理 1. nginx反向代理好处&#xff1a; 1. 提高访问速度&#xff08;可以进行缓存&#xff0c;如果访问相同资源可以直接响应数据&#xff09; 2. 可以进行负载均衡&#xff08;如果没有nginx前端只能固定地访问后端某一台服务器&#xf…

Linux系统编程—socket网络编程

Linux系统编程—socket网络编程 理论概念1. TCP与UDP对比端口号作用 socket开发过程服务端1. socket 创建套接字2. bind 绑定IP端口3. listen 监听客户端4. accept 接收客户端5. read / write 数据传输 客户端1. socket 创建套接字2. connect 连接服务3. read / write 数据传输…

合宙Air724UG LuatOS-Air LVGL API控件--下拉框 (Dropdown)

下拉框 (Dropdown) 在显示选项过多时&#xff0c;可以通过下拉框收起多余选项。只为用户展示列表中的一项。 示例代码 -- 回调函数 event_handler function(obj, event)if (event lvgl.EVENT_VALUE_CHANGED) thenprint("Option:", lvgl.dropdown_get_symbol(obj)…

稀疏数组的实现

文章目录 目录 文章目录 前言 一 什么是稀疏数组? 二 稀疏数组怎么存储数据? 三 稀疏数组的实现 总结 前言 大家好,好久不见了,这篇博客是数据结构的第一篇文章,望大家多多支持! 一 什么是稀疏数组? 稀疏数组&#xff08;Sparse Array&#xff09;是一种数据结构&a…

Elastic-job分布式调度系统

一、定时任务实现方式 1、Thread方式 final int timeInterval 1000;Thread thread new Thread(new Runnable() {Overridepublic void run() {while (true){try {//每一秒执行一次Thread.sleep(timeInterval);System.out.println("run...");} catch (InterruptedE…

数据结构和算法(1):开始

算法概述 所谓算法&#xff0c;即特定计算模型下&#xff0c;旨在解决特定问题的指令序列 输入 待处理的信息&#xff08;问题&#xff09; 输出 经处理的信息&#xff08;答案&#xff09; 正确性 的确可以解决指定的问题 确定性 任一算法都可以描述为一个由基本操作组成的序…

SpringBoot核心原理与实践

第一章、SpringBoot简介 1、入门案例 2、官网创建压缩包程序 注意使用的版本pom文件中java --> 1.8、 springboot --> 2.5.0 3、SpringBoot快速启动 运行程序--找引导类 换技术、加技术--加starter 第二章、基础配置 1、配置文件格式 《1、端口号配置》 《2、将目录文…