1. 课程导入与性能优化全景
MATLAB 之所以能在工程计算领域长期占据核心位置,很大程度上得益于它把矩阵运算、可视化与算法开发整合在同一套交互环境里。但当问题规模从“几千个点”增长到“上亿个点”,从“单次仿真”变成“参数扫描”或“训练迭代”时,单纯依赖 for 循环和默认的串行执行方式,计算时间会迅速成为瓶颈。本课程要解决的核心问题就是:如何在不牺牲 MATLAB 开发效率的前提下,把计算任务合理地分配到多核 CPU、GPU 以及多机集群上,并获得可度量的加速收益。
一、并行与 GPU 加速到底解决什么问题
MATLAB 中的性能瓶颈通常来自三类场景。第一类是大规模逐元素运算,例如对一张 8000×8000 的矩阵做滤波、阈值处理或逐点函数映射,这类任务天然适合向量化和 GPU 并行。第二类是可独立拆分的重复计算,例如对 200 组不同参数分别求解同一个微分方程,每组之间没有数据依赖,适合用 parfor 分配到多个 worker。第三类是计算密集但数据可驻留显存的任务,例如深度学习前向/反向传播、大规模矩阵乘法、FFT 与卷积,这类任务在 GPU 上往往能获得数十倍加速。
需要强调的是,并行不是“万能加速键”。如果任务本身只运行 0.05 秒,而启动并行池或传输数据需要 2 秒,那么并行反而更慢。因此判断是否值得并行,关键看三个量:单次计算耗时、任务可拆分程度、数据搬运开销。一个实用的经验判据是:当单次核心计算超过 0.1~1 秒、且各子任务相互独立时,并行收益通常开始显现;GPU 加速则要求数据规模足够大,使计算时间明显超过主机与设备之间的传输时间。
二、MATLAB 并行与 GPU 工具链全景
MATLAB 提供了一条从“单机多核”到“GPU”再到“集群”的渐进式工具链,理解它们的分工是后续学习的基础。下图给出了这条工具链的整体结构,以及各类任务与对应工具的映射关系。
从图中可以看到,工具选择遵循一条清晰的递进逻辑:先向量化,再并行,最后上 GPU 或集群。向量化是成本最低、收益最直接的第一步,它不需要任何额外硬件,只是把循环改写成矩阵运算。只有当向量化之后仍然太慢,才考虑引入并行池;只有当数据规模和计算密度都足够大时,GPU 才真正发挥优势。
三、一个可对照的示例:热扩散迭代
为了把“加速收益”变成可观察的量,这里给出一个贯穿课程的示例任务:对 2048×2048 的二维温度场做 500 次五点差分迭代。串行版本的核心循环如下:
n = 2048; T = zeros(n); T(1,:) = 100; T(end,:) = 0;
for k = 1:500
T(2:end-1,2:end-1) = 0.25 * ( ...
T(1:end-2,2:end-1) + T(3:end,2:end-1) + ...
T(2:end-1,1:end-2) + T(2:end-1,3:end));
end
在典型 8 核 CPU 上,这个串行版本大约需要数秒到十几秒(具体取决于机器)。如果改用 gpuArray,只需把初始矩阵搬到显存:
T = gpuArray(zeros(n));
% 循环体不变,运算自动在 GPU 上执行
T = gather(T); % 结果取回主机
此时每次迭代的四个矩阵加法与一次乘法都在 GPU 上并行完成,2048×2048 共约 419 万个元素,足以让 GPU 的数千个核心保持忙碌。判断加速是否成功,不能只看“感觉快了”,而应使用 gputimeit 或 timeit 做多次测量取中位数,并对比 gpuDevice 报告的显存占用,确认没有因为数据溢出显存而触发隐式回传。
gather 本身有传输成本,应尽量让整个计算链留在 GPU 上,最后只取回必要结果。四、学习路径与常见误区
本课程后续内容将沿着“诊断瓶颈 → 向量化 → 多核并行 → GPU 编程 → 性能度量与调优”的顺序展开。建议的学习路径是:先掌握用 tic/toc、timeit、Profiler 定位热点;再练习把循环改写为矩阵运算;然后学习 parfor 的适用条件与变量分类;接着进入 gpuArray、arrayfun、pagefun 等 GPU 编程接口;最后学习多 GPU、集群与深度学习加速。
需要提前警惕几个常见误区。其一,把并行当成默认选项,对小任务启动并行池,结果总时间反而增加。其二,在 parfor 中频繁访问大数组或做文件读写,导致通信开销吞掉计算收益。其三,GPU 上使用不支持的函数,MATLAB 会静默回退到 CPU 执行,表面能跑通,实际没有加速。其四,只测一次就下结论,忽略了缓存、预热和系统负载带来的波动。理解这些边界,比记住某个函数名更重要。