学习可能()和不太可能()编译器提示的样本

时间:2010-04-29 16:03:17

标签: c gcc optimization likely-unlikely

如何向学生展示likelyunlikely编译器提示(__builtin_expect)的可用性?

你能编写一个示例代码,这些代码比较没有提示的代码会快几倍。

2 个答案:

答案 0 :(得分:22)

这是我使用的那个,斐波那契数字的一个非常低效的实现:

#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <assert.h>

#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)

uint64_t fib(uint64_t n)
{
    if (opt(n == 0 || n == 1)) {
        return n;
    } else {
        return fib(n - 2) + fib(n - 1);
    }
}

int main(int argc, char **argv)
{
    int i, max = 45;
    clock_t tm;

    if (argc == 2) {
        max = atoi(argv[1]);
        assert(max > 0);
    } else {
        assert(argc == 1);
    }

    tm = -clock();
    for (i = 0; i <= max; ++i)
        printf("fib(%d) = %" PRIu64 "\n", i, fib(i));
    tm += clock();

    printf("Time elapsed: %.3fs\n", (double)tm / CLOCKS_PER_SEC);
    return 0;
}

使用GCC进行演示:

~% gcc -O2 -Dopt= -o test-nrm test.c
~% ./test-nrm
...
fib(45) = 1134903170
Time elapsed: 34.290s

~% gcc -O2 -Dopt=unlikely -o test-opt test.c
~% ./test-opt
...
fib(45) = 1134903170
Time elapsed: 33.530s

少了几百毫秒。这个增益是由程序员辅助的分支预测引起的。

但是现在,对于程序员应该做的事情而言:

~% gcc -O2 -Dopt= -fprofile-generate -o test.prof test.c
~% ./test.prof 
...
fib(45) = 1134903170
Time elapsed: 77.530s  /this run is slowed down by profile generation.

~% gcc -O2 -Dopt= -fprofile-use -o test.good test.c
~% ./test.good
fib(45) = 1134903170
Time elapsed: 17.760s

通过编译器辅助运行时分析,我们设法从原来的34.290s减少到17.760s。比程序员辅助的分支预测要好得多!

答案 1 :(得分:-1)

来自此博客post。我认为可能性和可能性大多已过时。非常便宜的CPU(在示例中为ARM Cortex A20)具有分支预测变量,并且无论采用跳转还是不采用跳转都不会受到影响。当您介绍可能/不太可能的结果时,结果将相同或较差(因为编译器生成了更多指令)。