第10章 并行编程基础
10.1 程序的并行行为
人们对应用程序性能的追求是无止境的,例如天气预报、药物设计、核武器模拟等应用。并行处理系统可以协同多个处理单元来解决同一个问题,从而大幅度提升性能。评价一个并行处理系统,主要看其执行程序的性能(即程序在其上的执行时间)。可以通过一些公认的并行测试程序集(如SPLASH、NAS)来进行评测。因此,在讨论并行处理结构之前,先来看一下程序的并行行为。程序的并行行为主要包括指令级并行性、数据级并行性、任务级并行性。
10.1.1 指令级并行性
指令级并行性(Instruction Level Parallelism,简称ILP)主要指指令之间的并行执行,当指令之间不存在相关时,这些指令可以在处理器流水线上重叠起来并行执行。在程序运行中,如果必须等前一条指令执行完成后,才能执行后一条指令,那么这两条指令是相关的。指令相关主要包括数据相关、控制相关和结构相关。数据相关包括写后读(Read After Write,简称RAW)相关、读后写(Write After Read,简称WAR)相关和写后写(Write After Write,简称WAW)相关。其中RAW相关是真正的数据相关,因为存在真正的数据传递关系;WAR相关和WAW相关又称为假相关或者名字相关,指令之间实际不存在数据传递。控制相关主要是由于存在分支指令,一条指令的执行取决于该分支指令的执行结果,则这两条指令之间存在控制相关。结构相关是指两条指令同时需要流水线中的同一个功能部件。在这些相关中,RAW数据相关和控制相关是真正制约指令级并行执行的相关。指令相关容易引起流水线阻塞,从而降低流水线效率。
现代处理器采用多种微结构设计技术挖掘指令级并行性,包括指令流水线、多发射、动态调度、寄存器重命名、转移猜测等技术。指令流水线重叠执行多条不相关的指令;多发射技术允许一个时钟周期执行多条指令,类似于“多车道”;动态调度允许后续指令越过前面被阻塞的指令继续被调度执行,相当于允许“超车”;寄存器重命名可以消除RAW和WAW的假相关并支持猜测执行;转移猜测技术可以猜测分支指令的方向和目标,在分支指令还未执行完之前获取更多可执行指令,以减少控制相关造成的指令流水线阻塞。这方面的技术已经比较成熟。
10.1.2 数据级并行性
数据级并行性(Data Level Parallelism,简称DLP)是指对集合或者数组中的元素同时执行相同的操作。这种并行性通常来源于程序中的循环语句。如图10.1所示的代码就是一个数据并行的例子。对于数组local中的元素local[i],执行相同的操作“(i+0.5)*w”。可以采用将不同的数据分布到不同的处理单元的方式来实现数据级并行。
图10.1 数据并行
数据级并行性是比较易于处理的,可以在计算机体系结构的多个层次来利用数据级并行性。例如:可以在处理器中设计向量功能部件,采用SIMD设计方法,如一个256位向量部件一次可以执行4个64位的操作;设计专门的向量处理器,如CRAY公司的CRAY-1、CRAY-2、X-MP、Y-MP等;在多处理器中,可以采用SPMD(Single Program Multi-Data)的编程方式,将数据分布到不同的处理器上执行同一个程序控制流。数据级并行性常见于科学和工程计算领域中,例如大规模线性方程组的求解等。正是由于这个原因,向量处理器在科学计算领域还是比较成功的。
10.1.3 任务级并行性
任务级并行性(Task Level Parallelism)是将不同的任务(进程或者线程)分布到不同的处理单元上执行。针对任务表现为进程或者线程,任务级并行性可分为进程级并行性或者线程级并行性。图10.2是一个任务并行的代码示意图。对于一个双处理器系统,当处理器ID(processor_ID)为a时,则执行任务A;当处理器ID为b时则执行任务B。
图10.2 任务并行的代码示意图
在并行处理系统中,挖掘任务并行性就是让每个处理器执行不同的线程或进程。这些线程或者进程可以执行相同或者不同的代码。通常情况下,不同线程或者进程之间还需要相互通信来协作完成整个程序的执行。任务级并行性常见于商业应用领域,如大规模数据库的事务处理等。另外,多道程序工作负载(Multiprogramming Workload),即在计算机系统上运行多道独立的程序,也是任务级并行的重要来源。