50、芯片多处理器架构与编程模型解析

芯片多处理器架构与编程模型解析

1. 芯片多处理器(CMP)架构基础

CMP架构在现代处理器设计中扮演着重要角色,以Power 7处理器架构为例,其每个核心都配备了分离的私有一级指令/数据(I/D)缓存和统一的私有二级(L2)缓存,同时在芯片上实现了一个大容量(32 MB)的共享三级(L3)缓存。这个三级缓存采用嵌入式DRAM技术,将DRAM与随机逻辑和SRAM逻辑集成在同一芯片上。

CMP中所有核心所需的累积带宽促使其需要高带宽的片外资源接口,因此CMP成为了将系统组件集成到芯片上的关键驱动力。例如,通过集成点对点互连接口(如英特尔的快速路径互连QPI和AMD的超传输HT),多个芯片可以相互通信,实现高带宽和低片间通信延迟。此外,当前的CMP还将内存控制器集成到芯片上,以提供高内存带宽。英特尔酷睿i7通过其片上内存控制器支持更高速度的DDR3内存,为所有核心共享的内存提供约21 GB/s的带宽。不过,将系统组件集成到芯片上也存在缺点,即处理器会受到特定接口标准的限制。

2. 异构核心的CMP

CMP在核心设计方面提供了广泛的选择。从核心复杂度来看,一种极端情况是CMP由许多简单的按序核心组成,这些核心可以同时运行多个线程以提高吞吐量性能;另一种极端情况是CMP只有少数几个大型、强大的乱序核心。大量小核心适用于具有高并行线程数的工作负载,如商业或数据库工作负载;而少量大核心则适用于提高单线程性能或线程并行性有限的工作负载。

在许多使用场景中,运行在CMP上的应用程序是异构混合的,会对系统的所有组件造成压力。如果CMP中的核心数量增加而功率预算固定,那么每个核心的功率预算必须超线性下降。这是因为片上互连网络(如点对点网络)的功耗会随着核心数量的增加而超线性增长,导致每个核心可用的总功率减少。因此,依赖大型乱序核心的单线程性能在具有许多简单核心的CMP上会显著下降。

为了解决单线程和多线程应用程序需求之间的冲突,异构CMP应运而生。在异构CMP中,每个核心在性能或功能能力上可能有所不同。实现性能不对称的方法有多种,以下是一些常见的技术及其相关信息:
| 方法 | EPI范围 | 改变EPI的时间 |
| ---- | ---- | ---- |
| DVFS | 1:2 至 1:4 | 100 µs,斜坡Vcc |
| 可变资源 | 1:1 至 1:2 | 1 µs,填充L1 |
| 推测控制 | 1:1 至 1:1.4 | 10 ns,管道刷新 |
| 混合核心 | 1:6 至 1:11 | 10 µs,迁移L2 |

  • 动态电压和频率缩放(DVFS) :根据应用程序的并行性数量动态调整核心的电压和时钟速率,从而改变每条指令消耗的能量(EPI)。当应用程序的并行性较低时,微处理器可以消耗所有可用功率来处理少量指令;当并行性丰富时,微处理器可以为每条指令消耗较少的功率,以同时处理大量指令。
  • 动态改变核心可用资源 :根据应用程序的需求动态调整核心可用的资源量。例如,当运行工作集较小的应用程序时,可以通过关闭一些缓存组来缩小缓存的大小或关联性,从而有效降低电容和动态功率,同时通过关闭缓存组的电源来减少静态功耗。不过,这种方法带来的EPI节省最多约为50%。
  • 推测控制 :通过限制飞行中指令的数量来改变EPI。当分支预测器的准确率较低时,这种方法特别有用,因为它可以避免在错误预测的指令被刷新时浪费大量能量。然而,由于取指节流仅影响电路活动因子,而大多数处理器结构仍在时钟驱动下,因此使用推测控制只能使EPI发生少量变化。

此外,核心还可以在功能上异构。例如,一个核心可以提供对加密的专门支持,而另一个核心可以只运行图形密集型代码。不同类型的异构性选择取决于应用程序中EPI的变化量以及过渡到新EPI状态的相关代价。

3. 异构CMP示例
  • IBM Cell :采用了极端的核心异构设计,它将一个PowerPC处理元素(PPE)与八个协同处理元素(SPE)相结合。PPE是一个双向同步多线程(SMT)核心,能够处理复杂操作;SPE是一个双发射按序处理器,每个周期最多可以发射两条单指令多数据(SIMD)指令。通过基于SIMD的SPE,Cell CMP的向量处理能力得到了显著增强。不过,SPE和PPE之间没有提供内存一致性的硬件支持,需要程序员来确保一致性。
  • 英特尔酷睿i7 :通过电压/频率缩放(DVFS)来调节EPI,实现了一种更简单的异构性。其“Turbo Boost”技术可以根据工作负载和CPU利用率的变化动态调整核心的运行频率。如果四个核心中只有一个核心处于活动状态,并且芯片温度、功率和电流供应在额定范围内,那么单个工作核心的时钟速率可以小幅度提高(当前酷睿i7实现中为133 MHz)。
