Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← 系统与高性能 / Systems & Performance

计算系统 / Computing Systems

1. 计算系统:计算机如何执行与加速程序

2. 从 C++ 源码到 CPU 执行

3. CPU 流水线、乱序执行与分支预测

4. Cache、一致性、伪共享与 NUMA

5. GPU、SM、Warp 与显存

6. 计算执行模型:程序怎样映射到机器

7. SIMD 与编译器向量化

8. C++ 多线程与 OpenMP

9. CUDA 平台与编程模型

10. CUDA Kernel、内存与性能

11. CPU-GPU 异构流水线

12. MPI 与分布式并行

13. 并行算法模式

14. 性能模型与工具

15. 递进学习项目:从单线程到集群

历史完整正文 / Original Deep Dives

1. 历史完整正文:统一前文章逐篇保留

原体系结构与硬件 / Original Architecture

1. 硬件编程与高性能计算:一张可走通的学习地图 / A Practical Learning Map for Hardware Programming and HPC

2. 计算机体系结构:CPU、内存与 GPU / Computer Architecture: CPUs, Memory, and GPUs

3. 计算机架构基础——为什么 GPU 比 CPU 更快 / Computer Architecture Fundamentals: Why GPUs Outperform CPUs

4. 并行计算理论——30 天训练能优化到多快? / Parallel Computing Theory and the Limits of Training Acceleration

5. GPU 架构深入——上万个核心如何分工协作 / GPU Architecture and Massive Parallel Execution

6. CUDA 编程模型——把矩阵乘法映射到 GPU / The CUDA Programming Model for Mapping Matrix Multiplication to GPUs

7. CUDA 内存管理——百亿参数如何装进显存 / CUDA Memory Management for Large Models

8. CUDA 性能优化——从 30 天缩短到 10 天 / CUDA Performance Optimization

9. CPU 并行编程——OpenMP 与 SIMD 向量化 / CPU Parallel Programming with OpenMP and SIMD

10. HPC 集群与 MPI——多节点分布式训练 / HPC Clusters and MPI for Distributed Training

11. 异构计算——CPU 与 GPU 如何协同工作 / Heterogeneous Computing with CPUs and GPUs

12. 深度学习训练优化实战——从 30 天到 3 天 / Deep Learning Training Optimization from Thirty Days to Three

13. 性能分析工具——找到真正的瓶颈 / Performance Analysis Tools for Finding Real Bottlenecks

14. NPU 全景——昇腾/寒武纪/TPU/苹果生态 / The NPU Landscape: Ascend, Cambricon, TPU, and Apple

15. 未来趋势——2030 年的计算机会是什么形态 / Future Computing Trends Toward 2030

16. 硬件与高性能计算:从“程序为什么慢”开始 / Hardware and HPC Starting from Why Programs Are Slow

原并行计算 / Original Parallel Computing

1. 并行计算:从 SIMD 到 MPI / Parallel Computing from SIMD to MPI

2. 并行计算全景:从晶体管、CPU、GPU 到计算集群 / Parallel Computing from Transistors, CPUs, and GPUs to Clusters

3. 并行计算基础:任务分解、加速比与可扩展性 / Parallel Computing Fundamentals: Decomposition, Speedup, and Scalability

4. 处理器体系结构:从指令流水线到多核芯片 / Processor Architecture from Instruction Pipelines to Multicore Chips

5. CPU 并行:多线程、SIMD、Cache 一致性与 NUMA / CPU Parallelism with Threads, SIMD, Cache Coherence, and NUMA

6. 内存层次:Cache、带宽、局部性与一致性 / Memory Hierarchies, Bandwidth, Locality, and Coherence

7. GPU 体系结构:SIMT、Warp、SM 与吞吐优先设计 / GPU Architecture with SIMT, Warps, and Streaming Multiprocessors

8. CUDA 编程模型:Thread、Block、Grid 与内存协作 / CUDA Threads, Blocks, Grids, and Cooperative Memory Access

9. 并行算法模式:Map、Reduce、Scan、Stencil 与任务图 / Parallel Patterns: Map, Reduce, Scan, Stencil, and Task Graphs

10. 异构计算:CPU、GPU、NPU 如何协同工作 / Heterogeneous Computing with CPUs, GPUs, and NPUs

