大模型动力引擎-深度学习必备硬件知识


GPU与内存

深度学习模型的基础计算单元是"算子",本质上是将输入映射为输出的计算过程,对于古老的CPU-内存体系来说,算子遵循一下步骤: - 从内存中读取输入数据 - 对独到的数据调用CPU指令,完成算子计算 - 将计算结果写回内存

内存

通常指的是随机访问存储器(RAM),“随机”意味着访问任何位置的数据所需的时间是相同的,与位置无关。 RAN可以分为两类: - 静态随机访问存储器(SRAM):基于双稳态触发器(bistable flip-flop),读取时不会丢失数据(非破坏性读取)。常用于Cache。 - 动态随机访问存储器(DRAM):基于电容存储,读取数据会丢失数据,需要重写(破坏性读取,需刷新)。常用于主存。

不管是SRAM还是DRAM,都是临时存储,断电后数据会丢失的,数据不会保留(易失性)。

在选用内存时往往会看到DDR4、DDR5等字样,指的是基于DDR的第几代产品,涉及技术标准、芯片结构及控制算法的升级,但是要看主板是否支持最新一代内存规格。

CPU

CPU的核心结构包括负责计算的算数逻辑单元(ALU)、负责加速数据读写速度的多级缓存,在此基础上还会采用CPU多核心设计来增加并行度。

硬盘

与RAM不同,硬盘是长期存储设备,断电后数据不会丢失,数据会保留(非易失性)。 一般常用的硬盘有机械硬盘HDD和固态硬盘SSD。SSD的读写速度远高于HDD,但是价格也更高。

硬盘的读写行为大致分为两种模式: - 随机读写模式:高频率读写小规模数据。IOPS(Input/Output Operations Per Second)是衡量硬盘随机读写速度的指标。 - 连续读写模式:需要读取大文件或顺序访问数据。MB/s(Megabytes per second)是衡量硬盘连续读写速度的指标。

其中连续读写速度有硬盘连续读写速度和数据传输速度共同决定。随着硬盘读取效率的不断提高,读写效率的瓶颈慢慢开始出现在了数据传输阶段,所以在SATA固态硬盘的基础上,又发展出了NVMe固态硬盘。NVMe固态硬盘使用传输效率更高的PCIe传输通道,在读写性能上往往超出SATA固态硬盘许多。

显卡

CPU局限性

CPU可以“全能”的处理各种指令(计算指令、访存指令,也能够处理好跳转等逻辑指令),但在处理计算密集型任务时,CPU的计算速度不如GPU或其他异构芯片高效。

因此针对计算密集型的额任务,应该让CPU处理复杂的交互逻辑,而采用一个专门的芯片处理密集的计算, 这需要我们在软件层面上对程序任务进行划分,将一个程序涉及的所有任务都分为两种类型: - 外围任务:业务代码、API接口、用户交互等逻辑复杂的任务。 - 内核任务:高度内聚的计算密集型任务,逻辑分支很少。

而GPU可以处理密集的计算,例如一个3D游戏,其中用户交互、用户界面(UI)、音频等部分由CPU负责处理,而图形渲染和物理仿真等核心计算任务则由GPU执行。 在深度学习领域,核心的计算任务被封装成算子并在GPU上执行,而复杂的逻辑调度、数据搬运等任务则由CPU完成。

GPU硬件结构

GPU的计算核心并不能直接从内存读取数据,于是在二者之间又加入了显存(VRAM)这个额外的存储元件。

GPU自顶向下可以分为以下几个部分: - 最外层:显存、L2缓存 - 高层封装单元:流式多处理器(SM) - L1缓存 - 多个流式处理器(SP),共享一个SM的L1缓存,每个SP包括: - 若干标量计算核心(CUDA core) - 若干张量计算核心(tensor core) - 若干寄存器 - 线程束调度器(warp scheduler)

这里面真正重要的是图中标记为蓝色的几个硬件单元。其中张量计算核心、标量计算核心决定了GPU的整体计算效率;L1缓存、显存决定了GPU存取数据的效率;线程束调度器则与CUDA编程模型中的线程束(warp)概念直接对应,负责线程间的通信和调度。

A100(Ampere架构)中的SM如下图:

A100整体架构图:

GPU编程模型及其硬件对应

Python、C++等程序能够在计算机上运行,是因为它们通过编译器转换成硬件能识别的指令,从而在CPU上执行。 基于这一逻辑,如果存在一个能将C++或Python编译成GPU指令的编译器,我们就可以直接在GPU上运行这些代码。 然而,遗憾的是,NVIDIA没有提供这种直接的编译器。相反,NVIDIA开发了一套专门的GPU编程模型,称为CUDA语言,来支持在GPU上进行编程。 CUDA编程模型本质是对GPU硬件的抽象。

CUDA编程模型的核心是要求程序员将算法的实现代码,拆分成多个可以独立执行的软件任务。 我们将算法拆分得到的每个独立任务,称为一个线程。线程是软件层面最小的执行单元。

为了尽可能提高并行度,SP中的线程束调度器(warp scheduler)会将每32个线程打包成一个线程束(warp)。 在一个时钟周期内,每组线程束会被调度到一个流式处理器上,执行一条相同的GPU指令。 SM对应CUDA编程语言中线程块(block)的概念。

GPU的并行能力其实分为软件并行和硬件并行两层: - 软件并行:将算子拆分成多个可以独立执行的线程,使用CUDA语言实现。 - 硬件并行:对线程进行分组,然后以线程束(warp)或者线程块(block)为单元,并行执行这些线程。

GPU的关键指标

  • Tensor core和CUDA core性能:决定了计算效率。
  • 显存大小:决定了可以承载的模型、数据规模上限。
  • 显存带宽:决定了显存读写效率。
  • 卡间通信带宽:决定了多块GPU卡之间数据通信的效率。

显存VRAM与内存DRAM之间的数据传输

一般来说,VRAM与DRAM之间的传输依靠CPU进行调度,但是如果DRAM中的数据存储在锁页内存(Pinned Memory)中,CPU无法直接访问,此时就需要使用DMA(Direct Memory Access)技术。

另外,NVIDIA还提供了依靠DMA的VRAM与硬盘/网络之间数据传输: - GPU Direct Storage技术:允许GPU借助DMA直接访问NVMe固态硬盘; - RDMA技术:允许GPU借助DMA直接访问网络存储。

分布式系统

单机多卡

多卡在单机上的通信方式有两种: - 通过PCIe总线连接 - 通过NVLink连接

NVLink是NVIDIA开发的一种高速互连技术,专门用于GPU之间的通信(CPU与GPU之间的通信使用PCIe总线)。

NVLink第一代在Pascal架构中被引入,后面逐代升级。

多机多卡

在涉及多机多卡的分布式训练中,不同机器上的GPU通信的硬件不再是NVLink或者PCIe这种高带宽低延迟的互联,而是基于网络设备的传输。 两类主流的解决方案分别基于Ethernet以及InfiniBand

分布式系统的数据存储

对于分布式训练系统来说,通过每台服务器的本地硬盘存储大规模训练数据并不现实。 基于网络的存储方案在分布式系统中更受欢迎。通常也分为两类,即NFS(network file system,网络文件系统)和基于云服务的存储方案。

分布式系统的硬件示意图:


文章作者: 庞贝堡垒
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 庞贝堡垒 !
评论
  目录