第1节:现代GPU硬件架构精讲

文章目录

前言

不懂硬件,写不出高性能CUDA代码

很多初学者学CUDA,上来就写核函数,结果发现:同样的算法,别人比我快10倍,还不知道为什么。

原因很简单:你不了解GPU这个"合作伙伴"的脾气秉性。

就像你要用好一个人,得知道他是急性子还是慢性子、擅长数学还是语文。GPU也一样------它的架构设计,直接决定了什么样的代码跑得快,什么样的代码跑得慢。

今天,我们就从硬件层面,彻底搞懂现代GPU的工作原理。

一、GPU vs CPU:为什么GPU适合并行计算?

先看一张经典的对比图:

CPU GPU
少数强大核心 数千个简单核心
复杂控制单元 简单控制单元
大容量缓存 小容量缓存
适合串行任务 适合并行任务

一句话总结:

  • CPU是博士:一个顶十个,擅长处理复杂问题
  • GPU是小学生:单个能力弱,但一万人一起上,干活比博士快

这就是所谓的延迟优化 vs 吞吐优化

二、GPU的整体架构:从芯片到核心

2.1 GPU的层级结构

现代GPU是一个复杂的多层结构:

层级说明:

  • GPC(图形处理簇):GPU的最高层级划分,每个GPC包含多个TPC
  • TPC(纹理处理簇):每个TPC包含1-2个SM
  • SM(流式多处理器):最核心的计算单元,我们编程直接打交道的对象

2.2 A100/H100芯片架构图

以NVIDIA A100(Ampere架构)为例:

A100关键数据:

  • 108个SM
  • 40MB L2缓存
  • 40/80GB HBM2显存
  • 1.6TB/s显存带宽

三、SM内部架构详解

3.1 SM(流式多处理器)内部结构

SM是GPU最核心的计算单元,我们直接看它的内部构造:

3.2 一个SM的详细数据(以A100为例)

组件 数量 说明
Warp调度器 4个 每个时钟周期可调度2条指令
CUDA Core (FP32) 64个 单精度浮点运算
CUDA Core (INT32) 64个 整数运算
FP64 Core 32个 双精度浮点运算(部分型号减半)
Tensor Core 4个 第四代Tensor Core
寄存器文件 256KB 65536个32位寄存器
共享内存/L1 164KB 可配置为共享内存或L1缓存
最大线程数 2048个 同时驻留的线程数
最大Warp数 64个 同时驻留的warp数
最大线程块数 32个 同时驻留的block数

四、Warp:最小的执行单元

4.1 Warp的内部结构

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                     一个Warp(32个线程)                           │
│                                                                   │
│  线程ID: 0   1   2   3   4   5   6   7   8   9  10  11  12  13  │
│  ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐
│  │T0 ││T1 ││T2 ││T3 ││T4 ││T5 ││T6 ││T7 ││T8 ││T9 ││T10││T11││T12││T13│
│  └───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘
│                                                                   │
│ 线程ID:14  15  16  17  18  19  20  21  22  23  24  25  26  27   │
│  ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐
│  │T14││T15││T16││T17││T18││T19││T20││T21││T22││T23││T24││T25││T26││T27│
│  └───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘└───┘
│                                                                   │
│ 线程ID:28  29  30  31                                            │
│  ┌───┐┌───┐┌───┐┌───┐                                           │
│  │T28││T29││T30││T31│                                           │
│  └───┘└───┘└───┘└───┘                                           │
│                                                                   │
│  所有线程执行同一条指令:                                          │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  instruction:  a = b + c                                 │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│  但每个线程操作不同的数据:                                        │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  T0: a0 = b0 + c0                                        │   │
│  │  T1: a1 = b1 + c1                                        │   │
│  │  ...                                                      │   │
│  │  T31: a31 = b31 + c31                                    │   │
│  └──────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────┘

4.2 Warp的执行过程