4. 连体核心的CMP

在具有连体核心的CMP中,核心之间共享资源的粒度比共享缓存时更细。例如,核心可以共享算术逻辑单元(ALU)等资源。这种设计的动机是单个核心内资源利用率存在显著的时间差异,像浮点功能单元这样的复杂资源占用大量芯片面积,但在大多数工作负载中利用率较低。通过高速互连,连体核心可以在芯片内的核心之间共享这些面积昂贵且利用率低的资源。

为了实现高效的资源共享,CMP上核心的布局需要考虑核心对共享资源的访问模式。例如,在同质CMP中,如果多个核心共享一个浮点单元(FPU),那么每个核心的执行阶段在芯片布局中必须与FPU等距,以确保所有核心对该单元的访问延迟相同。此外,资源共享还需要仲裁机制来防止竞争核心在同一周期访问资源。

以Sun的SPARC T1处理器为例,它是连体核心CMP的一个很好的例子。T1芯片上有八个核心,它们共享一个FPU以减少面积开销。每个核心都是细粒度多线程的,在执行过程中遇到的任何浮点运算都会将核心ID、操作码和输入操作数发送到共享资源。FPU计算结果操作数并将其发送回请求核心,请求核心会停止处理等待浮点运算完成的线程的指令,转而从其他运行线程中获取指令。

5. CMP的编程模型

CMP的硬件特性(如芯片多线程实现快速上下文切换、低延迟片上互连网络和共享末级缓存促进核心间通信)使得应用程序开发人员能够生成更短的线程,并以更细的粒度进行通信。以下是几种常见的编程模型:
- 独立进程 :运行多个独立进程是充分利用多个线程上下文的一种简单方法。例如,桌面用户通常会同时运行多个独立的应用程序(如网页浏览器、流媒体视频和文档编辑器),每个应用程序作为一个独立进程在单独的核心或线程上下文中运行。这种方法在个人计算机和工作站的商品市场中最为常见,但并行性受到用户活动的限制,并且独立进程无法利用CMP的共享资源和更短的线程间通信延迟。
- 显式线程并行化 :随着指令级并行性(ILP)提取在典型应用中变得越来越困难,线程级并行性(TLP)成为提高应用程序性能的另一种方法。通过将单个应用程序划分为多个线程,这些线程可以在多个线程上下文中并发运行并相互交换数据。应用程序程序员需要仔细理解应用程序的语义,识别可以并行执行的代码片段,如循环迭代和函数调用。

为了帮助程序员管理并行线程的执行,存在一些软件库。例如,Pthreads是一个流行的线程库,它为程序员提供了并行化API,程序员可以使用该库创建并发执行的线程、互斥访问共享数据并调用同步函数。OpenMP应用程序编程API则以编译指示(pragma)的形式提供编译器指令,帮助应用程序开发人员识别哪些代码片段可以并行化。例如,以下是一个使用OpenMP进行并行化的简单示例:

#pragma OpenMP parallel for
(int i = 0; i < n; ++i){a[i] = b[i] × c[i]}

