目录
- 前言
- 0. 简介
- 1. FLOPS
- 2. TOPS
- 3. HPC的排行,CPU/GPU比较
- 4. FLOPs
- 5. FLOPS是如何计算的
- 6. CUDA Core vs Tensor Core
- 总结
- 参考
前言
自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习课程第四章—TensorRT 模型部署优化,一起来了解模型部署的基础知识
课程大纲可以看下面的思维导图
0. 简介
本小节目标:理解 FLOPS 和 TOPS 是什么,CPU/GPU 中计算 FLOPS/TOPS 的公式,以及 CUDA Core 和 Tensor Core 的区别
这节课程开始我们进入第四章节—TensorRT 模型部署优化的学习,这章节是偏理论的部分,知识点比较碎片化。我们这节主要讲模型部署的基础知识,这部分内容其实不仅仅局限于 TensorRT 模型部署,大家在做其它硬件上的模型部署的时候很多概念都是通用的
第四章节主要分为以下几个部分:
- 模型部署基础知识
- 模型部署的几大误区
- 模型量化
- 模型剪枝
- 层融合
模型部署基础知识这小节主要教大家一些常见的东西比如 FLOPS、TOPS 等等,同时跟大家介绍一下 CUDA Core 和 Tensor Core 它们核心的区别是什么以及各个模型的 TOPS 是怎么计算的
模型部署的几大误区这小节简单过一下,主要是大家在做模型部署时可能存在的一些误解
模型量化这小节会跟大家讲得比较细,不仅仅是大家常听到的 PTQ 量化和 QAT 量化,会从基础的地方去讲模型量化是怎么做的以及模型量化的量化密度、校准算法选取、校准数据集 batch size 大小的影响、量化层融合等等
模型剪枝这小节会教大家 sparse pruning 是什么东西以及对 kernel 的剪枝和对 channnel 的剪枝它们的区别是什么,还有现在硬件上对模型剪枝的性能支持是怎么样的
层融合这小节主要是做一个总结性的小节,层融合这个概念其实在前面的很多部分都会涉及到,比如 TensorRT 优化有涉及层融合,模型量化也有涉及层融合
今天我们来讲第四章节第一小节—模型部署的基础知识,这节课学完之后希望大家理解 FLOPS 和 TOPS 是什么,CPU/GPU 中的计算 FLOPS/TOPS 的公式以及 CUDA Core 和 Tensor Core 的区别
1. FLOPS
FLOPS(FLoating point number Operations Per Second)
- 指的是一秒钟可以计算处理的浮动小数点运算的次数
- 衡量计算机硬件性能、计算能力的一个单位
- FLOPS 也可以写作 FLOP/s,是一个意思,但千万不能写成 FLOPs
常见的 FLOPS 如下表所示:
2. TOPS
TOPS(Tera Operations Per Second)
- 指的是一秒钟可以处理的整型运算的次数
- 衡量计算机硬件性能、计算能力的一个单位
3. HPC的排行,CPU/GPU比较
HPC(High Performance Compute)排名如下所示:
CPU 与 GPU 在 FLOPS 上的性能比如下图所示:
我们可以看到 CPU 与 GPU 在 FLOPS 上的性能比还是比较大的,CPU 主要是处理复杂逻辑的,GPU 主要是做并行处理所以它的计算密度比较大,在 FLOPS 上的性能也比较强
4. FLOPs
FLOPs(Floating point number operations)
- 是衡量模型大小的一个指标
- 大家在 CVPR 的 paper 或者 Github 里经常能够看到的就是这个信息
值得注意的是 FLOPs 不能够用来衡量模型的推理性能,具体我们还是要看 FLOPS,看模型在硬件设备上的 FLOPS,FLOPs 只是衡量模型大小的一个指标具体还是要看硬件的
5. FLOPS是如何计算的
跟 FLOPS 有关的概念:
- Core 数量
- 时钟频率
- 每个时钟周期可以处理的 FLOPS
FLOPS = 频率 * core数量 * 每个时钟周期可以处理的FLOPS \text{FLOPS = 频率 * core数量 * 每个时钟周期可以处理的FLOPS} FLOPS = 频率 * core数量 * 每个时钟周期可以处理的FLOPS
比如说 Intel i7 Haswell 架构(8 核,频率 3.0GHz)它的 FLOPS 在双精度的时候就是:
3.0*10^9Hz * 8 core * 16 FLOPS/clk = 0.38 TFLOPS \text{3.0*10\textasciicircum 9Hz * 8 core * 16 FLOPS/clk = 0.38 TFLOPS} 3.0*10^9Hz * 8 core * 16 FLOPS/clk = 0.38 TFLOPS
那么它的 FLOPS 在单精度的时候就是:
3.0 * 10^9Hz * 8 core * 32 FLOPS/clk = 0.76 TFLOPS \text{3.0 * 10\textasciicircum9Hz * 8 core * 32 FLOPS/clk = 0.76 TFLOPS} 3.0 * 10^9Hz * 8 core * 32 FLOPS/clk = 0.76 TFLOPS
我们思考下 16 FLOPS/clk 和 32 FLOPS/clk 是如何计算的呢?也就是每个时钟周期可以处理的 FLOPS 是怎么来的呢?
这个其实和硬件的架构相关:
上图是 Interl Haswell 的架构图,可以看到它有两个 FMA 以及支持 AVX-256 指令集
FMA(Fused Multiply Accumulation)是计算的一个硬件单元,下图展示了 FMA 的功能:
我们可以看到没有 FMA 乘法加法分开算,计算 D=A*B+C 需要两个时钟周期;有 FMA 乘法加法一起算,计算 D=A*B+C 需要一个时钟周期
AVX-256 指令集其实跟我们之前讲的 SIMD 操作相关即一个指令去处理多个数据,AVX-256 中一个寄存器可以存储 8 个 32-bit 的 float 或者 4 个 64-bit 的 double(如下图所示)那这也就意味着 AVX-256 在做 SIMD 操作时一个时钟周期就可以处理 8 个 FP32 或者 4 个 FP64 的计算
所以我们回到之前的问题,16 FLOPS/clk 的计算如下:
2 FMA * 4个FP64的SIMD运算 * 2 乘加融合 = 16 FLOPS/clk \text{2 FMA * 4个FP64的SIMD运算 * 2 乘加融合 = 16 FLOPS/clk} 2 FMA * 4个FP64的SIMD运算 * 2 乘加融合 = 16 FLOPS/clk
32 FLOPS/clk 的计算如下:
2 FMA * 8个FP32的SIMD运算 * 2 乘加融合 = 32 FLOPS/clk \text{2 FMA * 8个FP32的SIMD运算 * 2 乘加融合 = 32 FLOPS/clk} 2 FMA * 8个FP32的SIMD运算 * 2 乘加融合 = 32 FLOPS/clk
FPLOS 在 GPU 中是如何计算的呢?跟 CPU 不同的是 GPU 它的特性如下:
- 没有 AVX 这种东西
- 但是有大量的 core 来提高吞吐量
- 有 Tensor Core 来优化矩阵运算
- 有 Tensor Core 来优化矩阵运算
下图展示了 Ampere 架构中一个 SM:
从上图中我们可以看到一个 SM 里面有:
- 64 个处理 INT32 的 CUDA Core
- 64 个处理 FP32 的 CUDA Core
- 32 个处理 FP64 的 CUDA Core
- 4 个处理矩阵计算的 Tensor Core
每一种精度在一个 SM 中的吞吐量(一个时钟周期可以处理的浮点运算的个数)如下表所示:
我们再来看 Ampere 架构的各个精度的吞吐量,如下图所示:
我们思考下这些值是如何被计算出来的呢?我们以 Peak FP64 为例来讲解,我们前面说过一个 SM 里面有 32 个处理 FP64 的 CUDA Core,每一个时钟周期计算一个 FP64,而 Ampere 架构中的各项指标如下:
- 频率:1.41 GHz
- SM 数量:108
- 一个 SM 中计算 FP64 的 CUDA core 的数量:32
- 一个 CUDA core 一个时钟周期可以处理的 FP64:1
- 乘加:2
Throughout = 1.41 GHz * 108 * 32 * 1 * 2 = 9.7 TFLOPS \text{Throughout = 1.41 GHz * 108 * 32 * 1 * 2 = 9.7 TFLOPS} Throughout = 1.41 GHz * 108 * 32 * 1 * 2 = 9.7 TFLOPS
Peak FP32 也可以进行类似的计算,其吞吐量为:
Throughout = 1.41 GHz * 108 * 64 * 1 * 2 = 19.4 TFLOPS \text{Throughout = 1.41 GHz * 108 * 64 * 1 * 2 = 19.4 TFLOPS} Throughout = 1.41 GHz * 108 * 64 * 1 * 2 = 19.4 TFLOPS
值得注意的是 Ampere 中没有专门针对 FP16 的 CUDA core,而是将 FP32 的 CUDA Core 和 FP64 的 CUDA Core 一起使用来计算 FP16。因此我们暂且说一个 SM 中计算 FP16 的 CUDA Core 的数量是:64x2+32x4=256
因此 Peak FP16 的吞吐量为:
Throughout = 1.41 GHz * 108 * 256 * 1 * 2 = 78 TFLOPS \text{Throughout = 1.41 GHz * 108 * 256 * 1 * 2 = 78 TFLOPS} Throughout = 1.41 GHz * 108 * 256 * 1 * 2 = 78 TFLOPS
同理 Ampere 中也没有专门针对 INT8 的 CUDA Core,而是使用 INT32 的 CUDA Core 计算 INT8。因此我们暂且说一个 SM 中计算 INT8 的 CUDA Core 的数量是:64x4=256
因此 Peak INT8 的吞吐量为:
Throughout = 1.41 GHz * 108 * 256 * 1 * 2 = 78 TFLOPS \text{Throughout = 1.41 GHz * 108 * 256 * 1 * 2 = 78 TFLOPS} Throughout = 1.41 GHz * 108 * 256 * 1 * 2 = 78 TFLOPS
看完 CUDA Core 之后我们来分析 Tensor Core,Ampere 架构使用的是第三代 Tensor Core,它一个时钟周期可以完成 256x4=1024 个 FP16 运算,准确来说是 4x8 的矩阵与 8x8 的矩阵的 FMA,而 Ampere 的各项指标如下:
- 频率:1.41 GHz
- SM 数量:108
- 一个 SM 中计算 FP16 的 Tensor core 的数量:4
- 一个 Tensor core 一个时钟周期可以处理的 FP16:256
- 乘加:2
因此 Peak FP16 Tensor Core 的吞吐量为:
Throughout = 1.41 GHz * 108 * 4 * 256 * 2 = 312 TFLOPS \text{Throughout = 1.41 GHz * 108 * 4 * 256 * 2 = 312 TFLOPS} Throughout = 1.41 GHz * 108 * 4 * 256 * 2 = 312 TFLOPS
6. CUDA Core vs Tensor Core
下面我们来看 CUDA Core 和 Tensor Core 的一个比较,我们如果使用一个 CUDA Core 计算矩阵乘法 A * B = C,则计算过程如下图所示:
可以看到如果使用 CUDA Core 来做矩阵乘法的话,输出中的一个元素就需要 8 次 FMA,也就是需要 8 个时钟周期才可以完成一个 c(0,0) 的计算。要完成矩阵 4x8 与 8x4 的计算则需要 8x16=128 个时钟周期才可以完成
当然如果我们有 16 个 CUDA Core 的话,这些计算其实是并行的,实际上只需要 8 个时钟周期,不过为了与 Tensor Core 比较这里只用了一个 CUDA Core
我们再来看使用 1st Gen. Tensor Core(Volta 架构) 来计算矩阵乘法 A * B = C,其计算过程如下图所示:
值得注意的是 Tensor Core 不是一个一个的对 FP16 进行处理,而是 4x4 个 FP16 一起处理,第一个时钟周期先做 A 和 B 的前半段结果先存着,第二个时钟周期再处理 A 和 B 的后半段,最后和前半段结果做个累加完成计算。所以说 Tensor Core 处理 4x8*8x4 的计算只需要 1+1=2 个时钟周期
另外想说的是现在的 Ampere 架构中的 Tensor Core 已经是 3rd Gen. 了,它在一个时钟周期就可以处理 4x8*8x8 的计算,也就是说一个时钟周期可以处理 256 个 FP16
关于 CUDA Core 和 Tensor Core 的区别还可以看下图更直观的感受:
总结
本次课程我们主要学习了模型部署的一些基础知识,包括 FLOPS、TOPS、FLOPs 代表的含义以及 FLOPS 是如何计算的,最后我们简单聊了下 CUDA Core 和 Tensor Core 的一个区别。
OK,以上就是第 1 小节有关模型部署的基础知识的全部内容了,下节我们来学习 Roofline model,敬请期待😄
参考
- AI Chips: A100 GPU with Nvidia Ampere architecture
- High performance computer TOP 6 in JUNE 2024
- A Massively Parallel Processor: the GPU
- Github: Swin Transformer
- EfficientNetV2: Smaller Models and Faster Training
- Intel Processor Architecture
- What is SSE and AVX?
- 深度了解 NVIDIA Ampere 架构
- AI Chips: A100 GPU with Nvidia Ampere architecture
- Programming Tensor Cores in CUDA 9
- YouTube: About NVIDIA Tensor Core