告别CPU思维,拥抱并行天下:AI工程师深入表明GPU架构与实行模子 ...

打印 上一主题 下一主题

主题 1965|帖子 1965|积分 5895

引言:从熟悉到陌生——为什么工程师必要懂GPU?
如果你是一名软件工程师,特别是刚接触AI或高性能计算领域的,你大概率对CPU和次序编程模式洞若观火。究竟,从我们敲下第一行代码开始,就与CPU紧密相连。然而,对于那块在过去的十年里,因深度学习而变得举足轻重、被誉为“AI算力焦点”的GPU,它的内部究竟是如何工作的?它为何能在某些使命上比CPU快上百倍千倍?这些题目可能对许多工程师来说还蒙着一层神秘的面纱。

过去,GPU主要用于图形渲染,是游戏玩家的“专属”。但现在,从AI训练、科学计算到大数据分析,GPU的应用无处不在。明白GPU的基本工作原理,已经不再是少数图形学专家的专属技能,而是每一位志在并行计算领域的软件工程师,尤其是AI工程师的“必修课”。
今天,我们就来翻开GPU的神秘面纱,深入了解它的计划哲学、内部结构和独特的代码实行方式。
一、计划理念的本质差异:CPU vs. GPU
要明白GPU,最好的方式是先将它与我们熟悉的CPU进行对比。CPU和GPU最焦点的区别在于它们最初的计划目的不同:


  • CPU:追求低耽误的次序实行 CPU的计划重点在于尽快完成单个使命,也就是最小化指令的实行时延(Latency)。虽然当代CPU通过超线程、多核等技术也能实现并行,但大量计划工作长期以来都聚焦于提高单条指令的实行速率。为了实现这一点,CPU引入了许多复杂的功能,比方:

    • 指令流水线 (Pipeline): 将指令实行分解成多个步骤,重叠实行。
    • 乱序实行 (Out-of-Order Execution): 打乱指令次序,提前实行不依靠前一条指令结果的指令。
    • 预测实行 (Speculative Execution): 推测分支结果,提前实行可能的指令。
    • 多级缓存 (Multi-level Cache): 大容量、多层级的缓存体系,减少访问主内存的耗时。 这些功能都致力于让CPU可以或许尽可能快地、一条接一条地实行指令序列。CPU就像一位本领全面的“项目司理”,负责复杂使命的协调、决策和快速响应。

  • GPU:追求高吞吐量的大规模并行 与CPU大相径庭,GPU从诞生之初就是为同时处理大量简单使命而计划的。它的计划目的是最大化吞吐量(Throughput),即在单位时间内完成尽可能多的计算使命,而不是最小化单条指令的时延。这种计划方向受其焦点应用场景驱动:

    • 图形处理: 必要同时计算屏幕上数百万个像素点的颜色、光照等。
    • 数值计算: 必要对大量数据进行相同的数学运算(特别是线性代数)。
    • 深度学习: 本质上就是超大规模的矩阵乘法和数值计算。 所有这些应用都必要以极高的速率重复实行相同的计算。因此,GPU的计划牺牲了单条指令的低耽误,调换了大规模的并行计算本领。GPU更像是一个拥有成千上万“计算工人”的“大型工厂”,虽然每个工人完成单个使命可能不比项目司理快,但它们可以同时处理海量使命。

用一个简单的例子来说明:将两个数字相加。 CPU可以非常快地完成一次加法。如果必要按次序进行十次加法,CPU的总耗时会很低。 但如果必要进行数百万甚至数十亿次独立的加法运算(比如向量或矩阵相加),只管单次加法时延较高,GPU凭借其海量的计算单元可以同时实行成千上万次加法,因此在总耗时上将远远高出CPU。
数据可以直观地说明这一点:衡量硬件数值计算性能的指标是每秒浮点运算次数(FLOPS)。NVIDIA Ampere A100 GPU 在 32 位浮点精度下能达到 19.5 TFLOPS 的吞吐量,而同期(2021年)一款典型的 Intel 24 核 CPU 在相同精度下仅约 0.66 TFLOPS。随着时间推移,GPU在吞吐量上的上风还在不断扩大。

如果我们观察CPU和GPU的芯片架构图,会发现CPU将大量芯片面积用于缓存和复杂的控制单元,以低沉指令时延和优化次序实行。而GPU则将绝大部分面积用于密集的算术逻辑单元(ALU,负责实行计算),辅以少量缓存和控制单元,以最大化计算本领和吞吐量。
二、GPU的并行基石:流式多处理器(SMs)
那么,GPU是如何通过其架构实现如此高的吞吐量的呢?这就必要了解GPU的焦点计算单元——流式多处理器(Streaming Multiprocessor,简称SM)