复制代码
时间轴 →
┌──────────────────────────────────────────────────────────────────┐
│                                                                   │
│  Warp调度器每次选择一个Warp执行一条指令:                          │
│                                                                   │
│  ┌────────────┐                                                   │
│  │ Warp 0     │ ──→ 指令1 (a=b+c)                                │
│  └────────────┘                                                   │
│       ↓                                                           │
│  ┌────────────┐                                                   │
│  │ Warp 1     │ ──→ 指令1 (a=b+c)                                │
│  └────────────┘                                                   │
│       ↓                                                           │
│  ┌────────────┐                                                   │
│  │ Warp 2     │ ──→ 指令1 (a=b+c)                                │
│  └────────────┘                                                   │
│       ↓                                                           │
│  ┌────────────┐                                                   │
│  │ Warp 0     │ ──→ 指令2 (d=a*e)   ← 第一个Warp回来了            │
│  └────────────┘                                                   │
│                                                                   │
│  如果Warp 0在等待数据(比如访存):                                │
│  ┌────────────┐                                                   │
│  │ Warp 0     │ ──→ 访存指令 (load)                              │
│  └────────────┘                                                   │
│       ↓  (等待数据)                                                │
│  ┌────────────┐                                                   │
│  │ Warp 3     │ ──→ 执行计算 (不用等)   ← 零开销切换               │
│  └────────────┘                                                   │
│       ↓                                                           │
│  ┌────────────┐                                                   │
│  │ Warp 4     │ ──→ 执行计算                                     │
│  └────────────┘                                                   │
│       ↓                                                           │
│  ┌────────────┐                                                   │
│  │ Warp 0     │ ──→ 数据回来了,继续执行下一指令                  │
│  └────────────┘                                                   │
│                                                                   │
└──────────────────────────────────────────────────────────────────┘

五、计算核心的进化:CUDA Core → Tensor Core

5.1 CUDA Core vs Tensor Core 对比图

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                    CUDA Core (标量单元)                           │
│                                                                   │
│  一次做一个运算:                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  a = b * c + d                                            │   │
│  │                                                            │   │
│  │      b ──┐                                                │   │
│  │          ├─→ [MUL] ──→ [ADD] ──→ a                        │   │
│  │      c ──┘          ↑                                      │   │
│  │                     │                                      │   │
│  │      d ─────────────┘                                      │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│                    Tensor Core (矩阵单元)                         │
│                                                                   │
│  一次做一个4×4矩阵乘加:                                           │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  D = A × B + C                                            │   │
│  │                                                            │   │
│  │      ┌─────────┐                                          │   │
│  │      │ A (4x4) │                                          │   │
│  │      └─────────┘                                          │   │
│  │           ×                                                │   │
│  │      ┌─────────┐                                          │   │
│  │      │ B (4x4) │                                          │   │
│  │      └─────────┘                                          │   │
│  │           =                                                │   │
│  │      ┌─────────┐    ┌─────────┐                           │   │
│  │      │ A×B     │ +  │ C (4x4) │  =  D (4x4)               │   │
│  │      │ (4x4)   │    └─────────┘                           │   │
│  │      └─────────┘                                           │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│  一次Tensor Core运算 = 64次CUDA Core运算                          │
└──────────────────────────────────────────────────────────────────┘

