美文网首页程序员
经典问题之「分支预测」

经典问题之「分支预测」

作者: 清尘闲聊 | 来源:发表于2019-03-22 14:25 被阅读0次

    问题

    来源 :stackoverflow
    为什么下面代码排序后累加比不排序快?

    public static void main(String[] args) {
            // Generate data
            int arraySize = 32768;
            int data[] = new int[arraySize];
    
            Random rnd = new Random(0);
            for (int c = 0; c < arraySize; ++c)
                data[c] = rnd.nextInt() % 256;
    
            // !!! With this, the next loop runs faster
            Arrays.sort(data);
    
            // Test
            long start = System.nanoTime();
            long sum = 0;
    
            for (int i = 0; i < 100000; ++i)
            {
                // Primary loop
                for (int c = 0; c < arraySize; ++c)
                {
                    if (data[c] >= 128)
                        sum += data[c];
                }
            }
    
            System.out.println((System.nanoTime() - start) / 1000000000.0);
            System.out.println("sum = " + sum);
        }
    

    在我电脑上没有排序耗时:10.78390589
    排序后耗时:4.552145206

    出现上面这个时长差异的罪魁祸首就是这段代码 :

    if (data[c] >= 128)
        sum += data[c];
    

    排序后数据的示例:

    T = 表示进入分支
    N = 表示未进入分支
    
    data[] = 0, 1, 2, 3, 4, ... 126, 127, 128, 129, 130, ... 250, 251, 252, ...
    branch = N  N  N  N  N  ...   N    N    T    T    T  ...   T    T    T  ...
    
     = NNNNNNNNNNNN ... NNNNNNNTTTTTTTTT ... TTTTTTTTTT  (容易去预测)
    

    没有排序数据的示例:

    data[] = 226, 185, 125, 158, 198, 144, 217, 79, 202, 118,  14, 150, 177, 182, 133, ...
    branch =   T,   T,   N,   T,   T,   T,   T,  N,   T,   N,   N,   T,   T,   T,   N  ...
    
      = TTNTTTTNTNNTTTN ...   (全是随机数据 - 很难去预测)
    

    假如我们把代码里条件判断换成下面代码:

    int t = (data[c] - 128) >> 31;
    sum += ~t & data[c];
    

    没有排序耗时:2.698193263
    排序后耗时 :2.753661927
    说明没有用到条件判断语句没有排序和排好序的耗时很相近。
    在现代处理器中,都引入了分支预测来提高指令流水线的性能。所以就导致排序后比没有排序快。

    分支预测

    条件分支指令通常具有两路后续执行分支。即不采取(not taken)跳转,顺序执行后面紧挨JMP的指令;以及采取(taken)跳转到另一块程序内存去执行那里的指令。
    是否需要跳转,只有到真正执行时才能确定。如果没有分支预测器,处理器将会等待分支指令通过了指令流水线的执行阶段,才把下一条指令送入流水线的第一个阶段—取指令阶段(fetch stage),这种技术叫做 流水线停顿
    分支预测器就是猜测条件判断会走哪一路,如果猜对,就避免流水线停顿造成的时间浪费。如果猜错,那么流水线中推测执行的那些中间结果全部放弃,重新获取正确的分支路线上的指令开始执行,这导致了程序执行的延迟。

    相关文章

      网友评论

        本文标题:经典问题之「分支预测」

        本文链接:https://www.haomeiwen.com/subject/acjlvqtx.html