一个GPU由多个SM构成,每个SM内部又包含大量的计算焦点(Core),这些焦点也常被称为流式处理器(Streaming Processor)。比方,NVIDIA 最新的 H100 GPU 就拥有 132 个 SM,每个 SM 内部有 64 个计算焦点,整个芯片总计焦点数量高达 8448 个!
每个SM都是一个相对独立的计算单元,拥有:


  • 大量计算焦点: 负责现实的数值计算。
  • 片上内存: 通常称为共享内存(Shared Memory)或暂时存储器(Scratchpad Memory),供该SM内的所有焦点共享使用。这是一种非常快速的内存,对于SM内的线程间数据共享至关紧张。
  • 控制单元和硬件线程调度器: 负责管理和调度在该SM上运行的线程。
  • 专勤奋能单元: 除了基本的计算焦点,当代SM还会合成一些专门的硬件加快单元,比方用于矩阵运算的张量焦点(Tensor Core)(对深度学习至关紧张)或用于图形学的光线追踪单元(Ray Tracing Unit),以满足特定工作负载的高效计算需求。
明白SM是明白GPU并行架构的关键。每个SM都能同时实行多个线程束(我们稍后会具体先容),从而在SM层面实现并行。而整个GPU拥有多个SM,则在更高的层面实现了大规模并行。
三、层层加快:GPU的内存体系
GPU的高性能不仅依靠于海量计算焦点,也依靠于其经心计划的内存层次结构。与CPU类似,GPU拥有多层不同范例、不同速率和容量的内存,以满足不同计算阶段的数据访问需求。

从距离计算焦点最近、速率最快到最远、速率相对较慢的内存层次,主要包罗:

  • 寄存器(Registers):

    • 位置: 位于每个SM内部,紧邻计算焦点。
    • 速率/容量: 速率最快,容量相对较小,每个SM拥有一个较大的寄存器文件总量(比方 NVIDIA A100/H100 的每个 SM 有 65536 个寄存器),这些寄存器在SM内的所有线程之间动态分配。
    • 用途: 每个线程都有本身私有的寄存器,用于存储线程实行过程中的局部变量和中间结果。其他线程无法直接访问某个线程的私有寄存器。

  • 常量缓存(Constant Cache):

    • 位置: 片上(On-chip),每个SM有本身的常量缓存。
    • 用途: 缓存 SM 上实行的代码中使用的常量数据。程序员通常必要显式地将数据声明为常量,以便 GPU 可以将其缓存到常量缓存中,提高访问速率。

  • 共享内存(Shared Memory / Scratchpad Memory):

    • 位置: 片上(On-chip),每个SM拥有一块。
    • 速率/容量: 速率非常快,耽误低,容量比寄存器大但比缓存小。这是一种可编程的 SRAM 内存。
    • 用途: 供同一个线程块(Thread Block)内的所有线程共享使用。 这是 GPU 并行编程中非常紧张的一种内存。线程块内的线程可以将全局内存中的数据加载到共享内存中,然后该块内的所有线程都可以快速访问和共享这些数据,制止重复从较慢的全局内存中加载。它也常用于线程块内的线程同步。

  • L1 Cache:

    • 位置: 片上(On-chip),每个SM拥有一块 L1 缓存。
    • 用途: 缓存从 L2 缓存中频繁访问的数据。对于 SM 来说,L1 和 L2 缓存通常是透明的,SM 访问全局内存时,数据可能首先经过 L1 和 L2。

  • L2 Cache:

    • 位置: 片上(On-chip),但由 所有 SM 共享
    • 用途: 缓存全局内存中被所有 SM 频繁访问的数据,用于低沉全局内存访问的时延。

  • 全局内存(Global Memory):

    • 位置: 片外(Off-chip),是 GPU 主板上的 DRAM 内存。
    • 速率/容量: 容量最大,但由于距离 SM 较远,访问时延最高。当代高端 GPU 通常使用高带宽内存(HBM),提供极高的数据带宽(比方 NVIDIA H100 有 80GB HBM,带宽高达 3TB/s)。
    • 用途: 存储程序数据、输入输出数据、中间结果等。在 GPU 上实行计算前,通常必要将数据从 CPU(主机)内存复制到 GPU 的全局内存。