11. 分布式并行:MPI、集合通信、RDMA 与多机多卡 / Distributed Parallelism with MPI, Collective Communication, and RDMA

12. 性能工程:测量、Roofline、瓶颈定位与优化闭环 / Performance Engineering with Measurement, Roofline, and Bottleneck Analysis

13. 并行计算实战:AI、CAE、图像与科学计算 / Parallel Computing for AI, CAE, Imaging, and Scientific Computing

14. 并行计算实践路线:从单核优化到多机多卡 / A Parallel Computing Project Path from Single-Core to Multi-Node GPUs

本页目录

GPU 架构深入——上万个核心如何分工协作 / GPU Architecture and Massive Parallel Execution ​

📅 创建时间:2026-06-02 🏷️ 标签:#GPU #CUDA #StreamMultiprocessor #Warp #HBM #TensorCore 📚 前置知识:[[01-computer-architecture-basics]](CPU 架构) [[02-parallel-computing-theory]](并行理论) 📚 相关知识:[[04-cuda-programming-model]](CUDA 编程) [[05-cuda-kernel-and-memory]](内存管理)


先抓住直觉 ​

不要把一个 CUDA Core 当成一个 CPU Core。GPU 的优势来自大量轻量执行单元按组完成相似工作,并在一组线程等待数据时切换到另一组。理解顺序应是 Thread → Warp → Block → SM → 整张 GPU,不必先背芯片框图。

  • 必须理解:Warp 是调度单位;同一 Warp 走不同分支会串行化;GPU 用并发隐藏访存延迟。
  • 用到再查:A100 的核心数、GPC/TPC 数量、各级缓存容量。
  • 读完能回答:为什么 GPU 可以容忍较高延迟?为什么分支很多的任务可能不适合 GPU?

场景:GPU 的 6912 个核心,到底长什么样? ​

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  A100 GPU:6912 个 CUDA 核心                               │
│                                                             │
│  你可能听说过这个数字,但大脑无法直观理解:                  │
│                                                             │
│  6912 是什么概念?                                        │
│  - 普通 CPU:8-64 核                                      │
│  - A100:6912 核                                          │
│  - 差距:100 倍!                                          │
│                                                             │
│  但这 6912 个核心不是杂乱排列的。                          │
│  它们有严格的组织结构:SM → Warp → Thread。               │
│  理解这个结构,是写好 CUDA 代码的第一步。                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

第1节:GPU 架构全景图 ​

A100 完整架构 ​

┌─────────────────────────────────────────────────────────────┐
│                     A100 GPU 完整架构                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                    ┌─────────────────────┐                │
│                    │       A100 GPU      │                │
│                    │    (GA100 核心)     │                │
│                    └──────────┬──────────┘                │
│                               │                              │
│         ┌──────────┬─────────┼─────────┬──────────┐     │
│         │          │         │         │          │        │
│    ┌────┴───┐ ┌────┴───┐ ┌────┴───┐ ┌────┴───┐       │
│    │  GPC 0  │ │  GPC 1  │ │  GPC 2  │ │ GPC 3-7 │   │
│    │(图形处理)│ │(图形处理)│ │(图形处理)│ │ (×5)   │   │
│    │ ×4 个   │ │  ×4 个  │ │  ×4 个  │ │         │   │
│    └────┬────┘ └────┬────┘ └────┬────┘ └────────┘       │
│         │            │            │                        │
│     ┌───┴───┐    ┌───┴───┐    ┌───┴───┐              │
│     │  TPC 0  │    │  TPC 0  │    │  TPC 0  │         │
│     │(纹理处理)│    │(纹理处理)│    │(纹理处理)│         │
│     └────┬────┘ └────┬────┘ └────┬────┘              │
│          │            │            │                       │
│      ┌───┴───┐    ┌───┴───┐    ┌───┴───┐            │
│      │  SM 0  │    │  SM 0  │    │  SM 0  │            │
│      │  SM 1  │    │  SM 1  │    │  SM 1  │            │
│      │  ...   │    │  ...   │    │  ...   │            │
│      │  SM 15 │    │  SM 15 │    │  SM 15 │            │
│      └────────┘    └────────┘    └────────┘              │
│                                                             │
│  ┌───────────────────────────────────────────────────────┐ │
│  │                    HBM2e 显存                          │ │
│  │              40GB / 80GB,带宽 2 TB/s                  │ │
│  └───────────────────────────────────────────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘

