zoukankan      html  css  js  c++  java
  • Branch Prediction 与 Branch Predication的区别

        Branch PredictionBranch Predication都是针对程序分支语句影响硬件执行效率而提出的技术。Branch Prediction应用于CPU,目标是保证最高的线程执行效率。Branch Predication应用于SPMD结构的运算设备,这类设备以吞吐量为首要目标,GPU就是这类设备的代表。

    Branch Prediction

        Branch Prediction,即分支预测,目的是保证大部分时间下CPU流水线都处于满负荷状态,保证正在执行的线程以最高效率运行。CPU流水线可大致划分为4个阶段:指令预取、指令解码、执行和结果回写。当程序代码出现条件分支语句时,条件分支语句的下条指令直到条件结果计算完毕后才能确定。在结果计算完毕前,CPU流水线都无法进行指令预取和指令解码(这是因为无法确定下一条指令),也就是流水线stall了。为了解决流水线stall,提升执行效率,CPU的分支预测硬件模块在条件结果计算完毕前,根据程序的历史运行记录,预判下一条指令的位置并将其应用于流水线。如果条件结果计算符合预期或者说预判正确,CPU的流水线就不会stall,执行效率最高。

        如果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情况下,程序编写者可以按需要编写一个处理多数据的程序,这个程序在多个线程中并行执行。GPUShader程序就是SPMD的一个例子。

        硬件结构上,将多个ALU绑定一起,共享一个PC(Program Counter),就能组成一个SPMD运算单元,例如NV GPUSMXAMD GPUCU都是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的指令根据某些状态寄存器的值,执行不一样的逻辑,例如x86cmov系列指令,又例如某些厂商GPU指令会根据状态寄存器的值选择执行还是NOP(传说中的指令级多态?)

        使用Branch Predication转换后的代码,执行时间比条件分支代码长,因为转换后的代码,所有分支都会执行。于是,有人提出了一种类似动态指令融合的技术,在SPMD里既可保留条件分支,也保证执行效率——Dynamic warp formation。

    Dynamic warp formation

        Warp就是线程组threadgroup的意思,是SPMD运算单元的最小并行粒度,最小调度单位(NV称为warpAMD称为wavefront)。例如,NVwarp32线程,就是说,在SPMD运算单元内,每32ALU并行执行相同的指令。也可以把warp看作是一条硬件线程,它的执行宽度为32ALU。相对于CPU的线程,其执行宽度通常为1ALU。当然了,GPU一个ALU的宽度可达4*64 bit,那么,GPU一个warp的宽度就是32*4*64 bit,并且,GPU在同一时间可执行多个warp,所以单比吞吐量,GPUCPU不在一个数量级。

        以下均使用warp表示线程组,并以32线程为一个warp为前提展开。回顾SPMD出现条件分支的情况,例如出现分支A及分支B,那么,warp32个线程既执行分支A也执行分支B,最后,这些线程根据分支条件的结果选择接受A的结果还是接受B的结果。无论如何,总有一部分结果对于这些线程来说是没有意义的。

        把一个warp按分支路径拆分成多个子warp,并行执行,也不会带来任何效率的提升,因为拆分的子warp宽度肯定不够32。如果把这种思路应用于多个warp的话,情况会有所不同,例如warp1warp2warp3执行相同的代码并到达相同条件分支语句,分支将产生路径A和路径B,按路径拆分出的子warp重组成新warp并行执行,分支路径执行完毕后还原为原来的warp,这样就能高效应对条件分支,不会出现没有意义的运算,这就是Dynamic warp formation,更详细的介绍可自行google

  • 相关阅读:
    ActiveMQ 即时通讯服务 浅析
    Asp.net Mvc (Filter及其执行顺序)
    ActiveMQ基本介绍
    ActiveMQ持久化消息的三种方式
    Windows Azure Virtual Machine (27) 使用psping工具,测试Azure VM网络连通性
    Azure China (10) 使用Azure China SAS Token
    Windows Azure Affinity Groups (3) 修改虚拟网络地缘组(Affinity Group)的配置
    Windows Azure Storage (22) Azure Storage如何支持多级目录
    Windows Azure Virtual Machine (26) 使用高级存储(SSD)和DS系列VM
    Azure Redis Cache (2) 创建和使用Azure Redis Cache
  • 原文地址:https://www.cnblogs.com/rickerliang/p/2969893.html
Copyright © 2011-2022 走看看