GPU vs CPU 基本概念学习笔记

GPU vs CPU

名词解释

名词 通俗解释
Die(芯片裸片) 封装壳里那块薄薄的硅片,是芯片的"本体",上面刻着几十亿个晶体管电路
Core(核心) 芯片里能独立执行计算任务的"大脑单元",就像一个工人。4核CPU = 4个工人
ALU(算术逻辑单元) Core里专门做整数加减乘除和逻辑判断的电路,是最基本的计算部件
FPU(浮点运算单元) Core里专门处理小数(如3.14)运算的电路,"浮点"指小数点位置会随数值大小移动
Cache(缓存) 芯片内部的"小抄本",把常用数据存在离Core最近的地方,避免每次去远处内存取
L1/L2/L3 Cache 缓存分三层,L1最快最小(离Core最近),L3最慢最大
RAM / 主内存 电脑运行时存放数据的地方,断电消失,比Cache慢但容量大(如16GB)
DDR5 目前主流CPU使用的内存规格,第五代
HBM(高带宽内存) GPU专用内存,紧贴芯片封装,传输速度是普通内存的约30倍
时钟周期(cycle) 芯片工作的最小时间间隔,由时钟频率决定。3GHz芯片每秒震荡30亿次,即每个周期约0.33纳秒。频率越高,每个周期越短,运算越快
线程(Thread) 一段独立执行的指令序列,可理解为"一个任务"
SM(流式多处理器) GPU里的"小计算集群",包含大量简单计算核心
计算核心 GPU里最基础的计算单元,只做简单运算,但数量极多
Warp(线程束) GPU里32个线程被捆绑成一组,必须步调一致地执行同一条指令
SIMD 一条指令同时处理多份数据,通过加宽硬件通道实现
SIMT GPU的并行方式,一条指令让多个线程同时执行
分支预测 CPU技巧:if-else还没判断完时提前猜走哪条路
乱序执行 CPU技巧:不按代码顺序,把"现在能做的"先做了
带宽 数据传输的"马路宽度",带宽越高,单位时间搬运的数据越多

一、核心哲学的对立

CPU和GPU虽然都叫"处理器",但设计目标截然相反

维度 CPU GPU
设计目标 最小化延迟(让单个任务尽快完成) 最大化吞吐量(让尽量多任务同时运行)
核心数量 少(常见4~64个) 极多(数千个,高端超过一万个)
核心能力 每个核心都很"聪明"(会预判、会变通) 每个核心都很"简单"(只管埋头干活)
适合任务 复杂逻辑、操作系统、数据库、网页服务 大规模重复计算:AI训练、图形渲染、科学模拟

生活类比:

  • CPU = 顶尖外科医生:一次专注一台手术,技术全面,能应对各种突发情况
  • GPU = 流水线工厂:几千个工人同时各做一道工序,单个工人技能简单,但整体产出惊人

二、硬件架构拆解

2.1 什么是Die(芯片裸片)?

买到手的CPU/GPU外面是一个封装外壳。把外壳打开,里面有一块薄薄的硅片,这就是Die。Die上面用光刻技术刻出了几十亿个晶体管,组合成各种电路。

复制代码
你买到的CPU芯片(外观):

  ┌──────────────────┐
  │    封装外壳        │
  │  ┌────────────┐  │
  │  │  Die(硅片)│  │  ← 真正的"芯片本体"
  │  └────────────┘  │
  │  金属触点(针脚) │  ← 插在主板上的接口
  └──────────────────┘

CPU Die 和 GPU Die 都是硅片,只是上面刻的电路设计完全不同。


2.2 CPU架构:为"聪明的独奏家"打造

复制代码
  ┌──────────────────────────────────────────────┐
  │            CPU Die(芯片本体)                 │
  │                                              │
  │  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
  │  │  Core 0  │  │  Core 1  │  │  Core 2  │   │
  │  │ ──────── │  │ ──────── │  │ ──────── │   │
  │  │  ALU     │  │  ALU     │  │  ALU     │   │  ← 整数加减乘除
  │  │  FPU     │  │  FPU     │  │  FPU     │   │  ← 小数运算
  │  │ L1 Cache │  │ L1 Cache │  │ L1 Cache │   │  ← 每核自己的"便签"
  │  │ L2 Cache │  │ L2 Cache │  │ L2 Cache │   │  ← 稍大的"抽屉"
  │  └──────────┘  └──────────┘  └──────────┘   │
  │                                              │
  │       共享L3 Cache(所有核共用的"文件柜")     │
  │                                              │
  │           内存控制器 → 外部主内存(RAM)        │
  └──────────────────────────────────────────────┘

各组件解释:

组件 作用
ALU 处理整数运算(1、100这类没有小数点的数)的"计算器"
FPU 处理小数(如3.14,AI模型权重)的专用计算器
L1/L2 Cache Core自己的"随身便签",存最近用过的数据,极快但很小
L3 Cache 所有Core共享的"公共资料室",比L1/L2慢但比内存快
主内存(RAM) 容量大(16-64GB),但访问需要约200个时钟周期

为什么要分这么多层缓存?

主内存距离Core较远,取一次数据要等200个时钟周期。好比工人需要资料,但资料室在2公里外。解决:在工人旁边放小书架(L1),再远点放大书架(L2/L3),常用资料提前放进来,大多数时候就不用跑远路。


2.3 GPU架构:为"万人合唱团"打造

GPU的设计思路和CPU完全不同------不追求每个工人有多聪明,而是追求有多少工人同时干活

关于厂商差异: 下图是通用GPU架构,不依赖特定厂商。NVIDIA、AMD、Intel的GPU都遵循类似的层次结构。各厂商只是叫法不同(NVIDIA叫SM,AMD叫CU,Intel叫Xe-core),但原理完全相同。

复制代码
  ┌──────────────────────────────────────────────────────────┐
  │                  GPU Die(芯片本体)                       │
  │                                                          │
  │  ┌─────────────────────────────────────────────────┐     │
  │  │   SM(流式多处理器,GPU的"小计算集群")           │     │
  │  │                                                 │     │
  │  │  ┌────┐┌────┐┌────┐┌────┐  (几十到上百个核心)   │     │
  │  │  │核心││核心││核心││核心│                       │     │  ← 简单计算单元
  │  │  └────┘└────┘└────┘└────┘                       │     │
  │  │                                                 │     │
  │  │  Warp调度器 + 寄存器堆 + 共享内存                 │     │
  │  └─────────────────────────────────────────────────┘     │
  │                                                          │
  │               × N个SM(几十到上百个同时工作)              │
  │                                                          │
  │   高速专用内存(HBM)←→ L2 Cache ←→ SM                    │
  └──────────────────────────────────────────────────────────┘

各组件解释:

组件 作用
SM GPU里的"工人小队",包含几十到上百个简单计算核心
计算核心 最基本的计算单元,只做简单运算,但数量极多,靠数量取胜
Warp调度器 SM里的"小管家",决定哪32个线程接下来执行
寄存器堆 每个线程专属的"便签纸",始终保留在硬件里------这是GPU能快速切换线程的关键
高速专用内存(HBM) GPU专用内存,传输速度是普通电脑内存的约30倍

三、延迟 vs 吞吐量:最根本的取舍

3.1 先理解这两个概念

  • 延迟:完成一件事需要多长时间(越短越好)
  • 吞吐量:单位时间内能完成多少件事(越多越好)

生活例子:

延迟 吞吐量
外科医生 一台手术 = 2小时 一天能做 = 4台
流水线工厂 做一件衬衫 = 1天 每天产出 = 10,000件

两者都有价值,只是适用场景不同。


3.2 CPU的策略:消灭等待

CPU最大的"敌人"是内存访问的等待。每次从主内存读数据需要等约200个时钟周期------相当于"停工200步":

复制代码
没有优化时:
[取指令] → [等主内存....200步....] → [执行] → [写回]
                   ↑
         这200步CPU什么都没干,纯粹在等

CPU的三大优化手段:
① 大Cache:把常用数据提前存在"手边"
② 分支预测:if-else还没判断完,提前猜结果
③ 乱序执行:当前指令在等待时,把后面"不依赖这个结果"的指令先执行

乱序执行举例:

复制代码
代码顺序(如果严格按序):
步骤1: 从内存读A(等200步)
步骤2: 从内存读B(等200步)
步骤3: C = A + B
顺序执行总耗时:200 + 200 + 1 = 401步

CPU实际执行(乱序):
→ 同时发出"读A"和"读B"的请求(两个等待并行进行!)
→ 200步后A和B都到了
→ 执行C = A + B
实际耗时:200 + 1 = 201步(节省近一半!)

CPU核心像一位全能魔术师:当一件事卡住时,它会变着花样继续工作。


3.3 GPU的策略:用线程淹没等待

GPU根本不试图消灭等待,而是备好海量线程,让等待中的线程"靠边站",立刻切换到其他准备好的线程:

复制代码
GPU同时有1000组线程(每组32个,叫一个Warp)在排队:

时间轴:
Warp 0: [执行] → [要读内存,等着...]
                              ↓ 立刻切换,零代价
Warp 1:          [执行] → [要读内存,等着...]
                                        ↓ 立刻切换
Warp 2:                    [执行] → [要读内存,等着...]
                                                   ↓ ...
...(还有997个Warp在排队)...

当所有Warp都轮完一圈,Warp 0的内存数据早就回来了:
Warp 0:                                          [继续执行] ✅