GPC = Graphics Processing Cluster(图形处理簇)    × 7 个
TPC = Texture Processing Cluster(纹理处理簇)     × 16 个
SM  = Streaming Multiprocessor(流式多处理器)    × 108 个(实际 108 SM)
HBM = High Bandwidth Memory(高带宽显存)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

A100 规格一览 ​

┌─────────────────────────────────────────────────────────────┐
│                    A100 vs 其他 GPU 规格对比                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  规格             │  A100 SXM     │  H100 SXM    │ RTX3090│
│  ────────────────┼───────────────┼──────────────┼────────┤
│  CUDA 核心        │  6912         │  16896       │ 10496 │
│  SM 数量         │  108          │  132         │  82   │
│  Tensor Core     │  432          │  528         │  328  │
│  显存容量        │  40/80 GB     │  80 GB       │  24 GB│
│  显存带宽        │  2.0 TB/s     │  3.35 TB/s  │ 936 GB/s│
│  FP32 算力       │  19.5 TFLOPS  │  67 TFLOPS  │  36 TFLOPS│
│  Tensor FP16     │  312 TFLOPS   │  989 TFLOPS  │  71 TFLOPS│
│  功耗            │  400W         │  700W        │  350W  │
│  NVLink 带宽     │  600 GB/s     │  900 GB/s   │  N/A   │
│                                                             │
│  价格(参考)    │  ~10 万人民币 │  ~25 万人民币│ ~1.5万 │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

第2节:SM——GPU 的基本执行单元 ​

SM 内部结构(以 A100 为例) ​

┌─────────────────────────────────────────────────────────────┐
│                    流式多处理器(SM)内部结构                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                    ┌─────────────────┐                      │
│                    │   Warp Scheduler │  ← 调度器,每个 SM ×4 │
│                    └────────┬────────┘                      │
│                             │                                │
│   ┌─────────────────────────┼─────────────────────────────┐ │
│   │                  算术单元阵列                           │ │
│   │                                                      │ │
│   │  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐        │ │
│   │  │INT32 │  │INT32 │  │ FP32 │  │ FP32 │        │ │
│   │  │ ALU  │  │ ALU  │  │ FMA  │  │ FMA  │        │ │
│   │  └──────┘  └──────┘  └──────┘  └──────┘        │ │
│   │  ×16 个                                         │ │
│   │                                                      │ │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐        │ │
│   │  │TensorCore│  │TensorCore│  │TensorCore│        │ │
│   │  │ (矩阵乘) │  │ (矩阵乘) │  │ (矩阵乘) │        │ │
│   │  └──────────┘  └──────────┘  └──────────┘        │ │
│   │  ×4 个(每个 Tensor Core 每时钟执行 256 FLOP)     │ │
│   │                                                      │ │
│   │  ┌──────────┐  ┌──────────┐                      │ │
│   │  │  LD/ST   │  │  LD/ST   │  ← 加载/存储单元     │ │
│   │  │  Unit    │  │  Unit    │    ×16 个           │ │
│   │  └──────────┘  └──────────┘                      │ │
│   │                                                      │ │
│   └─────────────────────────┬───────────────────────────┘ │
│                             │                               │
│   ┌─────────────────────────┼───────────────────────────┐ │
│   │                  存储单元                             │ │
│   │                                                      │ │
│   │  ┌──────────────┐  ┌──────────────┐                │ │
│   │  │  L1/Shared  │  │   Registers  │                │ │
│   │  │   Memory    │  │  (65536 ×   │                │ │
│   │  │  128 KB     │  │   32-bit)   │                │ │
│   │  └──────────────┘  │  = 256 KB   │                │ │
│   │                    └──────────────┘                │ │
│   │                                                      │ │
│   │  ┌──────────────┐  ┌──────────────┐                │ │
│   │  │   L1 Cache   │  │  L2 Cache   │                │ │
│   │  │   (per SM)   │  │  (per GPU)   │                │ │
│   │  └──────────────┘  │  40 MB      │                │ │
│   │                    └──────────────┘                │ │
│   │                                                      │ │
│   └──────────────────────────────────────────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