5.2 各代Tensor Core演进

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                   Tensor Core 代际演进                            │
├──────────────────────────────────────────────────────────────────┤
│                                                                   │
│  Volta (V100, 2017) ──────────────────┐                          │
│  ┌──────────────────────────────────┐│                          │
│  │ 支持:FP16输入,FP32累加          ││                          │
│  │ 性能:125 TFLOPS (FP16)          ││                          │
│  └──────────────────────────────────┘│                          │
│                    ↓                  │                          │
│  Turing (T4, 2018) ─────────────────┐│                          │
│  ┌──────────────────────────────────┐││                          │
│  │ 新增:INT8、INT4量化支持          │││                          │
│  │ 性能:65 TFLOPS (FP16)           │↓│                          │
│  │       130 TOPS (INT8)            │ │                          │
│  └──────────────────────────────────┘ │                          │
│                    ↓                  │                          │
│  Ampere (A100, 2020) ───────────────┐│                          │
│  ┌──────────────────────────────────┐││                          │
│  │ 新增:BF16、TF32、结构化稀疏       │││                          │
│  │ 性能:312 TFLOPS (FP16)          │↓│                          │
│  │       624 TOPS (稀疏)            │ │                          │
│  └──────────────────────────────────┘ │                          │
│                    ↓                  │                          │
│  Hopper (H100, 2022) ───────────────┐│                          │
│  ┌──────────────────────────────────┐││                          │
│  │ 新增:FP8、Transformer引擎        │││                          │
│  │ 性能:1979 TFLOPS (FP8)          │↓│                          │
│  │       3958 TOPS (稀疏)           │ │                          │
│  └──────────────────────────────────┘ │                          │
│                    ↓                  │                          │
│  Blackwell (B200, 2024) ────────────┘                          │
│  ┌──────────────────────────────────┐                           │
│  │ 新增:FP4、第二代Transformer引擎   │                           │
│  │ 性能:4500 TFLOPS (FP8)          │                           │
│  │       9000 TOPS (稀疏)           │                           │
│  └──────────────────────────────────┘                           │
│                                                                   │
└──────────────────────────────────────────────────────────────────┘

六、内存层次结构

6.1 GPU内存层次图

复制代码
                     速度 (周期)                   容量 (每SM)
                         ↓                            ↓
                
    寄存器      ┌─────────┐                        ┌─────────┐
    <1周期     │         │  最快                   │ ~20KB   │  最小
               └─────────┘                        └─────────┘
                    ↓                                  ↓
                
  共享内存/L1   ┌─────────┐                        ┌─────────┐
   ~30周期     │         │                        │164KB    │
               └─────────┘                        └─────────┘
                    ↓                                  ↓
                
   只读常量缓存 ┌─────────┐                        ┌─────────┐
    ~30周期    │         │                        │ ~50KB   │
               └─────────┘                        └─────────┘
                    ↓                                  ↓
                
    纹理缓存   ┌─────────┐                        ┌─────────┐
    ~100周期   │         │                        │ ~50KB   │
               └─────────┘                        └─────────┘
                    ↓                                  ↓
                
     L2缓存    ┌─────────┐                        ┌─────────┐
    ~200周期   │         │                        │ 40MB    │  (全局)
               └─────────┘                        │ (A100)  │
                    ↓                                  ↓
                
   全局内存    ┌─────────┐                        ┌─────────┐
    ~400周期   │         │  最慢                   │40-80GB  │  最大
               └─────────┘                        └─────────┘


  速度差异:寄存器 : 共享内存 : 全局内存 ≈ 1 : 30 : 400

七、从硬件到软件的映射

7.1 CUDA线程层次与硬件映射

复制代码
┌──────────────────────────────────────────────────────────────────┐
│              CUDA软件概念 → GPU硬件映射                            │
├──────────────────────────────────────────────────────────────────┤
│                                                                   │
│  软件概念层:                                                      │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  Grid (网格)                                               │   │
│  │  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐                    │   │
│  │  │Block0│ │Block1│ │Block2│ │Block3│    ......          │   │
│  │  └──────┘ └──────┘ └──────┘ └──────┘                    │   │
│  └──────────────────────────────────────────────────────────┘   │
│                            ↓                                      │
│                            ↓  (由GigaThread引擎分发)              │
│                            ↓                                      │
│  硬件层:                                                         │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  GPU芯片                                                   │   │
│  │  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐            │   │
│  │  │  SM0   │ │  SM1   │ │  SM2   │ │  SM3   │   ......   │   │
│  │  └────────┘ └────────┘ └────────┘ └────────┘            │   │
│  └──────────────────────────────────────────────────────────┘   │
│                            ↓                                      │
│                            ↓  (Block分配到SM)                     │
│                            ↓                                      │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  SM内部                                                    │   │
│  │  ┌────────────────────────────────────────────────────┐   │   │
│  │  │  Block分配到SM后,切分成Warp执行:                   │   │   │
│  │  │                                                      │   │   │
│  │  │  Warp 0: 线程 0-31   ──→ 调度到CUDA Core执行        │   │   │
│  │  │  Warp 1: 线程32-63   ──→ 调度到CUDA Core执行        │   │   │
│  │  │  Warp 2: 线程64-95   ──→ 调度到CUDA Core执行        │   │   │
│  │  │  Warp 3: 线程96-127  ──→ 调度到CUDA Core执行        │   │   │
│  │  │  ...                                                │   │   │
│  │  └────────────────────────────────────────────────────┘   │   │
│  └──────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────┘