虽然全局内存时延高,但 GPU 的其他层级内存(特别是 Shared Memory 和 L1/L2 Cache)以及海量的计算单元和高效的调度机制,可以或许有用地“隐藏”这种时延,确保计算单元不会长时间空闲期待数据。
四、GPU如何实行代码:Kernel, Grid, Block, Thread 和 Warp
明白了GPU的硬件架构和内存,接下来我们看看编写的代码如何在这些硬件上跑起来。
大多数 GPU 通用计算编程都使用 NVIDIA 提供的 CUDA 编程接口(或者类似的开放尺度如 OpenCL/SYCL)。在 CUDA 中:

  • Kernel(核函数): 你要让GPU实行的并行计算使命,通常写成一个函数,称为 Kernel。Kernel 吸收输入参数(通常是必要并行处理的向量或矩阵),并在 GPU 上由成千上万个线程并行实行。比方,一个向量加法的 Kernel 就是对输入向量的每个元素实行相加操作,并将结果写入输出向量。
  • 实行结构:Grid, Block, Thread 为了在 GPU 上实行 Kernel,你必要启动大量的线程。这些线程不是紊乱无章的,而是构造成一个层次结构:

    • 网格(Grid): 所有实行同一个 Kernel 的线程的集合。一个 Kernel 对应一个 Grid。
    • 线程块(Thread Block): Grid 由一个或多个线程块构成。线程块内的线程可以互相协作(比方通过 Shared Memory)和同步。同一个线程块中的所有线程会被调度到同一个 SM 上实行。
    • 线程(Thread): 线程块由一个或多个线程构成。每个线程实行 Kernel 函数的副本,但处理数据中的不同部分(比方在向量加法中处理向量的不同索引)。



你可以根据数据规模和所需的并行度来配置 Grid 和 Block 的维度和巨细。比方,要对一个 256 维的向量进行加法,你可以配置一个包含 256 个线程的线程块,让每个线程处理一个元素。如果向量更大,你可能必要更多的线程块,或者让每个线程处理多个元素。
编写 GPU 代码通常分为两部分:


  • 主机代码(Host Code): 运行在 CPU 上。负责数据加载、为 GPU 分配内存、将数据从 CPU 内存复制到 GPU 全局内存(或使用统一虚拟内存),以及配置 Grid 和 Block 的巨细,并最终启动(launch)Kernel。
  • 装备代码(Device Code): 运行在 GPU 上。这部分就是 Kernel 函数本身。

五、并行实行的秘密:Block分配、Warp与耽误隐藏
当你在主机代码中启动一个 Kernel 后,GPU 是如何分配和实行这些线程的呢?

  • 数据传输: 首先,Kernel 必要处理的数据必须从 CPU(主机)内存传输到 GPU 的全局内存(装备内存)。(注:较新的硬件和 CUDA 版本支持统一虚拟内存,可以在一定水平上简化这一步骤,允许 GPU 直接访问主机内存)。
  • 线程块分配到SM: 数据准备好后,GPU 会将线程块分配给 SM 进行处理。GPU 内部有一个硬件调度器,负责将待实行的线程块分配给空闲的 SM。同一个线程块内的所有线程保证被调度到同一个 SM 上实行,这样它们才气使用共享内存进行协作和同步。由于 SM 数量有限,如果 Kernel 包含大量线程块,它们会排队期待分配。当一个线程块实行完毕,SM 开释资源,调度器就会从队列中选择下一个线程块进行实行。
  • 线程分组到 Warp: 被分配到同一个 SM 上的线程块,其内部的线程还会被进一步划分为更小的实行单元——Warp。一个 Warp 通常包含 32 个线程(这是 NVIDIA GPU 的特性)。SM 会以 Warp 为单位进行指令的调度和实行。
  • SIMT实行模子: SM 通过获取一条指令,然后将这条指令同时发送给 Warp 中的所有 32 个线程实行。所有的线程都实行同一条指令,但是操作的是不同的数据。这种实行模子被称为 单指令多线程(Single-Instruction, Multiple-Thread, SIMT)。在向量加法的例子中,一个 Warp 中的 32 个线程可能都在实行“加法”指令,但每个线程操作的是向量中不同的索引位置上的元素。这与 CPU 的 SIMD (Single-Instruction, Multiple-Data) 指令有点类似,但 SIMT 是在线程层面,更具机动性。

值得留意的是,较新的 GPU 架构(如 Volta 及之后)引入了独立线程调度(Independent Thread Scheduling),在 Warp 内部允许线程之间有更多的独立性和并发性,不再强制所有线程严格同步实行同一条指令,这能更好地使用实行资源,但也增加了同步的复杂性。

  • 耽误隐藏(Latency Hiding): 这是 GPU 高吞吐量的焦点秘密之一。我们知道,访问全局内存、实行某些复杂指令都可能引入较高的耽误,导致线程或 Warp 必要期待。此时,SM 不会空等。得益于每个 SM 上存在的大量线程和 Warp,以及每个线程都拥有本身的寄存器状态(切换代价低),SM 的硬件调度器会立即切换到实行另一个已经就绪、不必要期待的 Warp。通过快速地在不同 Warp 之间切换,SM 可以或许始终保持其计算单元处于忙碌状态,用大量的计算使命填充掉指令的期待时间,从而最大化整体吞吐量。

