2010-04-29 6 views
10

Wie kann ich für Studenten die Verwendbarkeit von likely und unlikely Compiler Hinweise (__builtin_expect) demonstrieren?Lernbeispiel für wahrscheinliche() und unwahrscheinliche() Compiler Hinweise

Können Sie einen Beispielcode schreiben, der mit diesen Hinweisen einige Male schneller ist und den Code ohne Hinweise vergleicht.

+2

http://kerneltrap.org/node/4705 –

+0

@T.J. Crowder, ja. aber ich möchte ein Programmbeispiel, in dem Studenten den Unterschied fühlen können, nicht in Assembler zu lesen. – osgx

+1

@osgx: Sie werden keine solche Probe bekommen, weil es keinen Unterschied gibt. Dies ist die schlimmste, hässlichste Art von nutzloser Mikrooptimierung. –

Antwort

22

Hier ist diejenige, die ich verwende, eine wirklich ineffiziente Umsetzung der Zahlen Fibonacci:

#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; 
} 

Um zu demonstrieren, 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 

Ein paar hundert Millisekunden weniger. Diese Verstärkung ist auf die programmierergestützte Verzweigungsvorhersage zurückzuführen.

Aber jetzt, für das, was sollte der Programmierer wirklich stattdessen tun:

~% 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 

Mit Compiler gestützte Laufzeitprofilierung konnten wir von dem ursprünglichen 34.290s bis 17.760s reduzieren. Viel besser als mit programmer-unterstützter Verzweigungsvorhersage!

+1

Profil verwenden ist die gute Option, aber ich muss zeigen "wahrscheinlich" und "unwahrscheinlich" – osgx

+19

aah, tm = -clock(); tm + = Uhr(); ist schön, ich habe es vorher nicht gesehen, danke! –

+0

Ich denke, was dies zeigt ist, dass "wahrscheinlich" und "unwahrscheinlich" nicht sehr nützlich sind. Vielleicht auch, dass dies eine wirklich schlechte Implementierung von 'fib()' ist ... –