每个 SM 的关键数字 ​

┌─────────────────────────────────────────────────────────────┐
│                    A100 每个 SM 的资源                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  寄存器文件:65536 × 32-bit = 256 KB(65536 个寄存器)      │
│  每个线程最多使用 255 个寄存器                              │
│  每个 SM 最多同时运行 2048 个线程(= 64 Warp × 32 线程)   │
│                                                             │
│  L1/Shared Memory:128 KB(可配置比例)                    │
│  - Shared Memory:用户显式管理的片上存储                    │
│  - L1 Cache:自动缓存                                      │
│  - 比例可调:0/8/16/32/64/128 KB                         │
│                                                             │
│  Warp Scheduler:4 个                                      │
│  每个 Scheduler 每时钟周期可以发射一条指令                   │
│                                                             │
│  计算单元:                                                 │
│  - INT32 ALU × 16(通用计算)                              │
│  - FP32 FMA × 16(浮点乘加)                              │
│  - LD/ST Unit × 16(内存访问)                             │
│  - Tensor Core × 4(矩阵乘法加速)                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

第3节:Warp——GPU 的基本调度单位 ​

什么是 Warp? ​

┌─────────────────────────────────────────────────────────────┐
│                    Warp:GPU 的"班级"                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Warp = 32 个线程为一组,一起执行同一条指令                 │
│                                                             │
│  想象一个班级(32 人):                                    │
│  - 老师(Warp Scheduler)发一条指令:"站起来"              │
│  - 32 个学生同时站起来(32 个线程同时执行同一指令)          │
│  - 完美并行!                                               │
│                                                             │
│  这就是 SIMT(Single Instruction Multiple Thread):          │
│  单指令,多线程                                            │
│                                                             │
│  为什么是 32?                                             │
│  - 硬件设计权衡:太多线程调度开销大,太少并行度不够          │
│  - 32 是一个经验最优值                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Warp 的执行模型 ​

┌─────────────────────────────────────────────────────────────┐
│                    Warp 执行流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  时间 →                                                    │
│                                                             │
│  Clock 1: Warp Scheduler 选择一个 Warp                    │
│           ↓                                                 │
│           Warp Scheduler 发射指令到执行单元                  │
│           ↓                                                 │
│           32 个线程同时执行同一条 FP32 指令                  │
│           ↓                                                 │
│           16 × 2 = 32 FLOP(一次发射完成)                │
│                                                             │
│  Clock 2: 下一个 Warp 被调度                                │
│           ...                                               │
│                                                             │
│  关键:每个时钟周期,Warp Scheduler 可以发射一条指令         │
│  4 个 Scheduler × 每周期 1 条 = 每周期 4 条指令            │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Warp 分支分化(Branch Divergence)——性能杀手 ​

┌─────────────────────────────────────────────────────────────┐
│                    Warp 分支分化                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  场景:32 个线程执行 if-else                               │
│                                                             │
│  if (threadIdx.x < 16) {     ← 前16个线程走这里          │
│      a = b + c;                                           │
│  } else {                   ← 后16个线程走这里              │
│      a = b - c;                                           │
│  }                                                        │
│                                                             │
│  问题:Warp 中 32 个线程必须执行同一条指令                  │
│                                                             │
│  Clock 1: 执行 if 分支 → 只前16个线程干活,后16个等        │
│  Clock 2: 执行 else 分支 → 后16个线程干活,前16个等        │
│                                                             │
│  效果:2 个时钟周期完成 1 个 if-else                        │
│       = 效率降为 50%!                                     │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │  理想:32 线程同时执行 = 100% 效率                   │  │
│  │  分支分化:只有 16 线程同时工作 = 50% 效率           │  │
│  │                                                       │  │
│  │  教训:GPU 代码中尽量避免 Warp 内的分支分化            │  │
│  │  如果无法避免,让分支的线程数量是 32 的倍数           │  │
│  └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

数值例子 ​

