<公开笔记/Bilibili/一张图片是怎么喂给大模型的?谈谈 CPU、内存、显存、GPU.md>
简介
本文从 GPU 训练/推理场景出发,详细剖析数据从固态硬盘到 GPU 计算核心的完整传输链路,解释显存占用与 GPU 利用率的区别,以及三条主要数据通路的性能瓶颈。
核心角色与定位
| 组件 | 角色定位 | 关键特点 |
|---|---|---|
| 硬盘 | 仓库 | 存储数据;SSD 比 HDD 快数十倍,训练数据应放 SSD |
| 内存 | 临时工作台 | 速度快,断电数据丢失,容量相对有限且成本较高 |
| CPU | 调度中心 / 全能博士 | 负责解码、调度等复杂操作,同一时间只能处理少量任务 |
| GPU 显存 | 计算核心的工作台 | 仅存储权重和中间结果,不参与计算 |
| GPU 计算核心 | 执行者 / 成千上万小学生 | 专门处理大规模矩阵运算(简单加减乘除),天然适合深度学习 |
重要区分:GPU ≠ 显存。GPU 由显存和计算核心两部分构成。加载权重到显存仅占用显存空间,计算核心空闲时 GPU 利用率为 0%(典型的"占着茅坑不拉屎"现象)。
数据完整传输链路
硬盘 → 内存 → 显存 → 计算核心
- 硬盘 → 内存:从 SSD 读取原始数据(如 JPG 图片)
- 内存 → 显存:通过 PCIe 总线传输数据
- 显存 → 计算核心:计算核心从显存读取权重和中间结果进行矩阵运算
补充说明:CPU 在此链路中负责解码原始数据(如将 JPG 转为张量),并可执行数据预处理、增强等操作。
三条数据管道的性能瓶颈
瓶颈一:硬盘 → 内存(数据加载)
- 原因:硬盘 I/O 速度远低于内存处理速度
- 解决方案:使用
DataLoader的num_workers参数并行读取(如设置为 8) - 补充:视频解码(如 mp4 → 张量)比图片解码复杂得多,也容易成为瓶颈。高端 GPU 已有硬件级视频解码加速
瓶颈二:内存 → 显存(PCIe 传输)
- 常见原因:
batch_size设置过大(如 128),数据排队等待- 代码设计不当,数据在 CPU 和 GPU 之间来回传输
- 优化原则:数据一旦传入 GPU,尽量在 GPU 端完成所有计算,减少"走回头路"
瓶颈三:显存 → 计算核心(内存墙 / Memory Wall)
- 原因:计算核心速度极快,但显存带宽有限,读写速度跟不上
- 表现:计算核心频繁等待从显存读取数据
量化(Quantization)的提速原理
| 精度 | 每参数占用空间 | 显存占用 |
|---|---|---|
| FP16/BF16 | 16 bit (2 byte) | 原始大小 |
| INT4 | 4 bit (0.5 byte) | 约为 FP16 的 1/4 |
补充说明:除节省显存外,量化还能提速的原因在于第三条瓶颈。以缓存/流水线为例,16 位模型单个数据包占 16 格,4 位量化后占 4 格,可同时传输更多数据,整体运算吞吐量提升。
面试题
Q1:GPU 利用率为 0% 但显存占用 90%,可能的原因是什么?
显存占用高通常只说明模型权重和中间结果占用了显存,但计算核心可能处于空闲状态: - 数据还未传入计算核心(等待数据加载或传输) - 数据预处理/解码成为瓶颈 - CPU 端操作阻塞了整个流程
Q2:训练时如何避免第一条数据管道(硬盘→内存)堵塞?
- 使用 SSD 存储训练数据
- 增大
DataLoader的num_workers参数实现并行数据加载 - 预加载和缓存数据
Q3:为什么量化不仅能省显存,还能提升推理速度?
量化后每个参数占用空间减少,在总线带宽(如显存带宽、缓存带宽)不变的情况下,单位时间内可传输/处理更多参数,相当于提升了数据吞吐量和计算效率。
Q4:GPU 和显存的区别是什么?
- GPU 计算核心:执行矩阵运算的地方,类似"成千上万的小学生"
- 显存(VRAM):GPU 上的高速内存,专门存储模型权重、激活值等数据
- 显存满 ≠ 计算核心忙碌,两者独立监控
