并行硬件
SIMD系统
在并行计算中,Flynn分类法经常用来对计算机体系结构进行分类。按照它能够同时管理指令流的数目和数据流的数目对系统分类。因此典型的冯·诺依曼系统是单指令单数据流(Single Instruction Stream Single Data Stream,SISD)系统,因此它一次只能执行一条指令,一次存取一个数据项。
单指令多数据流(Single Instruction Multiple Data SIMD) 系统是并行系统,SIMD系统通过对多个数据执行相同的指令从而实现在多个数据流上的操作,所以一个SIMD系统可以认为有一个控制单元和多个ALU,一条控制指令广播到多个ALU,每个ALU或者在当前数据上执行指令或者处于空闲的状态。
假设
for(i = 0;i < n; i++){
x[i] += y[i]
}
假如SIMD系统中有n个ALU,我们能够将x[i]和y[i]加载到第i个ALU中,然后让第i个ALU将x[i]和y[i]相加,结果储存在x[i]中。
在经典的SIMD系统中,ALU必须同步操作,即在下一条指令开始执行之前,每个ALU必须等待广播,此外ALU没有指令存储器,所以ALU不能通过存储指令来延迟执行指令。
SIMD系统适合对处理大型数组的简单循环实行并行化,通过将数据分配给多个处理器,然后让多个处理器使用相同的指令来操作数据子集实现并行化。称为数据并行化。
和SIMD系统相关的发展是:向量处理器,图形处理单元(Graphics Processing Unit, GPU)等。
向量处理器
重要的特点就是对数组或数据向量进行操作,典型的特征:
-
向量寄存器:能够存储多个操作数组成的向量,并且能够对其内容进行操作的寄存器。向量的长度有系统决定,从4到128个64位元素不等。
-
向量化和流水化的功能单元:对向量中的每个元素需要做相同的操作,向量操作是SIMD的。
-
向量指令:如果向量的长度是
vector_length
, 这些指令的功能相当于一个简单的循环语句for(i = 0; i < n; i++) { x[i] += y[i] }
只需要一次加载、一次加法、一次存储就完成了所有的操作
-
交叉存储器:在内存系统中由多个内存“体”组成,每个核可以独立访问,访问完一个内存体之后,再次访问需要一定时间延迟。如果能够访问另外一个内存体,就可以很快访问。所以如果向量中的每个元素分布在不同的内存体中,那么装入和存储就会快很多。
-
步长式存储器访问和硬件散射/聚集:在步长式存储器访问中,程序能够访问向量中固定间隔的元素。散射/聚集则是对间隔无规律的数据进行读(聚集)写(散射)。
向量系统有很高的内存宽带,每个加载的数据都会使用,不像基于Cache的系统不能完全利用高速缓存行的每个元素,但是它不能处理不规则的数据结构和其他并行结构。
图形处理单元(GPU)
实时图形应用编程接口使用点、线、三角形来表示物体的表面。它们使用图形处理水流线(graphics processing pipeline)将物体的表面的内部表示转换为一个像素的数组。可编程阶段的行为可以通过着色函数(shader function)来说明。典型的着色函数一般比较短,通过几行代码就可以实现了,它们能够应用到图形流中的多种元素,所以着色函数一般都是隐式并行的。GPU可以通过使用SIMD并行来优化性能。现在所有的GPU都使用SIMD并行,这是通过在每个GPU处理核引入大量的ALU来获取的。
GPU的缺点是需要处理大量的线程来位置ALU忙碌,在小问题的出来上性能相对较差。
MIMD系统
**多指令多数据流(Multiple Instruction Multiple Data ,MIMD)**系统支持同时多个指令流在多个数据流上操作,因此MIMD系统通常包括一组完全独立的处理单元或者核,每个处理单元或者核都有自己的控制单元和ALU。和SIMD不同,MIMD通常是异步的。即每个处理器能够按照自己的节奏运行,在很多MIMD系统中,没有全局时钟,两个不同的处理器上的系统时间之间没有联系的。
MIMD系统有两种主要类型
- 共享内存系统:自治的处理器通过互联网与内存系统连接,每个处理器能够访问内阁内存区域。
- 分布式内存系统:每个处理有自己私有的内存空间,处理器-内存对之间通过互联网相互通信。
一个共享内存系统
一个分布式内存系统
共享内存系统
最广泛使用的共享内存系统使用一个或者多个核处理器。
每个核访问内存中任何一个区域的时间都相同,称为一致内存访问(Uniform Memory Access,UMA),比较容易编程。
一个UMA多核系统
访问与该核直连接的那块内存域比访问其他内存区域快很多,因为访问其他内存区域需要通过另一块芯片,称为非一致内存访问(Nonuniform Memory Access,NUMA)
一个NUMA多核系统
分布式内存系统
最广泛使用的分布式内存系统就是集群(clusters)。
网络提供了一中基础架构,使地理上分布的计算机大型网络转换成一个分布式内存系统。通常,这样的系统是异构的,即每个结点都是由不同的硬件构造的。
互连网络
互连网络(interconnection network)在分布式内存系统和共享内存系统中都扮演一个决定性的角色。
共享内存互连网络
在共享内存系统中,最常用的两种互连网络是总线(bus)和交叉开关矩阵(crossbar)。
总线是由一组并行通信和控制对总线访问的硬件组成的。总线的核心特征是连接到总线上的设备共享通信线。总线具有低成本和灵活的优点,但是设备增大,性能会减低。
交换互连网络使用交换器(switch)来控制相互连接设备之间的数据传输。
这是一个交叉开关矩阵,线表示双向通信链路,方块表示核或者内存模块,圆圈表示交换器。
交换器的不同状态。
多个处理器同时访问内存
分布式内存互连网络
通常分为两种:
- 直接互连
- 间接互连
直接互连
每个交换器与一个处理器-内存对直接相连,交换器之间也相互连接。
一个环
一个二维环面网格
衡量“同时通信的链路数目”或者“连接性”的一个表示是等分宽度(bisection width)。为了理解这个标准,想象并行系统分为两个部分,每个部分都有一半的处理器或者节点。在这两个部分能同时发生的通信。
等分宽度是基于最坏情况下估计的。
链路的宽度(bandwidth)是指它的传输数据的速度,通常用兆位每秒或者兆字节每秒来表示。等分宽度(bisection bandwidth)通常用来衡量网络的指令。
最理想的直连互连网络是全连接网络,即每个交换器与每一个其他的交换器直接连接。
一个全互连网络
它的等分宽度是 p 2 4 \frac{p^2}{4} 4p2。但是为节点数目较多的系统构建这样的互连网络是不切实际的,因为它需要总共 p 2 2 + p 2 \frac{p^2}{2}+\frac{p}{2} 2p2+2p条链路。
超立方体一种已经用于实际系统中的高度互连的直接互连的网络。超立方体是递归构造的。
(a)一维 (b)二维 (c)三维
这样的超立方体的等分宽度是 p 2 \frac{p}{2} 2p
间接互连
为直接互连提供了一个替代的选择。在间接互连网络中,交换器不一定与处理器直接相连。
一个通用的间接网络
一个用于分布式内存的交叉开关矩阵互连网络
交叉开关矩阵和omega网络是间接网络中相对简单的例子。
在omega网络的交换器中有一个
2
×
2
2\times 2
2×2的交叉开关矩阵
与交叉开关矩阵不同的是,有一些通信无法同时进行。
一个omega网络
延迟和宽带
延迟:从发送源开始传送数据到目的地开始接受数据之前的时间。
带宽:目的地在开始接受数据后接受数据的速度。
Cache一致性
两个核和两个Cache的共享内存系统
在多核系统中,每个核的Cache存储相同变量的副本。当一个吹起更新Cache中的该变量副本时,其他处理器应该知道该变量已更新,即其他处理器中Cache的副本也应该更新,这称为Cache一致性问题。
有两种主要的方法来保证Cache的一致性:监听Cache一致性协议和基于目录Cache一致性协议。
监听Cache一致性协议
监听协议的想法来自于基于总线的系统:当多个核共享总线时,总线上传递的信号都能被连接到总线的所有核看到。当核0更新它的Cache中的副本,如果它也这个更新信息在总线上广播,假设核1正在监听总线,那么就会知道已经更新了,并将自己的Cache中的变量副本标记为非法的。这就是Cache一致性协议大致的工作原理。
考虑
- 互联网不一定必须是总线,只要能够支持从每个处理器广播到其他处理器
- 监听协议能够在写直达和写回Cache上都能工作
基于目录的Cache一致性协议
通过使用一个叫做**目录(directory)**的数据结构来解决上面的问题。目录存储每个内存行的状态。一般地,这个数据结构是分布式的。当一个高速缓存行被读入时,与这个高速缓存行相对应的目录项就会更新,表示核0有这个行的副本,当一个变量需要更新时,就会查询目录,并将所有包含该变量高速缓存行置为非法。