┌─────────────────────────────────────────────────────────────┐
│                分支分化导致的性能损失                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  场景:判断一个数是正数还是负数                             │
│                                                             │
│  // ❌ 差:每个线程都可能走不同分支                         │
│  if (x > 0) { sum += sqrt(x); }                          │
│  else { sum += x * x; }                                   │
│                                                             │
│  // ✅ 好:强制所有线程走同一分支(通过 blockIdx 分组)     │
│  if (blockIdx.x == 0) {                                  │
│      // 所有 blockIdx==0 的线程走这里                       │
│      sum += sqrt(x);                                       │
│  } else {                                                 │
│      sum += x * x;                                         │
│  }                                                        │
│                                                             │
│  // ✅ 更好:完全没有分支                                   │
│  // 用 step 函数替代 if-else                               │
│  int branch = (x > 0);  // 0 或 1                        │
│  sum += branch * sqrt(x) + (1 - branch) * x * x;         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

第4节:GPU 内存层次——为什么 HBM 带宽是关键 ​

GPU 内存与 CPU 内存的对比 ​

┌─────────────────────────────────────────────────────────────┐
│                    GPU vs CPU 内存对比                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  CPU 内存(DDR4/DDR5):                                  │
│  ┌──────────────────────────────────────────────────────┐ │
│  │  容量:256 GB    带宽:~200 GB/s    延迟:~100ns   │ │
│  │                                                      │ │
│  │  特点:容量大,延迟低,适合随机访问                   │ │
│  │  但带宽有限,多核同时访问容易成为瓶颈                  │ │
│  └──────────────────────────────────────────────────────┘ │
│                                                             │
│  GPU 显存(HBM2e):                                       │
│  ┌──────────────────────────────────────────────────────┐ │
│  │  容量:40-80 GB   带宽:2.0 TB/s    延迟:~500ns   │ │
│  │                                                      │ │
│  │  特点:带宽极高(CPU 的 10 倍!),但延迟高          │ │
│  │  适合顺序的大块数据访问(矩阵乘法、卷积)             │ │
│  └──────────────────────────────────────────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

GPU 内存层次详解 ​

┌─────────────────────────────────────────────────────────────┐
│                    GPU 内存层次(由快到慢)                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  L1 Cache (per SM)        128 KB     ~1 ns    ↑ 最快       │
│  Shared Memory (per SM)   128 KB     ~1 ns    (可编程)   │
│  L2 Cache (per GPU)       40 MB      ~30 ns                 │
│  Global Memory (HBM2e)    40-80 GB   ~500 ns  ↓ 最慢       │
│                                                             │
│  带宽对比(GB/s):                                         │
│  L1 Cache:        ~10,000 GB/s                              │
│  Shared Memory:   ~10,000 GB/s                              │
│  L2 Cache:         ~3,500 GB/s                              │
│  Global Memory:      2,000 GB/s                            │
│                                                             │
│  容量对比:                                                  │
│  Register:      256 KB(per SM)← 每个线程的"寄存器"        │
│  L1 Cache:      128 KB(per SM)← 自动缓存                  │
│  L2 Cache:       40 MB(per GPU)← 自动缓存,全 SM 共享     │
│  Global Memory:  40 GB(per GPU)← HBM 显存                │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

为什么 GPU 延迟高但仍然快? ​

CPU 的策略:低延迟
  - 优化单次访问的响应时间
  - 用复杂的分支预测和超线程隐藏延迟
  - 适合分支密集、不可预测的程序

GPU 的策略:高带宽 + 大规模并行隐藏延迟
  - 一次发起 thousands 个内存请求
  - Warp A 在等内存时,调度器切到 Warp B 执行
  - 通过"切换"而不是"等待"来隐藏延迟

┌─────────────────────────────────────────────────────────────┐
│                    延迟隐藏技术                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  GPU 有 108 个 SM,每个 SM 同时跑多个 Warp:               │
│                                                             │
│  A100 每个 SM:2048 个线程 / 32 = 64 个 Warp             │
│  A100 总共:108 × 64 = 6912 个 Warp 同时可调度            │
│                                                             │
│  当 Warp 0 等待内存:                                      │
│    → 调度器立刻切到 Warp 1 执行                            │
│    → Warp 1 等待内存时,切到 Warp 2                        │
│    → ...                                                   │
│    → 永远不闲着!                                          │
│                                                             │
│  这就是 GPU 能容忍高延迟的原因:                            │
│  足够多的线程 → 永远有其他线程可执行                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