7.2 硬件资源限制示意图

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                    SM资源限制示意图                                │
├──────────────────────────────────────────────────────────────────┤
│                                                                   │
│  一个SM最多能同时容纳:                                           │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  2048个线程  =  64个Warp × 32线程                         │   │
│  └──────────────────────────────────────────────────────────┘   │
│                            ↓                                      │
│  但实际受限于:                                                   │
│                                                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  寄存器限制                                                 │   │
│  │  ┌────────────────────────────────────────────────────┐   │   │
│  │  │  寄存器总数: 65536                                   │   │   │
│  │  │  每个线程用32寄存器 → 2048线程 ✅                     │   │   │
│  │  │  每个线程用64寄存器 → 1024线程 ❌                     │   │   │
│  │  │  每个线程用128寄存器 → 512线程 ❌                     │   │   │
│  │  └────────────────────────────────────────────────────┘   │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  共享内存限制                                               │   │
│  │  ┌────────────────────────────────────────────────────┐   │   │
│  │  │  共享内存总数: 164KB                                 │   │   │
│  │  │  每个Block用16KB → 10个Block (164÷16≈10) ❌          │   │   │
│  │  │  每个Block用32KB → 5个Block  (164÷32≈5)  ❌          │   │   │
│  │  │  每个Block用48KB → 3个Block  (164÷48≈3)  ❌          │   │   │
│  │  └────────────────────────────────────────────────────┘   │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  线程块限制                                                 │   │
│  │  ┌────────────────────────────────────────────────────┐   │   │
│  │  │  最大Block数: 32                                     │   │   │
│  │  │  即使寄存器/共享内存够用,也不能超过32个Block ❌       │   │   │
│  │  └────────────────────────────────────────────────────┘   │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│  实际活跃Warp数 = min(理论最大, 寄存器限制, 共享内存限制, Block限制) │
│  Occupancy = 实际活跃Warp数 / 64                                 │
└──────────────────────────────────────────────────────────────────┘

八、NVIDIA核心性能参数全景图

下面的表格汇总了从Volta到Blackwell架构的关键型号在编程和模型选型时最关注的硬指标:

型号 架构 FP16 算力 (TFLOPS) BF16 算力 (TFLOPS) FP8 算力 (TFLOPS) INT8 算力 (TOPS) FP64 算力 (TFLOPS) 显存带宽 显存容量 关键互联技术
V100 Volta 125 不原生支持 不原生支持 不原生支持 7.8 900 GB/s 32GB HBM2 NVLink 2.0
A100 Ampere 312 312 不原生支持 624 19.5 2.0 TB/s (HBM2e) 80GB HBM2e NVLink 3.0 (600 GB/s)
A800 (中国特供版) Ampere 312 312 不原生支持 624 19.5 2.0 TB/s (HBM2e) 80GB HBM2e NVLink 带宽受限 (400 GB/s)
H100 Hopper 1,979 1,979 3,958 3,958 67 3.35 TB/s (HBM3) 80GB HBM3 NVLink 4.0 (900 GB/s)
H800 (中国特供版) Hopper 1,979 1,979 3,958 3,958 67 3.35 TB/s (HBM3) 80GB HBM3 NVLink 带宽受限 (400 GB/s)
H200 Hopper ~1,979 ~1,979 ~3,958 ~3,958 67 4.8 TB/s (HBM3e) 141GB HBM3e NVLink 4.0 (900 GB/s)
L40S Ada Lovelace 733 733 1,466 1,466 91.6 (FP32) 864 GB/s (GDDR6) 48GB GDDR6 不支持NVLink
B100 Blackwell 待发布 待发布 ~7,900 (预估) 待发布 待发布 ~4.8 TB/s (HBM3e) 192GB HBM3e NVLink 5.0 (1.8 TB/s)
RTX 5090 Blackwell 83 (FP32) 83 支持 支持 1.3 (典型值) ~1 TB/s (GDDR7) 32GB GDDR7 不支持
RTX PRO 4500 Blackwell 支持 支持 支持 (含FP4) 支持 1.4 (典型值) 896 GB/s (GDDR7 with ECC) 32GB GDDR7 with ECC 不支持
H100 NVL (94G) Hopper 1,979 1,979 3,958 3,958 67 3.9 TB/s (HBM3) 94GB HBM3 (单卡) NVLink 4.0

💡 编程调优的关键洞察

这些参数对于编程实践意味着什么?

  1. 精度选择直接决定性能上限

    • 对于大模型训练 ,H100及后续架构对FP8的原生支持是关键。它能在保持模型精度的同时,大幅提升计算吞吐量并降低显存占用,是降低万亿参数模型训练成本的核心技术 。
    • BF16 在A100及之后架构上成为主流,因其动态范围与FP32相同,简化了混合精度训练的难度 。
    • 如果你的工作负载涉及科学计算(如分子动力学、气候模拟)FP64性能是刚需。H100的FP64性能是A100的3倍以上,而V100至今仍在这一领域有应用 。
  2. 内存带宽与容量:大模型的"命门"

    • H200的4.8TB/s带宽和141GB容量 是一个分水岭。它意味着像Llama 3 70B这样的模型可以单卡部署,无需复杂的模型并行策略,从而显著降低推理延迟并简化工程实现 。对于编程而言,这意味着可以尝试更长的序列长度和更大的batch size。
    • H100 NVL (94G) 的双卡配置,为参数量超过80B的模型提供了一种高带宽、大容量的解决方案,尤其适合推理场景 。
  3. 互联技术决定多卡扩展效率

    • 在进行多卡分布式训练 时,NVLink带宽至关重要。H100的900GB/s NVLink 能保证梯度同步等通信操作几乎不成为瓶颈,实现近线性的加速比。
    • 特别留意中国特供版A800/H800,其NVLink带宽被显著限制 。如果你的训练任务对卡间通信极为敏感(如使用GSPMD等并行策略),这个差异会对编程和性能优化策略产生重要影响。
  4. 架构特性:针对性优化

    • Transformer Engine (H100+):编程时可以利用其自动在FP8和FP16间切换的能力,简化了低精度训练的代码复杂度 。
    • L40S:它拥有RT核心,在AI推理的同时具备强大的3D图形渲染能力 。如果你的应用是AI+图形学(如数字人、Omniverse),这是编程时需要重点利用的异构计算特性。
    • RTX PRO 4500 :作为工作站显卡,它支持ECC显存纠错,这对需要长时间运行、数据零差错的专业计算和科学工作流至关重要 。

九、动手实践

9.1 查询你的GPU信息

运行以下代码,查看你的GPU硬件参数:

cpp 复制代码
#include <cuda_runtime.h>
#include <stdio.h>