相比之下,CPU 的上下文切换代价较高,由于它必要将一个历程(或线程)的寄存器状态生存到内存并恢复另一个历程的状态。GPU 的 Warp 切换发生在硬件层面,且每个线程的寄存器是独立的,因此服从极高。
六、性能的检验:资源分配与SM占用率(Occupancy)
虽然 GPU 拥有强大的并行本领,但要充实发挥其性能,必要开发者对资源管理有深入的明白。一个关键的指标就是 SM 占用率(Occupancy)
占用率衡量了 SM 被有用使用的水平,具体是指分配给一个 SM 的活跃 Warp 数量与该 SM 可以或许支持的最大 Warp 数量之间的比值。理想情况下,我们盼望达到 100% 的占用率,这意味着 SM 拥有充足的活跃 Warp 来隐藏指令耽误,确保计算单元始终满负荷运转,从而实现最大吞吐量。
然而,在实践中实现 100% 占用率并非易事,由于 SM 的资源是有限的,并且必要在多个线程块和线程之间进行动态分配。SM 拥有固定数量的资源池,主要包罗:


  • 总寄存器数量
  • 共享内存容量
  • 同时支持的线程块数量上限
  • 同时支持的总线程数量上限(通常即是最大 Warp 数 × Warp 巨细,如 64 Warp × 32 = 2048 线程在 H100 上)
当一个线程块被分配到 SM 上时,它会申请并占用这些资源。资源的分配是动态的:


  • 每个线程必要一定数量的寄存器。
  • 每个线程块必要一定量的共享内存。
  • 每个线程块占用一个线程块槽位。
  • 线程总数不能高出 SM 的上限。
资源分配是动态的,意味着资源会根据每个线程块或线程的现实需求来划分。比方,NVIDIA H100 的一个 SM 最多可以支持 32 个线程块、64 个 Warp(2048 个线程)。
资源的限制直接影响占用率。举例来说明:


  • 假设你的 Kernel 使用了 32 个线程的线程块,总共必要 2048 个线程来处理数据。这必要 2048 / 32 = 64 个线程块。但如果一个 SM 最多只能处理 32 个线程块,那么纵然该 SM 有 2048 个线程槽,它一次最多也只能运行 32 个线程块,总计 32 * 32 = 1024 个线程(或 32 个 Warp),此时占用率就只有 32 / 64 = 50%。
  • 假设你的 Kernel 每个线程必要 64 个寄存器。一个 SM 总共有 65536 个寄存器。如果一个 SM 最多支持 2048 个线程,那么均匀每个线程最多只能分配 65536 / 2048 = 32 个寄存器。如果你的 Kernel 必要 64 个寄存器,那么一个 SM 最多只能运行 65536 / 64 = 1024 个线程(或 1024 / 32 = 32 个 Warp),占用率同样只有 32 / 64 = 50%。

占用率不足意味着 SM 没有充足的活跃 Warp 来有用地隐藏指令耽误,或者无法满负荷地使用计算资源,从而无法达到硬件的最佳性能。
编写高效的 GPU Kernel 是一项充满挑衅的工作,开发者必要在最大化占用率(保证有充足的 Warp 来隐藏耽误)和优化单线程/单 Warp 性能(如通过使用更多寄存器减少访存,但这可能低沉占用率)之间找到均衡。合理地配置线程块巨细、管理共享内存的使用以及优化寄存器使用都至关紧张。
结论:跨越鸿沟,把握并行计算的钥匙
回顾一下我们今天探究的关键要点:

  • CPU与GPU计划理念大相径庭: CPU追求低耽误的次序实行,GPU追求高吞吐的大规模并行。
  • GPU的焦点计算单元是SM: 每个SM包含多个焦点、共享内存、控制单元和硬件调度器。
  • GPU内存体系多层级: 从快速私有的寄存器,到SM内共享的Shared Memory,再到全局共享的L1/L2 Cache,最终是容量大但慢的Global Memory (HBM/DRAM)。
  • GPU代码实行基于层次结构: Kernel构造成Grid,Grid包含Block,Block包含Thread。同一个Block的线程运行在同一个SM上。
  • Warp是调度的基本单位: SM以32个线程构成的Warp为单位实行SIMT指令,并通过在不同Warp间快速切换来隐藏耽误。
  • 资源分配影响性能: SM资源(寄存器、Shared Memory等)在线程间动态分配,直接影响SM的占用率。高占用率是实现高吞吐量的关键。
  • 优化Kernel必要权衡: 开发者必要精细管理资源,均衡各项指标,以达到最佳的SM占用率和性能。
明白这些基本概念,是你从CPU的次序思维跨越到GPU并行天下的敲门砖。虽然编写高效的GPU Kernel 是一项复杂的使命,涉及对硬件细节的深刻明白和精妙的代码优化,但根本原理是相通的。
盼望这篇文章能帮助你开端构建起对GPU架构和实行模子的认知框架。未来,随着你深入学习CUDA等并行编程模子,这些概念会越来越清晰。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

西河刘卡车医

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表