12

コンパイラのヒント( )の使いやすlikelyさを学生にどのように示すことができますか?unlikely__builtin_expect

これらのヒントを使用すると、ヒントなしのコードと比較して数倍高速になるサンプルコードを記述できますか。

4

2 に答える 2

24

これが私が使用しているもので、フィボナッチ数の非常に非効率的な実装です。

#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.290秒から17.760秒に短縮することができました。プログラマー支援の分岐予測よりもはるかに優れています!

于 2010-04-29T16:56:29.503 に答える
-2

このブログ投稿から。ありそうなこととありそうもないことはほとんど時代遅れだと思います。非常に安価なCPU(例ではARM Cortex A20)には分岐予測があり、ジャンプが実行されてもジャンプが実行されなくてもペナルティはありません。可能性のある/可能性の低いものを導入すると、結果は同じか悪いものになります(コンパイラーがより多くの命令を生成したため)。

于 2020-07-06T09:59:10.177 に答える