CPU branch

Branch Prediction

CPU流水线可大致划分为4个阶段:指令预取、指令解码、执行和结果回写。

Branch Prediction,即分支预测,目的是保证大部分时间下CPU流水线都处于满负荷状态,保证正在执行的线程以最高效率运行。

当程序代码出现条件分支语句时,条件分支语句的下条指令直到条件结果计算完毕后才能确定。在结果计算完毕前,CPU流水线都无法进行指令预取和指令解码(这是因为无法确定下一条指令),也就是流水线stall了。为了解决流水线stall,提升执行效率,CPU的分支预测硬件模块在条件结果计算完毕前,根据程序的历史运行记录,预判下一条指令的位置并将其应用于流水线。 如果条件结果计算符合预期或者说预判正确,CPU的流水线就不会stall,执行效率最高。

引入分支预测后,CPU流水线就会有一定几率不stall,提升了执行效率,特别地,当程序编写时有意迎合CPU分支预测机制,那么程序就能高效的执行,例如对一个int数组内大于100的元素进行操作,那么一个已排序的数组跟一个没有排序的数组执行相同的代码,执行效率显然是已排序数组的情况下高。

for (int i in IntArray)
{
    if (i > 100)
    {
        // do 
    }
}

当这段代码应用于已排序的数组时,CPU分支预测失败的情况(也就是说流水线stall)可能只发在i满足大于100这个条件的前几次循环里,而大部分时间,CPU的流水线都是满载运行。如果数组没有排序,CPU分支预测失败的情况就会很普遍,代码的运行效率就会下降。

Branch Predication

首先解析SPMD及对应的硬件结构。SPMD就是Single Program Multiple Data,可以理解为SIMD的扩展。在SIMD情况下,对多数据的处理只限于单条指令,而SPMD情况下,程序编写者可以按需要编写一个处理多数据的程序,这个程序在多个线程中并行执行。GPU的Shader程序就是SPMD的一个例子。

硬件结构上,将多个ALU绑定一起,共享一个PC(Program Counter),就能组成一个SPMD运算单元,例如NV GPU的SMX,AMD GPU的CU都是SPMD运算单元。一个SPMD运算单元包含的ALU数量决定了线程的理论最大并行数量。为了简化硬件结构,降低功耗,SPMD运算单元并没有为每个ALU配备分支预测硬件模块,更重要的是,在共享PC前提下,为每个ALU配备分支预测硬件模块对执行效率根本没有任何提升。

条件分支的出现将导致SPMD运算单元内ALU的执行路径不一致。由于这些ALU共享同一个PC,所以,要求ALU并行执行不同路径是不可能的。要在SPMD上实现条件分支,就需要编译器对条件分支程序代码进行等价变换,把不一致的执行路径转换成一致的执行路径,看下面这个例子:

A.原始代码,执行路径不一致
int condition = threadid + 100;
int result = 0;
if (condition > 220)
{
    result += 10;
}
else
{
    result -= 10
}

B.一种可能的转换后的代码

int result = 0;
int condition = threadid + 100;
int temp1 = result + 10;
int temp2 = result - 10;
result = (condition > 220) ? temp1 : temp2;

转换后的代码在每个ALU上的执行路径都一致,不存在条件分支。两个分支都执行,根据条件选择接受哪个分支的结果,就叫Branch Predication分支断定。

Branch Predication需要硬件指令集的支持,支持Branch Predication的指令根据某些状态寄存器的值,执行不一样的逻辑,例如x86的cmov系列指令,又例如某些厂商GPU指令会根据状态寄存器的值选择执行还是NOP(传说中的指令级多态?)

条件传送和条件控制转移
cmov条件传送指令

在这里插入图片描述

在这里插入图片描述
主要是 cmovge 避免了branch跳转。

cmpq指令用来比较%rsi和%rdi中值的大小关系(比较的行为是%rdi - %rsi),将比较结果保存在条件码寄存器中;
下面紧接着的cmovge根据对应条件码的值来执行这条指令,具体行为是如果%rdi >= %rsi,那么将%rdi中的值赋给%rax。

条件传送指令不会提高性能的情况

不过因为条件传送指令需要一开始就将两种情况的结果计算出来,当不需要被执行的分支计算量很大时,这样做显然是不划算的。

只有当两个表达式都很容易计算时,例如表达式分别都只是一条加法指令,它才会使用条件传送。根据我们的经验,即使许多分支预测错误的开销会超过更复杂的计算,GCC还是会使用条件控制转移。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值