第5节:Tensor Core——矩阵乘法的专用硬件 ​

为什么需要 Tensor Core? ​

传统 CUDA 核心(FP32 FMA)做矩阵乘法:
  - 每个 SM 有 16 个 FP32 单元
  - 每个单元每个时钟执行 1 次乘加 = 2 FLOP
  - 每 SM 每时钟:16 × 2 = 32 FLOP
  - A100 108 SM:108 × 32 = 3456 FLOP/时钟
  - A100 主频 ~1.41 GHz
  - 总算力:3456 × 1.41G ≈ 4.87 TFLOPS(FP32)

Tensor Core 做矩阵乘法:
  - 每个 SM 有 4 个 Tensor Core
  - 每个 Tensor Core 每个时钟执行 256 FLOP(FP16 矩阵乘)
  - 每 SM 每时钟:4 × 256 = 1024 FLOP
  - A100 108 SM:108 × 1024 = 110,592 FLOP/时钟
  - 总算力:110592 × 1.41G ≈ 156 TFLOPS(FP16 Tensor)

Tensor Core 比传统 CUDA 核心快约 32 倍!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Tensor Core 工作原理 ​

┌─────────────────────────────────────────────────────────────┐
│                Tensor Core: D = A × B + C                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入:                                                    │
│    A: M×K 矩阵   B: K×N 矩阵   C: M×N 矩阵(累加)        │
│  输出:                                                    │
│    D: M×N 矩阵   = A × B + C                              │
│                                                             │
│  A100 Tensor Core 支持的形状:                             │
│    - 16×16×16(FMA 模式)                                │
│    - 8×16×16(FP16)                                     │
│    - 4×8×16(INT8)                                      │
│    - 1×4×16(INT4)                                      │
│                                                             │
│  以 16×16×16 为例:                                       │
│    - 一次做 16×16 = 256 个输出元素                        │
│    - 每个输出 = 16 次乘 + 15 次加 = 16 FMA                │
│    - 总计 4096 FLOP                                       │
│    - 由 4 个 Tensor Core + 16 个 FP32 单元协同完成          │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Tensor Core 编程方式 ​

cpp
// CUDA 中使用 Tensor Core 的方式

// 方式 1:cuBLAS 库(最简单,推荐)
#include <cublas_v2.h>

cublasHandle_t handle;
cublasCreate(&handle);

// 调用矩阵乘法,自动使用 Tensor Core
// A: M×K, B: K×N, C: M×N
cublasGemmEx(handle,
    CUBLAS_OP_N, CUBLAS_OP_N,  // 不转置
    M, N, K,                     // 矩阵维度
    &alpha,                       // 缩放因子
    A, CUDA_R_16F, M,            // A 矩阵
    B, CUDA_R_16F, K,            // B 矩阵
    &beta,                        // 累加因子
    C, CUDA_R_16F, M,            // C 矩阵
    CUDA_R_16F,                   // 计算精度
    CUBLAS_GEMM_DEFAULT_TENSOR_OP);  // 启用 Tensor Core

// 方式 2:WMMA API(直接操作 Tensor Core)
#include <mma.h>

using namespace nvcuda::wmma;

// 声明矩阵片段
fragment<matrix_a, ...> a_frag;
fragment<matrix_b, ...> b_frag;
fragment<accumulator, ...> c_frag;

// 加载矩阵到片段
load_matrix_sync(a_frag, A, K);
load_matrix_sync(b_frag, B, N);

// 执行矩阵乘法
mma_sync(c_frag, a_frag, b_frag, c_frag);

// 存储结果
store_matrix_sync(C, c_frag, N, mem_layout::row_major);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

第6节:显存带宽的实际影响 ​

矩阵乘法的带宽分析 ​