为什么GPU切换线程是"零代价"的?

CPU切换线程需要保存/恢复所有寄存器数据,需要额外时间。GPU不同:每个Warp的所有寄存器始终保留在硬件里(不会被覆盖),切换瞬间完成。

顿悟点: GPU不怕延迟,它靠海量并发线程来掩盖延迟。只要排队的线程足够多,等待时间就会被完全"填满"。


四、SIMD vs SIMT:两种"一次干多件事"的方式

4.1 CPU的SIMD:加宽数据"通道"

SIMD = Single Instruction Multiple Data = 单指令多数据

"一条指令可以附带多个数据参数吗?"

不是"附带参数",而是数据本身被打包成更宽的格式,硬件电路同时处理这一大包数据。

通俗类比:

  • 普通加法:单车道,每次只能过1辆车(处理1个数)

  • SIMD加法:把道路拓宽成16车道,同一时刻过16辆车(处理16个数)

    普通加法(一次1个数,需要16条指令):
    指令1: 1 + 1 = 2
    指令2: 2 + 2 = 4
    ...
    指令16: 16 + 16 = 32

    SIMD加法(一次16个数,只需1条指令):
    输入A:[1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16]
    输入B:[1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16]
    输出C:[2, 4, 6, 8,10,12,14,16,18,20,22,24,26,28,30,32]
    16次运算同时完成!

关键理解: 这不是顺序执行16次,而是硬件电路本身就有16条并行的计算通道,物理上同时完成------就像16车道收费站和单车道的区别。

局限: 每次最多处理多少个数,由芯片电路宽度决定(不能无限扩展)。程序员需要专门改写代码才能用上SIMD。


4.2 GPU的SIMT:让多个线程"齐步走"

SIMT = Single Instruction Multiple Threads = 单指令多线程

GPU把32个线程捆绑成一个Warp,这32个线程共用一个"指令发射器",每个时钟周期只发出一条指令,但32个线程同时执行这条指令,各自处理自己的数据:

复制代码
Warp(32个线程同步执行一条加法指令):

线程 0: a[0] + b[0] = c[0]   ┐
线程 1: a[1] + b[1] = c[1]   │
线程 2: a[2] + b[2] = c[2]   │ ← 这32个线程在同一时刻
...                          │   执行"同一条"加法指令
线程31: a[31]+ b[31]= c[31]  ┘   但每个线程处理各自的数据

SIMT最妙的地方: 程序员写代码时,就像在写"只处理一个元素的单线程程序",硬件自动把它复制到32个线程同时执行。程序员不需要关心向量化的细节。


4.3 SIMD和SIMT的本质区别

SIMD(CPU) SIMT(GPU)
并行方式 加宽数据通道(电路更宽) 多个线程同步执行
并行上限 受芯片电路宽度限制(如一次最多16个float) 受线程数量限制(可以几百万个线程)
编程难度 需要手动向量化或特殊指令 写普通逻辑,框架自动并行
适合规模 小规模批量运算(几十个数) 超大规模并行(几百万个数)

五、内存层次结构对比

5.1 CPU内存层次(追求低延迟)

复制代码
速度最快 ↑     寄存器      ~1个时钟周期    ← Core的"双手"
容量最小 ↑        ↓
             L1 Cache   ~4个时钟周期    ← 每核自己的"便签",32-64KB
                 ↓
             L2 Cache   ~12个时钟周期   ← 每核自己的"抽屉",256KB-1MB
                 ↓
             L3 Cache   ~40个时钟周期   ← 所有核共享的"文件柜",32-192MB
                 ↓
速度最慢 ↓     主内存(RAM)~200个时钟周期 ← 电脑的"书架",8-128GB
容量最大 ↓

5.2 GPU内存层次(追求高带宽)

复制代码
速度最快 ↑     寄存器      ~1个时钟周期    ← 数量极多,始终保留在硬件里
容量最小 ↑        ↓
             共享内存    ~20-30个时钟周期 ← SM内线程共享的"小黑板"
                 ↓
             L1/L2 Cache ~30-200个时钟周期
                 ↓
速度最慢 ↓     高速专用内存 ~400个时钟周期  ← 延迟更高!但带宽是普通内存的30倍
容量最大 ↓

重要发现: GPU高速专用内存(HBM)的延迟(400周期)比CPU主内存(200周期)还高!但它的带宽是普通内存的约30倍。

为什么GPU反而要用延迟更高的内存?

矩阵乘法需要同时处理几百万个数字,关键在于"一次能搬多少数据"(带宽),而不是"某一个数据多快到达"(延迟)。

类比:

  • CPU内存 = 快递专车:速度快,但一辆只送一个包裹
  • GPU内存 = 大型货轮:单趟等待时间长,但一次运几万个集装箱,整体货物流量惊人