int main() {
    int deviceCount;
    cudaGetDeviceCount(&deviceCount);
    
    for (int i = 0; i < deviceCount; i++) {
        cudaDeviceProp prop;
        cudaGetDeviceProperties(&prop, i);
        
        printf("GPU %d: %s\n", i, prop.name);
        printf("  计算能力: %d.%d\n", prop.major, prop.minor);
        printf("  SM数量: %d\n", prop.multiProcessorCount);
        printf("  每个SM最大线程数: %d\n", prop.maxThreadsPerMultiProcessor);
        printf("  每个SM最大Warp数: %d\n", prop.maxThreadsPerMultiProcessor / 32);
        printf("  最大线程块大小: %d\n", prop.maxThreadsPerBlock);
        printf("  寄存器数量/SM: %d\n", prop.regsPerMultiprocessor);
        printf("  共享内存大小/SM: %.2f KB\n", prop.sharedMemPerMultiprocessor / 1024.0);
        printf("  全局内存大小: %.2f GB\n", prop.totalGlobalMem / (1024.0*1024*1024));
        printf("  L2缓存大小: %d KB\n", prop.l2CacheSize / 1024);
        printf("----------------------------------------\n");
    }
    
    return 0;
}

9.2 编译运行

bash 复制代码
nvcc device_query.cu -o device_query
./device_query

十、本节总结

10.1 核心要点回顾

  1. GPU是吞吐优先的设计:几千个简单核心,通过大量线程隐藏延迟

  2. SM是核心计算单元:每个SM有自己的CUDA Core、Tensor Core、寄存器、共享内存

  3. Warp是执行最小单位:32个线程一起执行同一条指令

  4. 零开销调度:通过切换Warp隐藏访存延迟

  5. Tensor Core是AI加速核心:一次完成64次乘加运算

  6. Occupancy决定性能:受寄存器、共享内存限制

10.2 下节预告

下一节我们将深入GPU内存体系,搞懂:

  • 全局内存为什么慢?
  • 共享内存怎么用才能快?
  • 寄存器溢出会怎样?
  • 如何通过内存优化让性能翻倍?

十一、参考资料

十二、面试真题(2024-2026)

Q1:解释GPU的SIMT模型和CPU的SIMD有什么区别?

考察点:对两种并行模型的理解

参考答案

  • SIMD(单指令多数据):一条指令同时操作多个数据,所有单元步调一致(如CPU的AVX指令)。数据必须连续存储,处理分支困难。
  • SIMT(单指令多线程):多个线程执行同一条指令,但每个线程可以访问不同地址、可以有独立分支(虽然分支会序列化)。
  • SIMT更灵活,适合图形学和AI等不规则并行任务,这也是GPU适合AI的原因。

Q2:什么是Warp?Warp的大小为什么是32?

考察点:对硬件细节的了解

参考答案

  • Warp是GPU调度的最小单位,32个线程组成一个warp。
  • 32是设计权衡的结果:太小则调度开销占比大,太大则分支开销大、资源浪费。
  • 从Tesla架构开始就定为32,一直延续至今,保证了软件生态的兼容性。

Q3:什么是Occupancy?如何计算和优化?

考察点:性能优化基础

参考答案

  • Occupancy = 活跃warp数 / 最大支持warp数(通常64)。
  • 计算方法:受限于寄存器、共享内存、线程块大小。
  • 优化方法:
    1. 减少每个线程使用的寄存器(-maxrregcount编译选项)
    2. 减少每个Block使用的共享内存
    3. 调整Block大小(128-256通常较好)
    4. 使用__launch_bounds__提示编译器

Q4:Tensor Core和CUDA Core有什么区别?分别在什么场景使用?

考察点:对现代GPU架构的理解

参考答案

  • CUDA Core:通用标量单元,适合控制流复杂、非规则计算。
  • Tensor Core:专用矩阵乘加单元,一次完成4×4矩阵乘加(64次运算)。
  • 使用场景:
    • CUDA Core:自定义算子、元素级操作、复杂逻辑
    • Tensor Core:矩阵乘法、卷积、AI训练/推理
  • 开发中:一般用cuBLAS、cuDNN自动调用Tensor Core,手写需用wmma命名空间API。

