KuiperInfer (自制深度学习推理框架)
我们在本项目的基础上开设了一个全新的课程,《从零自制大模型推理框架》,以下是目录,感兴趣的同学可以扫描二维码或者添加微信 lyrry1997 了解,欢迎大家参加。
《动手自制大模型推理框架》常见问题
- 课程更新完了吗?
主体已经更新完毕,完全可以开始自习。支持cuda,int8推理。
- 这是收费课程吗?怎么收费,怎么付款,过段时间买可以吗?
收费课程,256元,微信转账。可以,但是我的微信好友快满了,隔一段时间会清理,而且不定期会涨价。
- 为什么B站会贵一点,内容都一样吗?
B站要抽成,内容都一样。
- 怎么看课
飞书网盘,打开浏览器就可以看。
- 有答疑吗
有的,且有答疑群,群友也很热情。
- 不会C++可以学吗?
事在人为,我也尽量深入浅出教学。
- 课程目录有吗
见下文。
- 作者是干什么的?
主业就是开发大模型推理框架的,课件已经被人民邮电出版社约稿,同时也是kuiperinfer项目,也就是本项目的发起人,目前全GitHub C++项目排名120位。
《动手自制大模型推理框架》项目运行效果fp32模型1.1b参数。
KuipeInfer目前2.3k star,帮助很多人获得了大厂岗位。
《动手自制大模型推理框架》课程目录
一、项目整体架构和设计
学习架构思维,防止自己只会优化局部实现
- 环境的安装和课程简介
- 资源管理和内存管理类的设计与实现
- 张量类的设计与实现
- 算子类的设计与实现
- 算子的注册和管理
二、支持LLama2模型结构
本节将为大家补齐算法工程师思维,在算法层面讲解大模型和Transformer的原理之后,开始对LLama2进行支持
- LLama模型的分析
- MMap内存映射技术打开大模型的权重文件
- LLama模型文件的参数和权重载入
- LLama中各个层的初始化以及输入张量、权重张量的分配和申请
- 实现大模型中的KV Cache机制
三、模型的量化
为了减少显存的占用,我们开发了int8模型量化模块
- 量化模型权重的导出
- 量化系数和权重的加载
- 量化乘法算子的实现
四、Cuda基础和算子实现
带你学Cuda并在实战大模型算子的实现,为大模型推理赋能
- Cuda基础入门1 - 内容待定
- Cuda基础入门2 - 内容待定
- Cuda基础入门3 - 内容待定
- Cuda基础入门4 - 内容待定
- RMSNorm算子的Cuda实现
- Softmax算子的Cuda实现
- Add算子的Cuda实现
- Swiglu算子的Cuda实现
- GEMV算子的Cuda实现
- 多头注意力机制的Cuda实现
- 让框架增加Cuda设备的支持和管理
- 完成Cuda推理流程
五、用推理框架做点有趣的事情
- 文本生成
- 讲一段小故事
- 让大模型和你进行多轮对话
六、学习其他商用推理框架的实现,查漏补缺
- LLama.cpp的设计和实现讲解
- Miopen(AMD出品,对标CUDNN)的设计和实现讲解
- 总结
带领你亲手打造一个深度学习推理框架。关注我的B站空间,获取最新视频更新。 By following this project to build a deep learning inference framework from scratch, you will gain the following:
- Learn the knowledge behind a deep learning framework, master modern C++ project practices, debugging techniques, and engineering experience;
- How to design and write a computational graph;
- Implement common operators such as convolution, pooling, and fully connected operators;
- Based on step 3, learn common optimization techniques to accelerate operator execution;
- Finally, you will obtain your own inference framework capable of inferencing models like ResNet, UNet, YOLOv5, MobileNet, etc., which will be greatly beneficial for interviews and knowledge advancement.
Video course link: https://space.bilibili.com/1822828582
Support for LLaMA
We replaced the operators in llama.c with implementations from KuiperInfer
Model download link After downloading, replace it in demos/llama2/main.cpp
Second Course Outline
The second course is a reset version of the first course, with more comprehensive and improved content. The first course outline is in the section below.
Lesson Number | Progress | Course Link |
---|---|---|
Lecture 1 Project Preview and Environment Setup | Completed | https://www.bilibili.com/video/BV118411f7yM |
Lecture 2 Design and Implementation of Tensor | Completed | https://www.bilibili.com/video/BV1hN411k7q7 |
Lecture 3 Definition of Computational Graph | Completed | https://www.bilibili.com/video/BV1vc411M7Yp |
Lecture 4 Building Computational Graph Relationships and Execution Order | Completed | https://www.bilibili.com/video/BV19s4y1r7az |
Lecture 5 Operators and Registration Factory in KuiperInfer | Completed | https://www.bilibili.com/video/BV1gx4y1o7pj |
Lecture 6 Implementation of Convolution and Pooling Operators | Completed | https://www.bilibili.com/video/BV1hx4y197dS |
Lecture 7 Lexical and Syntactic Analysis in Expression Layer and Operator Implementation | Completed | https://www.bilibili.com/video/BV1j8411o7ao |
Lecture 8 Self-made Inference Framework Supporting ResNet Network Inference | Completed | https://www.bilibili.com/video/BV1o84y1o7ni |
Lecture 9 Self-made Inference Framework Supporting YOLOv5 Network Inference | Completed | https://www.bilibili.com/video/BV1Qk4y1A7XL |
Demo Effects
UNet Semantic Segmentation
🥰 KuiperInfer currently supports inference of UNet network, using pre-trained weights from Carvana
For inference reproduction, please refer to Running Kuiper's demo at the end of the document.
YOLOv5 Object Detection
The demo directly uses YOLOv5-s pre-trained weights (COCO dataset), using KuiperInfer for inference
First Course Outline
I have started a teaching course on Bilibili, currently covering the first 13 lessons. The course outline is as follows, and the homepage is: https://space.bilibili.com/1822828582. Welcome everyone to follow and support. The way to join the study group is through the QR code shown in the image above.
课程节数 | 主要内容 | 进度 | 课程链接 |
---|---|---|---|
第一课 | 整体框架解读和开发环境配置 | 完成 | https://www.bilibili.com/video/BV1HV4y1A7H8/ |
第二课 | 张量Tensor类的解析和输入数据的内存排布 | 完成 | https://www.bilibili.com/video/BV1Ed4y1v7Gb/ |
第三课 | 从CSV文件中初始化张量Tensor的一个实例 | 完成 | https://www.bilibili.com/video/BV1Pg411J7V5/ |
第四课 | 手写第一个算子Relu并完成算子注册工厂类 | 完成 | https://www.bilibili.com/video/BV1bG4y1J7sQ/ |
第五课 | Im2col的原理和卷积算子的实现 | 完成 | https://www.bilibili.com/video/BV1F841137Ct |
第六课 | 照葫芦画瓢,完成MaxPooling算子 | 完成 | https://www.bilibili.com/video/BV1m3411S7yy |
第七课 | 图结构(PNNX)讲解和计算图初步 | 完成 | https://www.bilibili.com/video/BV1VW4y1V7vp |
第八课 | 读取PNNX并构建自己的计算图 | 完成 | https://www.bilibili.com/video/BV1HY4y1Z7S3 |
第九课 | 卷积算子的实现和im2col加速计算的原理 | 完成 | https://www.bilibili.com/video/BV1F841137Ct |
第十课 | 再探Tensor类,构建计算图的图关系以及对算子的输入输出预分配 | 完成 | https://www.bilibili.com/video/BV1M54y1K7AG |
第十一课 | 算子的执行流程 | 完成 | https://www.bilibili.com/video/BV1wY411C7Kv |
第十二课 | 用我们自制的推理框架完成ResNet网络的推理和图片的分类 | 完成 | https://www.bilibili.com/video/BV1jD4y1M772 |
第十三课 | 用自制的推理框架支持Yolov5模型的推理 | 完成 | https://www.bilibili.com/video/BV1xs4y1J7t2 |
项目贡献
贡献者列表
感谢以下同学对Kuiperinfer的付出
- zjhellofss
- liuxubit
- Azusachan
- wfs2010
- mlmz
- Tigerrr07
- zyt1024
- zpye
- cmcamdy
- superCB
- sanbuphy
- TypeFloat
- Jasmine-up
- PerrySkywalker
- delve-wang
- z-learner
如何参与项目贡献?
- 提交代码增加新功能或修改bug;
- 提出特别有用的建议;
- 完善文档或增加单元测试。
本项目和视频课程的关系
-
本项目相当于课程的上游或者预研项目
-
这里的每一个功能都有可能成为视频课程中的知识点,无论是我开发的还是其他同学完善的。
使用的技术和开发环境
- 开发语言:C++ 17
- 数学库:Armadillo + OpenBlas(或者更快的Intel MKL)
- 加速库:OpenMP
- 单元测试:Google Test
- 性能测试:Google Benchmark
安装过程(使用Docker)
- docker pull registry.cn-hangzhou.aliyuncs.com/hellofss/kuiperinfer:latest
- sudo docker run -t -i registry.cn-hangzhou.aliyuncs.com/hellofss/kuiperinfer:latest /bin/bash
- cd code
- git clone --recursive https://github.com/zjhellofss/KuiperInfer.git
- cd KuiperInfer
- git checkout -b 你的新分支 study_version_0.02 (如果想抄本项目的代码,请使用这一步切换到study tag)
- mkdir build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release -DDEVELOPMENT=OFF ..
- make -j$(nproc)
提示:
- 如果需要对KuiperInfer进行开发,请使用 git clone --recursive https://github.com/zjhellofss/KuiperInfer.git 同时下载子文件夹tmp, 并在cmake文件中设置
$DEVELOPMENT
或者指定-DDEVELOPMENT=ON
- 如果国内网速卡顿,请使用 git clone https://gitee.com/fssssss/KuiperInferGitee.git
- 如果想获得更快地运行体验,请在本机重新编译openblas或apt install intel-mkl
安装过程(构建Docker镜像)
- docker build -t kuiperinfer:latest .
- docker run --name kuiperinfer -it kuiperinfer:latest /bin/bash
- cd /app
- 余下步骤参考上述安装过程的步骤4-10
安装过程(不使用docker)
- git clone --recursive https://github.com/zjhellofss/KuiperInfer.git
- git checkout -b 你的新分支 study_version_0.01 (如果想参考本项目的代码,请使用这一步切换到study标签)
- 安装必要环境(推荐编译安装openblas以获得更快的运行速度,或者使用apt install intel-mkl替代openblas)
apt install cmake, libopenblas-dev, liblapack-dev, libarpack-dev, libsuperlu-dev
- 下载并编译armadillo https://arma.sourceforge.net/download.html
- 编译安装glog、google test和google benchmark
- 剩余步骤与上述相同
提示:
- 在编译google benchmark过程中,如果遇到关于gtest缺失的错误,可以在google benchmark的cmake中关闭gtest选项
运行 Kuiper 的 demo
运行Unet的推理
编译后请复制 tmp/unet/demo
文件夹下的 test.png 图片的绝对路径或相对路径,
然后在 build/demos
中按以下格式运行推理程序
./unet_test test.png unet_demo.pnnx.param unet_demo.pnnx.bin
pnnx 模型的下载地址:https://cowtransfer.com/s/09c7f337bab443
如果推理成功,你将会在文件夹内看到原图的分割结果 unet_output.jpg 。
运行Yolov5的推理
请在demos文件夹下的yolo_test.cpp文件中修改以下代码
const std::string& image_path = "imgs/car.jpg";
const std::string& param_path = "tmp/yolo/demo/yolov5s_batch8.pnnx.param";
const std::string& bin_path = "tmp/yolo/demo/yolov5s_batch8.pnnx.bin";
-
image_path
指定图像目录,param_path
为模型的参数文件,bin_path
为模型的权重文件,请替换为你本地的路径。 -
模型定义和权重下载地址如下: https://cowtransfer.com/s/9bc43e0905cb40
-
编译完成后,在项目目录运行
./build/demos/yolo_test
已支持的算子
总体理念:逐步优化现有算子;在需要时再开发未实现的算子
- Convolution
- AdaptivePooling
- MaxPooling
- Expression(抽象语法树)
- Flatten, View(维度展平和变形)
- Sigmoid
- HardSigmoid
- HardSwish
- ReLU
- Linear(矩阵相乘)
- Softmax
- BatchNorm
- Upsample
- SiLU
- Concat
- ConvTranspose
目录
source是源码目录
- data/ 是张量类Tensor的实现和Tensor初始化方法
- layer/ 是算子的实现
- parser/ 是Pnnx表达式的解析类
- runtime/ 是计算图结构、解析和运行时相关
test是单元测试目录,基本做到public方法单元测试全覆盖
bench是google benchmark,包含对MobilenetV3、Resnet18和yolov5s的性能测试。
性能测试
测试设备
15 核心的AMD EPYC 7543(霄龙) 32-Core Processor (Docker 容器,宿主机共有32核心)
编译环境
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
性能结果
耗时通过连续五次运行并取平均值计算
输入尺寸 | 模型名称 | 计算设备 | 耗时 |
---|---|---|---|
224×224 batch = 8 | MobileNetV3Small | CPU(armadillo + openblas) | 6.76ms / 图像 |
224×224 batch = 8 | ResNet18 | CPU(armadillo + openblas) | 23.53ms / 图像 |
224×224 batch =16 | ResNet18 | CPU(armadillo + openblas) | 13.52ms / 图像 |
640×640 batch = 8 | Yolov5nano | CPU(armadillo + openblas) | 78.37ms / 图像 |
640×640 batch = 8 | Yolov5s | CPU(armadillo + openblas) | 177.54ms / 图像 |
640×640 batch = 16 | Yolov5s | CPU(armadillo + openblas) | 134.57ms / 图像 |
致谢
推理框架NCNN,已在借鉴的代码中保留了NCNN的BSD协议 https://github.com/Tencent/ncnn
优秀的数学库Openblas: https://github.com/xianyi/OpenBLAS
优秀的数学库Armadillo: https://arma.sourceforge.net/docs.html
给予我灵感的Caffe框架: https://github.com/BVLC/caffe
fmath框架:https://github.com/herumi/fmath/