如果代码在具有两个线程上下文的系统上执行,第一个线程上下文(CPU#1)将执行从0到(n/2 - 1)的迭代,第二个线程上下文将执行循环的后半部分迭代。如果在具有四个逻辑线程上下文的系统上执行,运行时环境会自动为每个CPU分配四分之一的循环迭代。

不同的OpenMP库和运行时支持实现方式可能不同。一种简单的实现方式是将并行循环编译指示转换为OpenMP库函数调用,该库函数在运行时探测底层系统以获取可用线程上下文的数量,然后创建与硬件线程上下文数量相同的线程。每个执行循环的线程可以被视为一个函数调用,其开始和结束循环索引作为参数传递。运行时环境会根据线程上下文的数量确定每个线程的开始和结束循环索引。

通过以上对CMP架构和编程模型的介绍,我们可以看到CMP在提高处理器性能和资源利用率方面具有巨大潜力,但也面临着一些挑战,如功率管理和软件并行化等问题。未来,随着技术的不断发展,CMP有望在更多领域得到应用和优化。

芯片多处理器架构与编程模型解析

6. 线程通信开销对线程粒度的影响

线程通信开销会显著影响线程粒度的选择,下面通过一个简单的例子来说明。假设有一个应用程序开发者需要决定一个循环的两个连续迭代(Iteration1和Iteration2)是否可以在两个不同的线程上下文中并行执行。

设Iteration1完成需要T ns,并且在T / 2时刻产生Iteration2所需的值。Iteration2运行T / 2 ns,然后必须等待Iteration1的数据才能继续。考虑三种不同的系统:对称多处理(SMP)系统中值的通信时间为100 ns;CMP中核心间的通信时间为10 ns;多线程核心中通信时间为0 ns。

  • SMP系统 :Iteration2完成需要T / 2 + 100 + T / 2 ns。由于Iteration1和Iteration2并行执行,SMP系统上的总执行时间为T + 100 ns。如果两个迭代在单个核心上顺序运行,假设Iteration1可以通过寄存器将数据无成本地传递给Iteration2,总执行时间为2T ns。为了使SMP上的并行执行有益,需要满足2T > T + 100,即T > 100 ns。
  • CMP系统 :CMP上并行执行有益的条件是2T > T + 10,即T > 10 ns。这意味着在CMP上,每个线程的大小只需是SMP上线程大小的十分之一就可以利用并行化。
  • 多线程核心 :从通信角度来看,在同一核心上运行这两个线程时,并行化总是更优的。

这个例子表明,CMP较低的线程通信延迟使得开发者可以使用更细粒度的线程,从而更好地利用并行性。

7. 独立进程编程模型的优缺点分析

独立进程编程模型是利用CMP的一种常见方式,它有其自身的优缺点:
| 优点 | 缺点 |
| ---- | ---- |
| 实现简单,无需用户或应用开发者付出额外努力,用户可以像平常一样同时运行多个独立应用程序。 | 并行性受用户活动限制,无法充分发挥CMP的潜力。 |
| | 独立进程之间不共享数据和指令,无法利用CMP的共享资源,反而会竞争资源,例如增加每个进程的缓存缺失率。 |
| | 由于不进行值的通信,无法利用CMP更短的线程间通信延迟,还会导致总线请求增加,造成总线拥塞和更长的缺失惩罚,失去了共享L2缓存的好处。 |

8. 显式线程并行化的操作流程

显式线程并行化是提高应用程序性能的重要方法,其操作流程如下:
1. 理解应用程序语义 :程序员需要仔细分析应用程序,确定哪些代码片段可以并行执行,常见的如循环迭代和函数调用。
2. 消除或处理依赖关系 :对于循环迭代,需要识别并处理循环携带的依赖关系,确保每个迭代可以独立运行。
3. 实现互斥访问 :对于共享数据结构的修改,需要使用互斥机制进行保护,例如循环迭代计数器的递增操作需要串行执行。
4. 插入同步代码 :当每个线程完成其分配的循环迭代后,可能需要等待其他线程完成,这可以通过线程同步原语来实现。
5. 使用软件库 :可以使用如Pthreads和OpenMP等软件库来简化线程的创建、同步、通信和终止等任务。

9. OpenMP实现并行执行和同步的流程

OpenMP通过库和运行时支持实现并行执行和同步,其流程如下:

graph TD;
    A[遇到并行循环pragma] --> B[调用OpenMP库函数];
    B --> C[运行时探测可用线程上下文数量];
    C --> D[创建与硬件线程上下文数量相同的线程];
    D --> E[确定每个线程的开始和结束循环索引];
    E --> F[线程并发执行循环];
    F --> G[循环结束后插入屏障同步];
    G --> H[所有线程完成后,单线程执行后续代码];

具体来说:
1. 当遇到并行循环编译指示(pragma)时,将其转换为OpenMP库函数调用。
2. 库函数在运行时探测底层系统,获取可用于该循环的线程上下文数量。
3. 根据线程上下文数量创建相应数量的线程。
4. 为每个线程确定开始和结束循环索引,将其作为参数传递给线程执行的函数。
5. 线程并发执行循环。
6. 循环结束后,运行时环境自动插入屏障同步,确保所有线程完成循环迭代。
7. 所有线程完成后,只有一个线程继续执行循环后的代码。

10. 总结与展望

芯片多处理器(CMP)架构通过集成系统组件、采用异构核心设计和连体核心设计等方式,提高了处理器的性能和资源利用率。在编程模型方面,独立进程和显式线程并行化各有优缺点,而显式线程并行化中的OpenMP为开发者提供了一种方便的并行编程方式。

然而,CMP也面临着一些挑战。例如,在异构CMP中,如何根据应用程序的特点选择合适的异构性类型,以及如何处理功率预算和单线程性能之间的矛盾。在编程方面,软件并行化仍然是一个昂贵的努力,一些遗留软件可能难以并行化。

未来,随着技术的不断发展,我们可以期待CMP在以下方面取得进一步的突破:
- 更智能的功率管理 :开发更先进的算法,根据应用程序的需求动态调整核心的功率和性能,以提高能源效率。
- 更高效的并行编程工具 :改进现有的并行编程库和编译器,降低并行编程的难度,使更多的开发者能够利用CMP的优势。
- 更广泛的应用领域 :CMP有望在人工智能、大数据处理等领域得到更广泛的应用,为这些领域的发展提供更强大的计算支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值