Later done, 以下是来自GPT的未编辑内容。
L05 Pipelining II
Deeper Pipelines: MIPS R4000
MIPS R4000 处理器采用了8级流水线,结合了指令缓存和数据缓存,从而优化了流水线的处理效率。流水线的各个阶段分为以下几部分:取指(IF)、指令存储器(IS)、寄存器读取(RF)、执行(EX)、数据访存(DF)、数据选择(DS)、标签检查(TC)和写回(WB)。这些阶段为处理器的每个指令提供了清晰的执行路径,使得处理器能够更高效地处理并发的操作。
关键点:
- 直接映射的I$(指令缓存):允许在标签检查完成之前就使用指令,这加速了指令的执行并减少了等待时间。
- 标签检查的时机:尽管指令在IS阶段可用,但标签检查实际上在RF阶段进行。同时,寄存器在RF阶段读取,以便后续的执行和数据访存操作可以顺利进行。
- 数据访问和标签检查:数据访问阶段(DF)需要进行缓存的标签检查(TC),以确保数据访问的准确性。如果缓存未命中,流水线可能需要倒退一个周期来重新获取正确的数据。
这张图展示了R4000的八级流水线结构,其中标注了不同阶段的划分以及流水线寄存器的位置。这种设计优化了流水线处理器的并发能力,同时通过合理安排指令和数据缓存,提高了系统的整体性能。
R4000 Load-Use Delay
MIPS R4000 的整数流水线中存在一个 x1 负载使用延迟。当处理器从寄存器中加载数据时,数据值实际上在DS阶段即可获取,而无需等待到流水线的最后阶段(WB)。由于R4000使用了直接映射的数据缓存(D$),使得在标签检查完成之前就可以使用数据,从而缩短了延迟。
关键点:
- 负载使用延迟:由于数据在DS阶段即可获取,因此延迟为一个周期(x1)。如果标签检查在TC阶段检测到缓存未命中,流水线会倒退一个周期,等待正确的数据加载完成。
- 旁路机制:旁路机制允许数据在加载后立即被后续指令使用,而不必等待完整的流水线周期,进一步减少了负载使用的延迟。
图示展示了不同指令的执行时间线,特别是当数据访存涉及负载指令时如何影响流水线的处理效率。通过直接映射的D$,流水线可以在标签检查完成之前就使用数据,优化了流水线的并行处理能力。
R4000 Branches
MIPS R4000 处理器的分支延迟是三周期的。这是因为条件的评估是在 执行阶段(EX) 完成的,而分支的决策需要等待这个评估结果。图C.39展示了这种分支延迟的流水线过程:
- BEQZ指令:即“分支如果为零”指令在执行阶段决定是否跳转。由于评估是在EX阶段完成的,因此从指令开始到分支跳转的最终决策,整个过程需要三个周期。
- 其他指令:在分支指令后,处理器继续执行指令1、指令2和指令3,直到确定分支是否执行。当分支跳转确认后,流水线会跳转到目标指令,新的指令从该点继续执行。
这种设计通过在流水线中引入适当的延迟来保证分支跳转的正确性,同时保持流水线的高效性。
Simple Vector-Vector Add Code Example
这个例子展示了一个简单的向量加法代码,计算A[i] = B[i] + C[i],其中涉及寄存器操作和内存加载。代码在每个循环中执行以下步骤:
- 加载向量元素:
fld f0, 0(x2)
:从地址x2(指向B数组的当前元素)加载B[i]到浮点寄存器f0。fld f1, 0(x3)
:从地址x3(指向C数组的当前元素)加载C[i]到浮点寄存器f1。
- 加法操作:
fadd.d f2, f0, f1
:将f0和f1中的值相加,结果存储到寄存器f2中。
- 存储结果:
fsd f2, 0(x1)
:将结果f2存储到地址x1(指向A数组的当前元素)。
- 更新指针:
addi x1, x1, 8
:更新指向A数组的指针(递增8字节)。addi x2, x2, 8
:更新指向B数组的指针(递增8字节)。addi x3, x3, 8
:更新指向C数组的指针(递增8字节)。
- 分支:
bne x1, x4, loop
:如果x1不等于x4(结束条件),则跳转回到loop
继续执行下一个循环。
通过这个循环,处理器能够逐个元素地计算向量A的值,每次迭代都会加载、计算并存储一个向量元素的结果。
Simple Pipeline Scheduling
通过重新调度代码,可以尝试减少流水线中的冒险(hazards)。下方的循环展示了如何调整加载指令和浮点运算,以最大限度地减少流水线中的停顿。
loop: fld f0, 0(x2) // x2 指向 B 数组
fld f1, 0(x3) // x3 指向 C 数组
addi x3, x3, 8 // 增加 x3 指针,指向下一个 C 元素
addi x2, x2, 8 // 增加 x2 指针,指向下一个 B 元素
fadd.d f2, f0, f1 // 浮点加法:f2 = f0 + f1
addi x1, x1, 8 // 增加 x1 指针,指向下一个 A 元素
fsd f2, -8(x1) // 将 f2 存储到 A 数组
bne x1, x4, loop // 如果 x1 不等于 x4,继续循环
在这个例子中,加载指令和浮点操作的长延迟限制了单次循环迭代中的并行性。为了在流水线中更好地分配指令,可以对指令的顺序进行调整,以减少数据冒险(如 RAW)。不过,由于浮点操作需要较长的执行时间,所以可以通过更好的指令调度来减少依赖关系带来的停顿。
One Way to Reduce Hazards: Loop Unrolling
为了减少动态指令计数,并进一步暴露更多的并行性,可以使用循环展开技术。通过展开循环,每个循环体将处理更多的迭代,从而减少分支指令的执行次数,减少控制冒险,并增加流水线利用率。
以下是一个展开后的循环示例:
loop: fld f0, 0(x2) // x2 指向 B 数组
fld f1, 0(x3) // x3 指向 C 数组
fld f10, 8(x2) // 加载 B[i+1]
fld f11, 8(x3) // 加载 C[i+1]
addi x3, x3, 16 // 增加 x3 指针,跳过两个元素
addi x2, x2, 16 // 增加 x2 指针,跳过两个元素
fadd.d f2, f0, f1 // 计算 A[i] = B[i] + C[i]
fadd.d f12, f10, f11 // 计算 A[i+1] = B[i+1] + C[i+1]
addi x1, x1, 16 // 增加 x1 指针,跳过两个元素
fsd f2, -16(x1) // 存储 A[i] 的结果
fsd f12, -8(x1) // 存储 A[i+1] 的结果
bne x1, x4, loop // 如果 x1 不等于 x4,继续循环
循环展开的优点:
- 减少冒险:通过展开,可以更好地调度指令,减少流水线中冒险的发生。
- 增加并行性:更多的计算可以同时进行,增加指令级别的并行性。
- 减少动态指令计数:展开减少了分支和循环控制指令的频率,降低了动态指令的数量。
循环展开的限制:
- 寄存器数目限制:展开的程度受到架构寄存器数目限制的影响,较多的展开需要更多的寄存器来存储中间结果。
- 增加指令缓存的占用:循环展开会增加代码大小,从而增加指令缓存的负担,可能导致缓存不命中率上升。
- 编译器复杂性增加:编译器需要处理展开后的指针和指令调度,增加了编译器的复杂性。
Alternative Approach: Decoupling (lookahead, runahead) in Microarchitecture
在微架构设计中,解耦技术是一种将控制和内存地址操作与数据计算分离的方法。通过这种方式,控制和地址的计算可以提前进行,而数据的计算则可以被推迟。这种方法使流水线更具弹性,能够更有效地应对延迟。
解耦后的循环示例:
loop: fld f0, 0(x2) // x2 指向 B 数组
fld f1, 0(x3) // x3 指向 C 数组
fadd.d f2, f0, f1 // f2 = f0 + f1
fsd f2, 0(x1) // 将 f2 存入 A 数组
addi x1, x1, 8 // 更新 x1 指针
addi x2, x2, 8 // 更新 x2 指针
addi x3, x3, 8 // 更新 x3 指针
bne x1, x4, loop // 如果 x1 不等于 x4,继续循环
在这个代码片段中,地址操作与数据计算之间没有依赖关系,因此这些地址操作(例如 addi
指令)可以比数据计算(例如 fld
和 fadd.d
指令)提前进行。这意味着,尽管数据计算可能被延迟,地址相关操作可以继续前进,减少流水线中的停顿。
解耦设计的优点:
- 减少冒险:通过提前处理地址和控制逻辑,数据操作的延迟不会阻塞流水线中其他指令的执行。
- 增加吞吐量:在数据计算等待期间,可以继续进行控制和地址操作,最大化资源利用率。
Simple Decoupled Access/Execute Machine
解耦访问和执行的架构通常包括独立的整数流水线和浮点流水线,并通过微操作队列(micro-op queue)进行任务调度。
整数流水线与浮点流水线的解耦示意图:
- 整数流水线负责处理基本的整数运算,例如地址计算和指令调度。
- 浮点流水线专门处理浮点运算,操作通常具有较高的延迟。
流水线中的数据和地址会被分别排队处理,数据加载和存储操作可以独立于计算操作。这种设计方式确保当一个操作需要等待(例如内存访问延迟)时,不会阻塞其他操作的执行。
解耦流水线的关键组件:
- uOp Queue(微操作队列):存放需要执行的微操作,供整数流水线和浮点流水线分别执行。
- Load Data Queue(加载数据队列):处理所有内存加载相关的操作。
- Store Data Queue(存储数据队列):负责所有内存存储的操作。
通过这种解耦设计,流水线的各个部分可以独立工作,从而提高处理效率,减少等待时间。
Decoupled Execution
在解耦执行(Decoupled Execution)中,指令执行过程中的加载、存储和计算操作被分离,能够独立排队执行。这样可以最大化流水线的利用率,即使部分操作(如内存加载)存在延迟,流水线也可以继续进行其他不依赖的操作。
解耦执行的具体操作步骤:
- 加载浮点寄存器
fld f0
:将加载操作发送到内存,并排队等待写入f0
寄存器。 - 加载浮点寄存器
fld f1
:将加载操作发送到内存,并排队等待写入f1
寄存器。 - 浮点加法
fadd.d
:将加法操作排队等待执行。 - 存储结果
fsd f2
:排队存储地址,等待存储数据写入内存。 - 更新指针
addi x1, x2, x3
:更新指针操作独立进行,这些操作不依赖于数据计算,可以提前执行。 - 分支操作
bne
:检查条件跳转并更新程序计数器。
在这种结构中,每个操作可以在没有依赖关系的情况下异步排队,从而减少流水线停顿,提高指令吞吐量。特别是当多个加载操作(如对 f0
的多次写入)排队时,这些操作可以同时进行,从而减少等待时间。
优势:
- 提高流水线效率:通过将加载、计算和存储操作解耦,可以更好地利用流水线中的资源,减少空闲周期。
- 并行处理:多个操作(如指针更新、内存加载)可以同时处理,无需等待计算操作完成。
- 减少冒险和停顿:当某些操作(如存储或加载)需要较长时间时,不会阻塞流水线的其他部分。
这种解耦设计允许处理器在面对内存访问延迟时依然能保持高效的执行速度,最大限度地提高性能。
CS152 Administrivia
- HW1发布:截至日期为2月2日。
- Lab1发布:截至日期为2月9日。
- 实验报告要求:必须提供易于阅读的英文总结,禁止直接提交日志文件。
- 报告需符合页数限制,具体要求请参照实验规范和Ed讨论区。
- 讲座讨论区:
- 每个讲座有一个讨论主题帖。
- 请按照指定格式提交问题:
- [幻灯片编号] 您的问题。
- 工作人员将异步解答问题。
- 下周二的客座讲座:主题为预取技术。
Supercomputers
超级计算机的定义是指世界上在特定任务中最快的机器。它们不仅代表了计算性能的极致,同时也具备了多种特点,用以解决大规模计算和数据处理问题。以下是超级计算机的主要定义和相关背景:
-
世界上最快的机器:在特定任务或应用领域内,超级计算机是执行速度最快的设备,通常用于科学、气象模拟、基因组学等高计算需求的领域。
-
将计算密集型问题转化为I/O密集型问题的设备:通过超强的计算能力,超级计算机能够使得原本由于计算资源不足而受限的问题,变为受输入输出(I/O)限制的问题,这意味着它能够快速处理海量数据。
-
价值超过3000万美元的机器:超级计算机的研发和制造成本极高,通常造价在数千万美元以上。
-
由Seymour Cray设计的机器:Seymour Cray被誉为“超级计算机之父”,他设计的多台计算机,包括CDC6600,被视为开创了超级计算机的时代。
-
CDC6600:由Cray在1964年设计的CDC6600被普遍认为是第一台超级计算机。它在当时具有革命性的计算能力,标志着超级计算机领域的开端。
CS252 Administrivia
- CS252阅读材料:可通过以下网址进行查看和上传评论:
- 阅读材料网址
- 在周三之前通过 hotcrp 提交评论,内容应包括一段总结主要内容和优缺点,还应回答或提出1-3个问题供讨论。首两篇文章为《360 Architecture》和《VAX11-780》。
- 讨论时间:每周三下午2-3点,地点Soda 606/Zoom。
- CS252项目时间表:
- 提案提交日期:2月22日星期三。
- 使用252A的助教(Abe和Prashanth)的办公时间来获取反馈。
CDC 6600 (Seymour Cray, 1964)
CDC 6600是Seymour Cray于1964年设计的超级计算机,凭借其革命性的架构和性能成为当时世界上最快的计算机,并引领了超级计算的新时代。该机型具有以下显著特点:
-
高速流水线处理,60位字长:CDC 6600采用了流水线技术,使得处理器能够并行处理指令,显著提高了计算速度。其内存容量为128K字,分为32个内存银行,支持并发访问。
- 十个功能单元(并行、非流水线):CDC 6600配备了十个功能单元,能够同时执行不同类型的操作。功能单元包括:
- 浮点运算:加法器、两个乘法器和一个除法器。
- 整数运算:加法器和两个递增器等。
-
硬件控制(无微编码):CDC 6600使用硬件直接控制指令调度,而不是通过微编码控制,这使得指令执行更快。
-
指令调度的动态调度机制(Scoreboard):引入了一个动态调度机制,称为Scoreboard,用于管理指令的执行顺序,并处理资源冲突。
-
十个外设处理器用于输入/输出:CDC 6600还配备了十个外围处理器,负责处理I/O操作。这些处理器为多线程12位整数ALU,专门用于处理输入/输出任务,以提高整体系统效率。
-
极快的时钟频率:CDC 6600的时钟频率为10 MHz,这在当时是非常高的,尤其是在浮点加法可以在4个时钟周期内完成。
-
>400,000个晶体管,使用氟利昂冷却系统:该计算机使用超过40万个晶体管,占地面积为750平方英尺,重5吨,耗电150千瓦。它使用一种创新的基于氟利昂的冷却系统来保持计算机在高性能下的稳定运行。
- 五年内世界最快的计算机:从1964年到1969年,CDC 6600保持了世界最快计算机的头衔,直到CDC 7600的出现。总共销售了100多台,每台售价在700万到1000万美元之间。
CDC 6600的存取/存储架构
CDC 6600采用了一种存取/存储(Load/Store)架构,其指令集独立处理三种不同类型的寄存器:
- 8个60位数据寄存器(X寄存器)
- 8个18位地址寄存器(A寄存器)
- 8个18位索引寄存器(B寄存器)
所有算术和逻辑指令都是寄存器到寄存器的操作,指令格式为15位,具体如下:
-
寄存器到寄存器指令:这类指令的格式由6位操作码和三个3位寄存器地址字段组成。其典型操作为:
Ri ← Rj op Rk
,即从两个源寄存器中读取操作数并将结果写回目标寄存器。 -
存取指令(30位):与存储器相关的指令需要30位,其中6位为操作码,3位为索引寄存器,18位为偏移量(立即数)。其操作格式为:
Ri ← M[Rj + disp]
,即从存储器中取数或将数存入存储器。
特别是,操作寄存器1到5会触发载入操作,而操作寄存器6和7会触发存储操作,这对向量计算非常有用。
CDC 6600 数据通路(Datapath)
CDC 6600的设计采用了高度并行化的结构,能够高效处理复杂的运算需求。其数据通路架构如下:
-
中央内存:CDC 6600拥有128K字的中央内存,划分为32个内存银行,每个周期为1微秒。这样的内存架构允许多个并行访问,减少了内存瓶颈。
-
操作数寄存器(X寄存器):有8个60位的操作数寄存器,专门用于存储数据和操作数。指令的操作数通过这些寄存器传递给功能单元,并将结果写回寄存器。
-
地址寄存器(A寄存器)和索引寄存器(B寄存器):CDC 6600使用8个18位的地址寄存器和8个18位的索引寄存器。地址寄存器用于存储内存地址,而索引寄存器则用于生成有效地址,以实现有效的内存操作。
-
功能单元:CDC 6600配备了10个功能单元,包括浮点和整数运算单元。这些功能单元非流水线化,允许指令并行执行,极大提升了处理速度。
-
指令堆栈:该处理器还具有一个8个60位的指令堆栈,用于存储和管理指令的执行流程。
CDC 6600 向量加法示例
向量加法是一种典型的并行运算示例,在CDC 6600上可以通过循环和寄存器操作高效实现。以下是一个向量加法的汇编代码片段:
B0 ← -n // 将B0寄存器初始化为向量大小的负值
loop: JZE B0, exit // 如果B0为0,则跳出循环
A0 ← B0 + a0 // 加载第一个向量的地址(索引计算)
A1 ← B0 + b0 // 加载第二个向量的地址(索引计算)
X6 ← X0 + X1 // 将两个向量元素相加,结果存入X6寄存器
A6 ← B0 + c0 // 计算存储结果的目标地址
B0 ← B0 + 1 // 索引递增,准备处理下一个元素
jump loop // 跳回循环开始,处理下一个向量元素
在这个代码示例中:
- Ai(地址寄存器):用于存储内存地址。
- Bi(索引寄存器):用于计算内存访问的索引。
- Xi(数据寄存器):用于存储向量数据的具体值。
向量加法在CDC 6600上的实现利用了寄存器和内存操作,通过流水线处理可以在多个时钟周期内并行完成运算。
CDC6600 的指令集架构(ISA)为简化高性能实现而设计
CDC6600 的指令集架构(ISA)是为了最大限度地简化高性能计算的实现,主要体现在以下几个方面:
-
三地址、寄存器到寄存器的ALU指令:CDC6600采用三地址的寄存器到寄存器的ALU操作指令,这使得流水线化实现更加简单。每条指令只需检查3个位的寄存器指定字段以检测依赖性,没有隐含的输入或输出依赖性,从而减少了指令之间的耦合和复杂性。
-
地址寄存器(Ar)与数据寄存器(Xr)的解耦:地址寄存器的设置与从数据寄存器中检索值解耦,这极大简化了内存访问并发操作的实现。地址更新指令不仅更新了地址寄存器,同时也隐含执行了内存操作,这样的软件设计允许在实际使用地址值之前安排加载地址寄存器的操作,能够在期间插入独立的指令。
-
并行、非流水线化的功能单元:CDC6600 拥有多个并行的、非流水线化的功能单元,例如同时使用的两个乘法器。这种设计使得机器能够并行执行多个运算,显著提高了计算效率。
-
后继机型 CDC7600 的改进:CDC7600 进一步改进了功能单元的设计,采用了流水线化的功能单元,这种设计思路也为后来的RISC架构设计奠定了基础。
IBM 关于 CDC6600 的备忘录
1963年8月,IBM首席执行官Thomas Watson Jr. 针对CDC6600系统发表了内部备忘录。该备忘录指出:
“上周,Control Data 宣布推出6600系统。我了解到开发该系统的实验室中仅有34人,其中14人为工程师,4人为程序员,甚至包括清洁工。而在我们公司庞大的开发活动中,竟然让世界上最强大的计算机被其他公司推出,我无法理解我们如何失去行业领导地位。”
对此,Seymour Cray幽默地回应道:“看来Watson先生自己已经回答了他的问题。”
这段对话反映了CDC6600团队的小规模、高效开发模式,尤其是在对比IBM庞大的开发团队时,凸显了Cray和他的团队在高性能计算领域的独特创新能力。
计算机架构术语
在计算机架构中,有几个核心术语用于描述处理器执行指令的不同性能指标:
- 延迟 (Latency):指从操作开始到完成(从启动到结果可用)的时间,通常以秒或周期为单位。
- 带宽 (Bandwidth):表示每秒或每周期能够执行的操作数量,通常以操作/秒或操作/周期为单位。
- 占用时间 (Occupancy):指功能单元在执行操作时被占用的时间,通常与结构性冒险(例如资源冲突)相关。
注意:对于单一功能单元的关系:
- 占用时间可以远小于延迟——这可以通过流水线化设计来实现,使得每个周期都能启动一个新的操作。
- 占用时间也可以大于延迟——这是当某些操作可能阻塞功能单元并延迟后续操作时发生的。
- 带宽可以大于 1/延迟——这通常意味着系统能够在功能单元的延迟内启动多个操作。
- 带宽也可以小于 1/延迟——当资源冲突或流水线气泡导致功能单元不能充分利用时,这种情况会发生。
复杂流水线控制中的问题
在复杂流水线控制中,面临的一些主要问题包括:
- 执行阶段的结构性冲突:当某些FPU或内存单元没有流水线化时,可能需要多个周期完成操作,导致冲突。
- 回写阶段的结构性冲突:由于不同功能单元的延迟不同,可能会在写回阶段发生冲突,尤其是在多个功能单元同时尝试写入寄存器文件时。
- 乱序写入冒险:由于不同功能单元具有不同的延迟,可能会导致乱序写入,破坏数据一致性。
- 异常处理:在流水线中发生异常时,如何有效处理成为一个关键问题。
图示展示了不同功能单元(ALU、存储器、浮点加法器、浮点乘法器等)在复杂流水线中的交互及调度问题。
CDC6600 的计分板机制
CDC6600 通过计分板(Scoreboard)机制实现了动态指令调度和资源管理,其主要特点包括:
- 指令顺序调度:指令按顺序分派到功能单元,但前提是没有结构性冒险(资源冲突)或WAW(写后写)冒险。如果遇到结构性冲突,指令将停顿,直到有空闲的功能单元。
- 处理RAW冒险:指令在执行前会等待所需的输入操作数,以避免读后写(RAW)冒险。系统支持乱序执行,只要满足操作数的准备条件即可。
- 处理WAR冒险:当功能单元的结果需要写入寄存器时,指令会等待输出寄存器被前面的指令读取完成,以避免写后读(WAR)冒险。功能单元会保留结果,直到可以安全写入寄存器。
这种设计允许CDC6600在乱序执行的基础上,保证指令执行的正确性与资源的高效利用。
更复杂的顺序执行流水线
在更复杂的顺序执行流水线中,主要处理了操作延迟不一致的问题。所有操作在回写阶段(W阶段)统一进行,这样避免了因操作延迟差异导致的回写冲突。通过延迟回写,确保每个周期都能有一条指令进入流水线并完成。系统使用旁路(Bypassing)技术来解决单周期整数运算的性能下降问题。以下是一些关键点:
- 延迟回写:所有操作在回写阶段的延迟一致,以确保流水线的顺利进行。
- 旁路(Bypassing):在某些情况下,单周期的整数运算通过旁路技术直接跳过延迟的回写,避免流水线停顿。
- 流水线暂停:对于长延迟的操作(如除法、缓存未命中等),流水线会暂停,直到操作完成。
- 异常处理:异常在提交点统一处理,确保程序执行的正确性。
该流水线示例中包含多种功能单元,包括加法器(FAdd)、乘法器(FMul)和非流水线化的除法器(FDiv)。
顺序超标量流水线
顺序超标量流水线在每个周期获取两条指令,同时发射一条整数或内存指令和一条浮点指令,从而增加吞吐量。这种方法相对廉价,是提高处理器性能的一种有效方式,常见于 Alpha 21064(1992年)和 MIPS R5000(1996年)等处理器。以下是其特点:
- 同时获取与发射:每个周期获取两条指令,并发射给不同的功能单元进行并行执行。
- 混合指令类型:可以同时发射一条整数/内存指令和一条浮点指令,从而最大化功能单元的使用。
- 可扩展性:通过增加更多的功能单元(例如,4发射超标量的UltraSPARC和Alpha 21164),可以进一步增加系统的指令吞吐量,但这也会带来寄存器文件端口和旁路成本的急剧上升。
这些机制的设计使得在顺序执行的同时,实现了一定的并行化,从而提高了处理器的执行效率。
顺序执行流水线中的双ALU阶段
MC68060的整数单元流水线包含两个ALU阶段,能够在地址计算和内存访问后分别执行ALU操作。流水线设计展示了如何通过增加ALU阶段来加速运算,并且在保持顺序执行的同时提升处理器的效率。具体结构如下:
- 地址计算(EA阶段):在内存访问前,流水线会先计算内存地址,以便准备好数据存取。
- 内存访问(MEM阶段):地址计算完成后,内存访问阶段负责从数据缓存中读取或者写入数据。
- 整数ALU执行(INT EX阶段):在内存访问后,整数ALU会对获取的数据执行运算任务。这样保证了ALU操作在有数据之后才进行,减少了等待时间。
通过这样的设计,流水线中可以进行更高效的指令调度,避免了内存访问和运算操作的冲突,提高了整体系统的吞吐量。
MC68060的动态ALU调度
MC68060使用动态ALU调度机制来提高指令的并行执行效率。在这个设计中,ALU操作和内存访问可以重叠,允许ALU在内存访问之后直接进行计算。下图展示了该动态调度的执行方式:
- 指令流:例如,RISC-V风格汇编代码中可以看到ALU和内存操作交替进行,例如指令
add x1, x1, 24(x2)
,该指令会先计算地址,然后再进行加法操作。 - 流水线图:展示了多个ALU阶段和内存访问阶段是如何交错排列的,避免了流水线阻塞。特别是指令间的旁路操作使得指令可以在前面的指令结果完成之前启动,进一步提高了性能。
这种调度方式是现代顺序执行RISC流水线设计中的常见技巧,尽管没有寄存器-内存操作,但它能够通过巧妙的调度减少流水线中的停顿,优化处理器性能。