Q5:SM上同时能跑多少个线程?受什么限制?

考察点:对硬件资源约束的理解

参考答案

以A100为例,理论上限2048线程(64 warp × 32线程)。

实际受三重限制:

  1. 寄存器限制:65536寄存器 ÷ 每线程寄存器数
  2. 共享内存限制:164KB ÷ 每Block共享内存 × 每Block线程数
  3. 线程块限制 :最多32个Block同时驻留
    最终取三者最小值。

思考题

如果你的核函数每个线程用64个寄存器,每个Block有256个线程,每个Block用32KB共享内存。在A100上,一个SM最多能同时跑多少个线程?

提示:A100每个SM有65536个寄存器、164KB共享内存、最多64个warp、最多32个Block。

计算。

  • Tensor Core:专用矩阵乘加单元,一次完成4×4矩阵乘加(64次运算)。
  • 使用场景:
    • CUDA Core:自定义算子、元素级操作、复杂逻辑
    • Tensor Core:矩阵乘法、卷积、AI训练/推理
  • 开发中:一般用cuBLAS、cuDNN自动调用Tensor Core,手写需用wmma命名空间API。

Q5:SM上同时能跑多少个线程?受什么限制?

考察点:对硬件资源约束的理解

参考答案

以A100为例,理论上限2048线程(64 warp × 32线程)。

实际受三重限制:

  1. 寄存器限制:65536寄存器 ÷ 每线程寄存器数
  2. 共享内存限制:164KB ÷ 每Block共享内存 × 每Block线程数
  3. 线程块限制 :最多32个Block同时驻留
    最终取三者最小值。

思考题

如果你的核函数每个线程用64个寄存器,每个Block有256个线程,每个Block用32KB共享内存。在A100上,一个SM最多能同时跑多少个线程?

提示:A100每个SM有65536个寄存器、164KB共享内存、最多64个warp、最多32个Block。

欢迎在评论区留下你的答案!

相关推荐
学嵌入式的小杨同学10 小时前
STM32 进阶封神之路(十三):空气质量传感器实战 ——KQM6600 模块从协议到代码(串口通信 + 数据解析)
c++·stm32·单片机·嵌入式硬件·架构·硬件架构·嵌入式实时数据库
Peter·Pan爱编程11 小时前
第2节:GPU内存体系深度解密
人工智能·硬件架构
学嵌入式的小杨同学12 小时前
STM32 进阶封神之路(十四):语音交互实战 ——SU03T 语音识别模块从固件制作到 STM32 控制(串口通信 + 命令响应)
c++·stm32·单片机·嵌入式硬件·架构·硬件架构·ux
梦..1 天前
电路EMC问题(二)
嵌入式硬件·硬件架构·硬件工程·pcb工艺
头发够用的程序员2 天前
GPU 流水线底层探索:从 SIMT 前端到 SIMD 后端的全链路解析
arm开发·人工智能·嵌入式硬件·深度学习·硬件架构·边缘计算
Stream_Silver2 天前
【系统架构设计师】第一章 计算机硬件 1.1 计算机硬件组成
笔记·硬件架构
学嵌入式的小杨同学3 天前
STM32 进阶封神之路(十二):串口实战全攻略 —— 发送 / 接收 / 中断 /printf 重定向(库函数 + 寄存器)
stm32·单片机·嵌入式硬件·mcu·硬件架构·pcb·嵌入式实时数据库
测试专家4 天前
揭秘反射内存卡RF2G测试:从硬件架构到带宽损耗的深度解析
硬件架构
学嵌入式的小杨同学4 天前
STM32 进阶封神之路(十一):串口通信底层原理全解析 ——UART/USART 区别 + 电平标准 + 协议规范(面试重点)
stm32·单片机·嵌入式硬件·mcu·硬件架构·硬件工程·智能硬件