《大规模并行处理器程序设计》学习笔记
第一章
TL; DR — 处理器的发展已经进入大规模并行和异构计算时代;GPU 通过大量线程提供高吞吐量,但要真正获得性能提升,程序员必须识别数据并行性,并同时处理任务划分、内存访问、数据传输、同步和可扩展性问题。
现代处理器性能提升正在从 提高单核频率 转向 增加并行计算单元。GPU 拥有大量计算核心,适合同时执行大量相似任务,因此能够为数据并行程序提供很高的吞吐量。
传统 CPU 性能提升受到功耗、散热和指令级并行度的限制,单纯提高时钟频率越来越困难。硬件厂商因此采用多核架构,但软件必须显式利用并行性,才能从新增核心中获得性能收益。这意味着程序员需要完成思维方式的转变:
- 从顺序算法转向并行算法
- 把计算拆分为大量可同时执行的任务
- 关注数据访问、同步和任务之间的依赖
- 考虑程序能否随处理器核心数量增长而扩展
CPU 主要针对低延迟和复杂控制流优化:
- 核心数量较少,但单核能力强
- 具有复杂的缓存和控制逻辑
- 擅长分支、串行逻辑和不规则任务
- 注重尽快完成单个任务
GPU 主要针对高吞吐量优化:
- 拥有大量相对简单的计算核心
- 将更多晶体管用于算术运算
- 通过大量线程隐藏内存访问延迟
- 擅长结构规则、计算密集、数据并行的任务
因此,GPU 并不是在所有场景下都比 CPU 快。只有当问题存在足够的并行性,并且计算与数据传输成本比例合理时,GPU 才能发挥优势。
现代系统通常采用 CPU 与 GPU 协同工作的异构架构:CPU 作为主机,负责程序控制、任务调度和串行部分;GPU 作为设备,负责大规模并行计算;数据需要在主机内存和设备内存之间进行管理或传输。
一个典型执行流程是:
- CPU 准备输入数据。
- 将数据传送到 GPU。
- CPU 启动 GPU 内核函数。
- GPU 使用大量线程并行处理数据。
- 将结果返回 CPU。
整体性能不能只看 GPU 内核的执行速度,还必须计算数据传输、内核启动和同步等开销。
GPU 最适合数据并行问题,即对大量数据元素执行相同或相似的操作。例如:
- 向量和矩阵运算
- 图像与视频处理
- 科学计算和数值模拟
- 机器学习
- 大规模数据分析
优秀的并行程序应具有可扩展性:当硬件提供更多计算资源时,同一程序无需大幅修改就能利用这些资源。为此,程序通常需要创建数量远多于物理核心的线程,由硬件运行时负责调度。
CUDA 提供了一种面向 NVIDIA GPU 的并行编程平台。程序员可以编写内核函数,并指定大量线程执行该函数。CUDA 的关键价值包括:
- 使用接近 C/C++ 的方式表达并行计算
- 将线程组织为层次化结构
- 由硬件和运行时完成线程调度
- 允许程序员控制设备内存和数据移动
- 使程序能够适配不同规模的 GPU
GPU 编程本质上是围绕大规模线程、数据并行和异构执行展开的。
GPU 拥有很高的理论运算能力,但实际性能还取决于:
- 算法中可并行部分的比例
- 内存访问效率
- CPU 与 GPU 之间的数据传输
- 线程间同步和通信
- 分支导致的执行分歧
- 是否有足够多的线程占满硬件
- 算法的计算密度
根据 Amdahl 定律,程序中的串行部分会限制整体加速比。即使并行部分运行得非常快,只要串行部分或数据传输占比较高,总体提升仍然有限。
第二章
参考资料
附录
Amdahl 定律
TL; DR — 在问题规模固定、串行与并行比例固定、主要关注缩短执行时间、不考虑并行化开销的前提下,Amdahl 定律 用于估算当程序只有一部分能够被并行化时,增加处理器数量或加速并行部分,整个程序最多能获得多大的加速。
- 整体优化效果取决于被优化部分在原运行时间中的占比;
- 少量串行代码也可能限制最大加速比;
- 处理器数量增加时,性能收益通常递减;
- 优化前应先测量瓶颈,优先优化耗时占比最大的部分;
- 并行化时必须把通信、同步和数据传输纳入总成本;
设
让处理器数量趋近于无穷:
称为最大理论加速比。
在 CPU 和 GPU 协同计算中,串行或不可加速的部分可能包括:
- CPU 上的串行逻辑
- CPU 与 GPU 之间的数据传输
- GPU 内核启动开销
- 线程同步
- 无法有效并行的算法阶段
- 文件读取和网络访问
- 负载不均衡造成的等待
基本公式假设并行部分可以被完美地平均分配,但实际系统还存在:
- 创建和调度线程的开销
- 锁竞争与同步开销
- 缓存一致性开销
- 内存带宽限制
- 处理器之间的通信
- 工作分配不均
- GPU 分支分歧
- CPU 与 GPU 数据复制
因此,更接近实际情况的时间模型可以写成:
其中
Gustafson 定律
TL; DR — 在总运行时间固定、问题规模能够随处理器数量增加而扩大、串行部分耗时基本不变、并行工作能够均匀分配且暂不考虑并行化开销的前提下,Gustafson 定律 用于估算增加处理器后,系统能够处理多大规模的问题,以及由此获得的可扩展加速比。
- 增加处理器的主要价值不只是缩短固定任务的运行时间,也可以是在相同时间内处理更大的问题;
- 当问题规模扩大时,并行部分可以随处理器数量增长,而串行部分通常保持相对稳定;
- 只要串行比例足够小,整体加速比就可以接近处理器数量;
- Gustafson 定律没有 Amdahl 定律中固定的最大加速上限,但串行部分仍会降低并行效率;
设
整理后也可以写成:
其中:
是使用 个处理器时测得的串行时间比例; 是并行时间比例; 表示相同时间尺度下,单处理器完成等量工作的时间与多处理器运行时间之比。
当处理器数量增加时:
如果
代入 Gustafson 定律可得:
让处理器数量趋近于无穷:
因此,Gustafson 定律虽然允许加速比随处理器数量增长,但串行比例仍然决定了系统能够达到的长期并行效率。
在 CPU 和 GPU 协同计算中,适合通过扩大问题规模获得收益的场景包括:
- 处理更高分辨率的图像或视频
- 扩大矩阵和张量的规模
- 增加科学模拟的网格数量
- 增加机器学习的批次大小
- 同时处理更多数据样本
- 提高数值计算的精度或迭代次数
- 扩大数据库查询或数据分析的范围
Amdahl 定律与 Gustafson 定律的核心区别是:
| 对比项 | Amdahl 定律 | Gustafson 定律 |
|---|---|---|
| 问题规模 | 固定 | 随处理器数量扩大 |
| 关注目标 | 缩短固定任务的运行时间 | 在固定时间内处理更多工作 |
| 串行比例 | 通常基于单处理器原始程序 | 通常基于多处理器运行时间 |
| 加速上限 | 受串行部分限制,存在固定上限 | 理想情况下可随处理器数量增长 |
| 典型问题 | 固定任务最快能运行多快 | 更多处理器能处理多大的任务 |
| 适用场景 | 固定数据集、固定工作量 | 科学计算、大数据、仿真和模型训练 |
简而言之,Amdahl 定律强调固定工作量下串行部分对加速比的限制;Gustafson 定律强调通过扩大并行工作量,可以让更多处理器持续发挥作用。
