高性能计算机的体系结构与程序优化

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• 技术方面的缺点需要通过结构来弥补 • DRAM慢,SRAM小=》存储器层次结构
– 体系结构方面的革新
• 各个级别上并行性的开发
• 如何支持编程?
– 共享内存 – 承担一些软件较难完成的优化工作
• 如动态执行, 猜测执行, COMA等
三种类型的体系结构技术
• 保守的结构
– 硬件仅提供必需的设施, 如大量的寄存器 – 高性能能否最终达到, 完全依赖软件
– 引入了更多的指令级和线程级并行性 – 容忍远程访问延迟和数据依赖的负面影响
• 多个上下文之间的切换机制
– 发生事件时切换(有点象进程的切换) – 每个时钟周期都切换: 每次取不同线程的指令
• 多个线程的指令在同一流水线中(无依赖)
• 第一个多线程系统(Tera)已经问世
– 多线程同时工作对cache干扰很大
• 暴露出了更多的可同时执行 的操作 • 不好看,但实用
运算顺序的调整
• 通常的算法设计和程序实现中,人们习 惯在需要某数据的地方才计算出该数据 的值,紧接着使用该数据。 • 这是很自然的思维习惯,但对于流水线 则会造成麻烦。 • 两个运算相继进行,但后一个运算需要 的操作数还没有被计算出来,只有原地 等待,造成了流水线的停滞。
应用程序员可以做什么?
• 仔细地研究编译器的优化功能和选项
– -O2, -O3, -finline-functions, -funroll-loops
• 充分利用已经优化过的库函数
– 如BLAS等 – 如果可能,找或编适合自己需要的高效率库
• 做一些源程序级的优化
– 最典型的一种优化:循环展开 – 为编译程序的优化提供更多的机会
• 优化后的循环
DO 10 I = 1, N 10 B(I) = A(I) * A(I) DO 20 I = 1, N 20 C(I) = 1 / B(I)
• 先展开,再调整顺序
• 又称为循环拆分
存储器的层次结构
• 弥补CPU与主存间的速度差异 • 各个层次间的访问速度和容量差别
– 寄存器:32个;几乎不需要时间 – 一级cache:16KB-128KB;1个时钟周期 – 二级cache:128KB-4MB;几个时钟周期 – 本地主存:64MB-1GB;几十个时期周期 – 远程主存:512MB以上;成百上千个周期 – 硬盘对换区(虚存):成千上万个周期
寄存器的使用
• 寄存器的使用基本上是可以控制的
– 在汇编子程序里完全可以控制 – 在C语言里用register说明用得最多的变量
• 需要考虑CPU内通用寄存器和浮点寄存器的数量
– 编译程序在生成代码前,会进行寄存器分配
• 程序设计与优化时,可考虑寄存器利用
– 最内层循环体不宜过长,寄存器会不够用 – 循环展开的次数不能太多
循环展开的例子
• 展开前的代码 DO 10 I = 1, N 10 Y(I) = A*X(I) + Y(I) • 这是一种常见的写法 • 循环体里包含的运算 量较小(1加、1乘) • 循环控制意味着转移 • 如果CPU一拍能做4 个浮点运算,这个循 环的性能就不高了 • 展开4次后的代码 DO 10 I = 1,N,4 Y(I)=A*X(I)+Y(I) Y(I+1)=A*X(I+1)+Y(I+1) Y(I+2)=A*X(I+2)+Y(I+2) 10 Y(I+3)=A*X(I+3)+Y(I+3)
• 折衷的结构
– 硬件做一些动态的优化, 如高速缓存 – 软件仍有优化的余地
• 包揽式的结构
– 硬件试图做充分的动态优化, 如COMA – 认为软件在动态分析和优化方面能力有限
结点内并行:超长指令字结构
• 芯片面积主要用于功能部件和高速缓存
– 完全依赖编译程序开发指令级并行性
• 分支预测, 循环展开, 软件流水, 踪迹调度
指令调度的例子
假设:取数时间较长,后续指令不能立即使用 源程序语句:a = b + c; d = e - f; a, b, c, d ,e, f 都在存储器中. Slow code: Fast code: LW Rb,b LW Rb,b LW Rc,c LW Rc,c ADD Ra,Rb,Rc LW Re,e SW a,Ra ADD Ra,Rb,Rc LW Re,e LW Rf,f LW Rf,f SW a,Ra SUB Rd,Re,Rf SUB Rd,Re,Rf SW d,Rd SW d,Rd
结点内并行 超标量、动态调度、猜测执行
• 硬件动态地分析指令流,同时执行多条指令
– 在分析区间内,指令以数据流的方式执行 – 弥补编译器在静态分析和调度方面的不足 – 换代后目标码不重新编译也能获得较好的性能
• 需要发掘指令级并行性的新来源
– 精确的动态分支预测,消除分支损耗 – 设置大量换名寄存器,消除虚假的数据依赖 – 不等分支完成,就开始执行目标指令(猜测) – 同时执行分支的多个目标(多标量)
寄存器的使用
• • • • • • for ( k=0;k<10;k++) { for (j=0;j<1000;j++) 执行运算过程B; } 运算过程B的大小也是我们必须考虑的。如果B过大, CPU内部寄存器的压力就会很大,如果寄存器的数量 不足以保存B中出现的所有数据,可能会出现颠簸的现 象,刚刚从寄存器中换出的数据也许就是下一个需要 的数据,还得重新读入寄存器,这对效率显然是有影 响的。解决的办法是将循环体过大的循环拆分成若干 循环体较小的循环,这种方法叫做循环分布,循环体 拆分的粒度是以寄存器数量的多少为参考的。
结点间并行:共享存储系统
• 共享存储的好处
– 易于编程、通用性强 – 与SMP及其应用实现无缝衔接
• 存储一致性模型与实现效率
– 松(弱)一致性模型允许多种优化 – 对系统软件设计或应用程序设计提出新的要求?
• 如何避免、隐藏或容忍远程访问的开销
– Origin2000: 185周期; 未来可能达数百万个周期 – 缓存、预取、预送、多线程
– 指令系统结构不兼容
• 显式并行指令结构(EPIC)
– Explicitly Parallel Instruction Computer – 128位的Group包括3条指令 – 设置专门的域指示指令间是否存在依赖关系 – 可连接多个Group以支持更大范围内的并行
结点内并行:同时多线程结构
• 由硬件提供快速的上下文切换机制
运算顺序的调整
• • • • • • • • • 如下例所示: b[0]=a[0]*a[0]; c[0]=1/b[0]; b[1]=a[1]*a[1]; c[1]=1/b[1]; b[2]=a[2]*a[2]; c[2]=1/b[2]; …… 是求一系列数的平方的倒数的操作。虽然因为 c[0] 紧接着 b[0] 计算,让计算的内在含义更明显,也更 符合通常的思维习惯,但对于流水线来说效率极差。
• 未来系统中两大问题的解决也是如此
– ①极长的等待时间;②极大的并行度
充分利用处理器内的并行
• 提高单机性能是提高并行机性能的基础 • 目前CPU内部常用的并行结构包括:
– 指令流水线与运算流水线 – 多个功能部件并行执行
• 如:定点运算、存/取、浮点加、浮点乘、…
• 充分流水、并行工作的条件
– 指令间没有相关,即相互独立 – 结构相关:两条指令要用同一个部件 – 数据相关:一条指令要用另一条指令的结果 – 控制相关:条件转移指令影响其它指令
• 体系结构是硬件和系统软件之间的界面
– Enable High Performance – Support Ease Programming
• 编程模型是应用和计算机系统间的界面
– 理想的模Biblioteka Baidu: 应用不必了解具体的结构特征
体系结构的主要研究内容
• 如何提高性能?
– 先进的工艺技术--纯粹属于硬件的范围?
结点间并行:消息传递系统
• Tcomm = Tstartup + Tblock + Ncomm/Bcomm • 如何实现与处理能力匹配的通信带宽
– 通信带宽、通信延迟对应用性能的影响 – 光互连技术
• 如何减少通信开销
– 用户级通信 – 硬件支持重试、保证通信的可靠性和顺序
• 如何减少阻塞
– 自适应路由、优化应用的通信结构
存储层次发挥作用的基本原理
• 程序的访存局部性(locality)
– 时间局部性:最近访问的,将来还要访问 – 空间局部性:访问了A,则要访问A的近邻
• 局部性使快速存储区的内容多次被访问
– 比喻:80%的时间花在20%的代码上
• 工作集:最近程序集中访问的地址空间
– 调整程序结构,使工作集小于cache容量
高性能计算机的 体系结构与程序优化
提纲
• • • • • • 应用编程与体系结构的关系 高性能计算机体系结构概述 CPU内的并行结构(指令级并行) 存储器的层次结构 多体交叉的并行存储系统 分布存储系统中的通信优化
体系结构的位置
Programming Models Architecture Applications System Software Hardware
运算顺序的调整
• • • • • • • • • 现在变动如下: b[0]=a[0]*a[0]; b[1]=a[1]*a[1]; b[2]=a[2]*a[2]; …… c[0]=1/b[0]; c[1]=1/b[1]; c[2]=1/b[2]; …… 调整以后,先是整个的把 数组b[]计算出来,然后再 计算数组c[],此时,需要 的b[]数组中的数据都已经 计算出来了,就不会存在 流水线停滞的问题。
更一般的形式
• 原始循环
DO 10 I = 1, N B(I) = A(I) * A(I) 10 C(I) = 1 / B(I)
• 进一步优化
DO 10 I = 1, N, 3 B(I) = A(I) * A(I) B(I+1)=A(I+1)*A(I+1) B(I+2)=A(I+2)*A(I+2) C(I) = 1 / B(I) C(I+1) = 1 / B(I+1) 10 C(I+2) = 1 / B(I+2)
寄存器的使用
• 根据运算过程B的实际情况和并行环境的 特点,可以拆分为以下两种形式中的一 种。 形式A: • for(k=0;k<10;k++) { • for(j=0;j<1000;j++) • 执行运算过程B1; • for(j=0;j<1000;j++) • 执行运算过程B2; • }
寄存器的使用
– 全系统的查找需大量时间
存储器的供数率跟得上吗?
• CPU消耗数据的速率远大于存储器供数率
– 时钟频率增长的速度大于访存时间缩短的速度 – 同时执行多条指令要求供数率进一步提高 – 多线程或芯片内多处理器要求访问多组数据
• 已知的解决方案:存储器层次结构
– 片内cache的供数率能满足指令级并行的要求? – 片内cache的命中率足够高? – 为多个线程或处理器提供各自的cache? – 如何通过程序或算法的改进增强访存局部性?
• • • • • • • • • • 形式B: for(k=0;k<10;k++){ for(j=0;j<1000;j++) 执行运算过程B1; } for(k=0;k<10;k++){ for(j=0;j<1000;j++) 执行运算过程B2; } 形式A比较符合人们的习惯思维方式,形式B对 循环的拆分更彻底,更加有利于并行执行。
发挥CPU内并行性的主要手段
• 编译程序:静态指令调度
– 分析程序中的指令流 – 在不影响结果的前提下,对指令重新排序 – 缺点:不能获得运行时的动态信息 – 改进:基于profile的指令调度或优化
• 硬件:超标量、动态指令调度
– 由专用硬件检查即将执行的一段指令 – 挑选出源操作数和功能部件都已齐备的指令 – 缺点:硬件会变得很复杂、降低时钟频率
性能不仅依赖于结构
• 性能的提高依赖于体系结构上的革新
– 硬件技术的发展对体系结构提出了新的要求 – 各个层次并行性的开发是新体系结构的主要特征
• 实际性能的提高更依赖于体系结构与编译技 术、操作系统、应用算法间的配合与协调
– Architectural Support for Programming Languages and Operating Systems, Since 1988
结点间并行:COMA
• CC-NUMA的主要问题
– 数据静态地分配在home结点上 – 通过远程访问cache存取非本地的数据 – 数据分配不当会造成大量的数据传输
• COMA中没有物理地址, 数据可动态迁移
– 经过“预热”, 数据将被“吸引”到处理结点附 近
• 主要问题: 不命中时如何快速找到所需数据
相关文档
最新文档