┌─────────────────────────────────────────────────────────────┐
│                矩阵乘法 C = A × B 的带宽需求                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  A: M×K, B: K×N, C: M×N                                   │
│                                                             │
│  数据量:                                                   │
│    读取 A: M×K × 2 字节(FP16)                          │
│    读取 B: K×N × 2 字节(FP16)                          │
│    写入 C: M×N × 2 字节(FP16)                          │
│    总计:2×(M×K + K×N) + M×N × 2 ≈ 2×(M×K + K×N)         │
│                                                             │
│  计算量:                                                   │
│    M×N × K 次乘加 = 2×M×N×K FLOP(FP16)                  │
│                                                             │
│  算力需求(FLOP vs 带宽):                                 │
│    Roofline Model: 最大 FLOP = min(算力上限, 带宽 × 算术强度)│
│                                                             │
│    算术强度 = 计算量 / 数据量                               │
│            = 2×M×N×K / (2×M×K + 2×K×N)                   │
│            ≈ MNK / (MK + KN)                               │
│            = K / (1 + K/N + K/M)                          │
│                                                             │
│    当 K >> M 且 K >> N 时(典型深度学习场景):             │
│    算术强度 ≈ K(非常大!)                                │
│    → 带宽充足时,Tensor Core 可以跑满                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

Roofline 模型 ​

┌─────────────────────────────────────────────────────────────┐
│                    Roofline 性能模型                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  性能 (TFLOPS)                                             │
│      ↑                                                     │
│  312 ┤                                          ★ A100     │
│      │                                         /           │
│  156 ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  Tensor Core│
│      │                                        /│ FP16      │
│   20 ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│      │                                     /               │
│   10 ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│      │                                  /│ FP32           │
│    5 ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│      │                               /                     │
│    0 ┼──────────────────────────────────────────────────→  │
│         0      200     500    1000    2000    算术强度      │
│                    (FLOP/Byte)                             │
│                                                             │
│  关键点:                                                   │
│  - 算术强度 < 312 时,性能受限于带宽(A100 HBM)           │
│  - 算术强度 > 312 时,性能受限于算力                        │
│  - 矩阵乘法算术强度很大 → 受限于算力                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

升华:GPU 架构的核心记忆点 ​

┌─────────────────────────────────────────────────────────────┐
│                    GPU 架构速记卡                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  A100:6912 CUDA 核心 = 108 SM × 64 线程/SM               │
│                                                             │
│  调度层次:                                                 │
│  Grid → Block → Warp → Thread                             │
│  (整体)  (SM)   (32线程) (最小单元)                        │
│                                                             │
│  执行模型:                                                 │
│  - SIMT:单指令多线程                                      │
│  - Warp:32 线程为一组,同步执行                           │
│  - 分支分化 = 效率损失                                     │
│                                                             │
│  内存层次(由快到慢):                                     │
│  Register → L1/Shared → L2 → Global Memory (HBM)          │
│                                                             │
│  Tensor Core:                                             │
│  - 比 CUDA 核心快 32 倍                                    │
│  - 专门做矩阵乘法 D = A×B+C                               │
│  - 深度学习训练的加速核心                                   │
│                                                             │
│  延迟隐藏:                                                 │
│  6912 个 Warp 随时可调度,永远不闲着                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

"AI 可查 vs 必须理解"清单 ​

AI 可查:
✅ A100/H100 的具体核心数、频率、带宽——官网规格表
✅ Tensor Core 支持的具体精度(FP16/BF16/INT8/INT4)
✅ cuBLAS/cuDNN 的具体 API 参数

必须理解:
🔴 SM × Warp × Thread 的三层调度结构
🔴 Warp = 32 线程,同步执行,分支分化 = 效率损失
🔴 GPU 内存层次:Register < L1/Shared < L2 < Global Memory
🔴 为什么 HBM 带宽 2 TB/s 是关键指标
🔴 Tensor Core 比 CUDA 核心快 32 倍,是矩阵乘法的专用硬件
🔴 GPU 用大量 Warp 隐藏内存延迟
1
2
3
4
5
6
7
8
9
10
11
12

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇4. 并行计算理论——30 天训练能优化到多快? / Parallel Computing Theory and the Limits of Training Acceleration
下一篇6. CUDA 编程模型——把矩阵乘法映射到 GPU / The CUDA Programming Model for Mapping Matrix Multiplication to GPUs

持续记录,持续成长

Copyright © Tidenflow