六、分支处理:GPU的软肋

6.1 什么是"分支"?

程序里的if-else就是分支,根据条件走不同的执行路径。

6.2 CPU如何处理分支(非常擅长)

CPU有分支预测器:在条件还没判断出来之前,根据历史规律猜测"这次可能走哪条路",提前开始执行。

  • 猜对了:节省等待时间
  • 猜错了:丢弃结果重来

现代CPU分支预测准确率高达95%以上,大量if-else对CPU几乎没有影响。

6.3 GPU如何处理分支(很痛苦)

GPU的32个线程(一个Warp)必须步调一致,同一时刻只能执行同一条指令

当if-else让不同线程走不同路径时:

复制代码
Warp里32个线程遇到if-else:
线程 0~15:应该执行A路径
线程16~31:应该执行B路径

但32个线程只能统一行动!GPU的处理方式(很无奈):

第1步:所有线程执行A路径
       线程 0~15:正常执行A  [有效]
       线程16~31:被"屏蔽",空转  [浪费!]

第2步:所有线程执行B路径
       线程 0~15:被"屏蔽",空转  [浪费!]
       线程16~31:正常执行B  [有效]

效率减半!

这就是Warp Divergence(线程束分化)------原本步调一致的线程,因为if-else而"分道扬镳"。

结论:

  • CPU写满if-else的复杂逻辑 → 完全没问题
  • GPU写满if-else的复杂逻辑 → 性能大幅下降
  • 好的GPU程序要尽量让同一Warp里的线程"命运相同"

七、适用场景总结

CPU擅长

  • ✅ 复杂业务逻辑(大量判断、分支、递归调用)
  • ✅ 追求快速响应的任务(网页请求、键盘输入)
  • ✅ 操作系统、任务调度、文件读写
  • ✅ 不规则数据结构(链表、树)

GPU擅长

  • ✅ 矩阵乘法(深度学习核心运算)
  • ✅ 图像/视频处理(每个像素独立处理)
  • ✅ 科学模拟(流体动力学、气象预报)
  • ✅ 图形渲染(游戏画面)

八、深度学习为什么离不开GPU?

以矩阵乘法 C = A × B(1024×1024)为例:

复制代码
需要计算:1024 × 1024 × 1024 = 约10亿次乘加运算

CPU(8核,3GHz):
- 每核每周期约1次FMA(乘加)
- 理论峰值:3GHz × 8核 = 24 GFLOPS
- 耗时:约40毫秒

GPU(高端型号):
- 专用Tensor Core,每周期可完成多次小矩阵乘法
- 理论峰值:约1000 TFLOPS
- 耗时:约0.001毫秒
- 加速比:约40,000倍!

Tensor Core(张量核心):GPU专门为矩阵乘法设计的硬件单元,比普通计算核心快几十倍。


九、顿悟总结

CPU GPU
哲学 让一件事做得极快 让很多事同时做
核心 少而强 多而简
延迟 极力消除 用并发掩盖
分支 擅长(预测器) 怕(Warp分化)
内存 大缓存,低延迟 高带宽,HBM
编程 串行思维 数据并行思维
类比 瑞士军刀 流水线工厂

最终顿悟: GPU不是"更快的CPU",而是完全不同的计算范式 。当你的问题能被拆解成百万个相同的小问题时,GPU就是终极武器。深度学习训练的本质,就是把学习过程变成了这样一个"百万相同小问题"。

相关推荐
reset202111 小时前
GPU调试
gpu·pid
桃酥4033 天前
GPU架构 - 零基础入门
ai·gpu
d1z8883 天前
(十八)32天GPU测试从入门到精通-TensorRT-LLM 部署与优化day16
人工智能·python·深度学习·gpu·tensorrt
CodeCraft Studio4 天前
LightningChart .NET v12.5.1 发布:高性能数据可视化再升级,赋能工业与实时数据场景
信息可视化·.net·gpu·数据可视化·lightningchart·高性能图表开发·数据可视化引擎
坏孩子的诺亚方舟4 天前
RTL设计师攻略0_架构与微架构
架构·cpu·面试攻略
HyperAI超神经7 天前
【TVM教程】理解 Relax 抽象层
人工智能·深度学习·学习·机器学习·gpu·tvm·vllm
逻极7 天前
Windows平台Ollama AMD GPU编译全攻略:基于ROCm 6.2的实战指南(附构建脚本)
人工智能·windows·gpu·amd·ollama
CappuccinoRose8 天前
计算机系统体系结构及其组成 - 汇总篇
cpu·计算机体系结构·总线·计算机组成·指令系统·并行处理机·码制
avi91119 天前
万事课程:AMD CPU 结构 和虚拟化---入门讲解
cpu·amd·系统工程师