并行计算是指同时利用多个处理资源来解决计算问题。计算任务被拆分为可同时执行的部分,并在必要时进行协调。这些资源可以是一台计算机中的多个核心、一个图形处理器(GPU),或多台互联的机器。与顺序执行不同,并行执行利用操作之间的独立性来缩短耗时或处理更大的工作负载。它是超级计算机及许多科学应用的基础。(hpc.llnl.gov)
并行性及相关概念
并发与并行相互关联,但并不相同。并发关注如何组织各自独立推进的活动;并行则关注如何同时执行这些活动。并发程序可以通过交错执行各项活动,在单个处理核心上运行,而不实现并行执行。另一方面,并发程序的结构也可以将适合多个处理器执行的工作显露出来。(go.dev)
当联网的机器协同完成计算时,分布式计算与并行计算便存在交集。不过,并行计算不一定涉及多台机器:共享内存中的线程和 GPU 核函数也可以并行执行。分布式内存编程则要求拥有独立本地内存的任务彼此通信,无论这些任务位于一台机器上还是多台机器上。(hpc-tutorials.llnl.gov)
能否并行执行取决于算法,而不只是硬件。独立的操作可以同时进行,而需要先前结果的操作则必须遵循其依赖关系。因此,分解问题需要识别独立的工作、决定其粒度,并确定中间结果的交换方式。(hpc-tutorials.llnl.gov)
并行执行的形式
**数据并行对数据集的不同部分执行相似的操作。例如,各个工作单元可以处理一个矩阵中不同的分块,或对不同的数组元素应用相同的变换。任务并行**将不同的活动分配给不同的工作单元;这些活动可以执行不同的操作,也可以沿不同的控制路径运行。(hpc.llnl.gov)
**流水线并行**将处理过程划分为多个阶段。不同阶段同时处理不同的输入,类似于装配流水线。尽管每个输入仍须依次经过各个阶段,流水线执行依然可以提高吞吐量。多线程程序可以将流水线与其他基于任务的组织方式结合起来。(hpc-tutorials.llnl.gov)
硬件也支持不同的执行组织方式。单指令多数据(SIMD)执行方式将一条指令应用于多个数据元素。NVIDIA GPU 使用与之相关的单指令多线程(SIMT)模型,将线程分组执行,同时向程序员提供单个线程的编程视图。同一组内的控制流分歧可能降低执行效率。(docs.nvidia.com)
内存架构与编程模型
在**共享内存系统中,处理器访问共同的地址空间。这便于共享数据,但程序必须协调相互冲突的访问。在分布式内存系统**中,处理器拥有各自独立的本地内存,并通过互连网络交换数据。混合系统则在节点内部使用共享内存,在节点之间使用分布式内存。(hpc.llnl.gov)
OpenMP 为 C、C++ 和 Fortran 的并行编程提供编译器指令、运行时例程和环境变量。其构造用于表达工作共享、任务、同步以及数据共享属性。使用 OpenMP 并不自动保证程序正确:程序员仍须负责处理依赖关系和相互冲突的访问。(openmp.org)
消息传递接口(MPI)规定了并行进程之间的通信接口。它支持点对点消息和集合操作,并可运行于共享内存和分布式内存平台。一种常见的混合方式是在节点之间使用 MPI,在各节点内部使用线程模型。(hpc-tutorials.llnl.gov)
CUDA 为 NVIDIA GPU 提供编程模型。核函数通过由线程、线程块和网格组成的层次结构执行。线程块被分配给可用的 GPU 多处理器,使程序能够呈现大量可并行执行的操作,而不必将每项操作显式分配给某个物理执行单元。(docs.nvidia.com)
协调与正确性
并行执行会引入简单顺序代码中不存在的执行次序问题。当对同一内存位置的相互冲突的访问未按适当的顺序进行,且其中至少有一次写入时,就会发生数据竞争。在 OpenMP 内存模型下,这类竞争会使程序结果处于未规定的状态。(openmp.org)
同步机制用于实现协调。临界区每次只允许一个参与线程执行受保护的代码。原子操作保护指定的内存更新,而屏障要求参与线程先到达同一个执行点,才能继续运行。这些机制各有用途,不能相互替代。(hpc-tutorials.llnl.gov)
正确性与性能可能发生冲突:过多的同步会限制各项工作同时推进,而同步不足则会导致错误。负载均衡也很重要,因为工作分配不均会使部分资源闲置;在屏障处,较快的工作单元必须等待最慢的参与者。(hpc.llnl.gov)
性能与可扩展性
加速比通常表示为 (S(p)=T_1/T_p),即顺序执行时间与使用 (p) 个处理器时的执行时间之比。理想的线性加速比为 (S(p)=p),但串行工作和并行开销通常会限制性能提升。强扩展性衡量问题总规模固定时的性能;弱扩展性则衡量每个处理器的工作量保持大致不变时的性能。(docs.nvidia.com)
阿姆达尔定律描述了问题规模固定时的加速比限制:
[ S(p)\leq \frac{1}{s+(1-s)/p}, ]
其中,(s) 是原始执行时间中仍须串行执行的部分所占的比例。该模型假定并行工作能够理想地划分,并忽略额外开销。如果 (s=0.1),那么无论处理器数量有多少,加速比的极限都是十。古斯塔夫森定律则考虑随可用资源增加而扩大问题规模的情况,解释了为什么即使固定规模问题的加速比受到限制,更大规模的计算仍可能从中受益。(docs.nvidia.com)
内存带宽、通信和数据移动都可能成为瓶颈。因此,仅优化算术运算的执行并不一定能缩短整个应用程序的运行时间;主机内存与 GPU 内存之间的数据传输开销可能抵消加速计算带来的收益,甚至超过这些收益。(docs.nvidia.com)
应用
并行计算支持仿真、数值计算和深度学习。在采用数据并行的神经网络训练中,各个工作单元持有模型副本,处理不同的样本,并通过交换梯度来保持更新协调一致。其他方法则将模型状态或计算划分到多个设备上,从而能够训练超出单个设备内存容量的模型。(arxiv.org)