1. 课程导入

当你用手机拍照后瞬间完成人像虚化,当自动驾驶汽车在毫秒级识别车道与行人,当大模型在数秒内生成一段代码,这些体验背后并不是某一颗“更快的 CPU”在独自支撑,而是 CPU、GPU、FPGA 等多种计算单元协同工作的结果。这种让不同架构的处理器各展所长、共同完成一个计算任务的方式,就是异构并行计算。本课程将围绕 CPU、GPU、FPGA 三类主流器件,讲清它们如何分工、如何编程、如何协同,以及如何把性能真正“压榨”出来。

一、为什么需要异构并行计算

过去几十年,处理器性能提升主要依赖主频提高和指令级并行。但进入多核时代后,单核频率增长趋缓,功耗墙与散热墙成为硬约束。与此同时,数据规模却在爆炸式增长:图像分辨率从 1080P 走向 4K/8K,深度学习模型参数量从百万级走向千亿级,基因测序、金融风控、雷达信号处理等场景的数据吞吐要求远超传统串行程序的处理能力。

单一架构无法同时满足“复杂控制逻辑”和“海量数据并行”两类需求。CPU 擅长分支判断、任务调度和低延迟响应,但并行度有限;GPU 拥有数千个流处理器,适合规则的大规模数据并行;FPGA 可通过硬件电路重构实现流水线与定制位宽,在特定算法上具备极低延迟和高能效。异构计算的核心思想,就是把合适的任务交给合适的硬件,让系统整体性能、功耗和成本达到最优平衡。

核心判断:如果一个任务中 90% 的时间花在可并行的密集计算上,那么把它迁移到 GPU 或 FPGA 往往能带来数量级的加速;反之,如果任务充满复杂分支和串行依赖,CPU 仍是更合适的选择。

二、核心概念与整体知识框架

在正式进入编程之前,需要先建立几个贯穿全课程的概念。第一是主机与设备:通常 CPU 作为主机负责控制流、内存管理和任务调度,GPU/FPGA 作为设备负责计算加速。第二是计算密集型与数据密集型:前者如矩阵乘法、卷积,后者如数据清洗、流式过滤。第三是并行粒度:指令级、线程级、数据级、任务级并行,不同硬件擅长的粒度不同。第四是存储层次与数据搬运:异构系统中,数据在主机内存与设备内存之间移动的开销常常是性能瓶颈。

下图给出本课程的整体知识框架:从异构背景出发,分别深入 CPU 多核、GPU 并行、FPGA 加速三条技术路线,再汇聚到异构协同、性能优化与典型应用。

异构并行计算 性能 · 功耗 · 延迟 · 成本 CPU 多核并行 线程 / 进程 / OpenMP 任务调度 · 缓存一致性 分支预测 · 低延迟控制 适合:复杂控制、串行依赖 GPU 大规模并行 CUDA / SIMT / 线程束 共享内存 · 寄存器压力 访存合并 · 占用率调优 适合:规则数据并行、矩阵运算 FPGA 可重构加速 HDL / HLS / 流水线 定制位宽 · 片上存储 低延迟 · 高能效 适合:流式处理、协议加速 异构协同与性能优化 任务划分 · 数据搬运 · 流水重叠 · 负载均衡 典型应用场景 深度学习训练与推理 · 科学计算 · 图像视频处理 · 金融风控 · 网络与雷达信号处理

三、方法流程:异构程序的基本工作流

无论使用哪种器件,异构程序通常遵循相似的五步流程。理解这条主线,后续学习具体 API 时就不会迷失方向。

  1. 任务分析:识别热点函数,判断可并行比例,估算加速上限(Amdahl 定律)。
  2. 任务划分:把计算拆成适合 CPU、GPU、FPGA 的子任务,确定数据依赖关系。
  3. 数据准备与搬运:在主机内存与设备内存之间分配、拷贝数据,必要时使用零拷贝或统一内存。
  4. 并行执行:启动核函数、流水线或硬件加速器,配置线程块、流水深度等参数。
  5. 结果回收与验证:把结果拷回主机,与 CPU 参考实现对比,检查数值误差与性能指标。

下面是一段典型的 CUDA 异构程序骨架,可以看到“主机分配—设备分配—拷贝—核函数—拷回”的完整节奏:

// 1. 主机分配与初始化
float *h_in = (float*)malloc(N * sizeof(float));
float *h_out = (float*)malloc(N * sizeof(float));
initData(h_in, N);

// 2. 设备分配
float *d_in, *d_out;
cudaMalloc(&d_in,  N * sizeof(float));
cudaMalloc(&d_out, N * sizeof(float));

// 3. 主机到设备拷贝
cudaMemcpy(d_in, h_in, N * sizeof(float), cudaMemcpyHostToDevice);

// 4. 启动核函数(网格与线程块配置)
dim3 block(256);
dim3 grid((N + block.x - 1) / block.x);
vectorAdd<<<grid, block>>>(d_in, d_out, N);

// 5. 设备到主机拷回并校验
cudaMemcpy(h_out, d_out, N * sizeof(float), cudaMemcpyDeviceToHost);
verify(h_out, N);

四、典型应用场景与器件选型

不同应用对延迟、吞吐、功耗和开发周期的要求差异很大,选型时不能只看峰值算力。下表给出常见场景的对照参考。

应用场景 主要特征 推荐器件 关键指标
深度学习训练 大规模矩阵运算、规则数据并行 GPU 吞吐量、显存带宽
实时视频编解码 流式处理、固定算法流水线 FPGA / GPU 延迟、能效比
高频交易风控 极低延迟、确定性响应 FPGA + CPU 微秒级延迟
科学计算仿真 双精度浮点、迭代求解 CPU + GPU 浮点性能、内存容量
数据库查询加速 分支多、数据量大、访问不规则 CPU + FPGA 查询延迟、吞吐

五、常见误区与学习建议

误区一:认为“用了 GPU 就一定快”。如果数据传输开销大于计算收益,或者并行度不足,GPU 版本可能比 CPU 还慢。误区二:忽视数值精度差异,GPU 单精度与 CPU 双精度结果不一致时误判为程序错误。误区三:把 FPGA 当作“更快的 CPU”,实际上 FPGA 需要从硬件结构角度重新设计数据通路。
学习建议:先建立“性能模型”意识,再动手写代码。每做一个实验,都记录加速比、数据传输时间、占用率或资源利用率等指标,用数据判断优化方向,而不是凭感觉调参。

本课程后续将沿着“背景—CPU 多核—GPU 并行—FPGA 加速—异构协同—性能优化—综合案例”的路径展开。你不需要一开始就掌握所有细节,但需要始终带着三个问题阅读:这个任务的计算特征是什么?哪种器件最适合它?数据在器件之间如何高效流动?把这三个问题想清楚,异构并行计算就从“玄学调参”变成了可分析、可验证的工程方法。