How do the likely/unlikely macros in the Linux kernel work and what is their benefit?

后端 未结 10 717
攒了一身酷
攒了一身酷 2020-11-22 12:58

I\'ve been digging through some parts of the Linux kernel, and found calls like this:

if (unlikely(fd < 0))
{
    /* Do something */
}

o

相关标签:
10条回答
  • 2020-11-22 13:20

    As per the comment by Cody, this has nothing to do with Linux, but is a hint to the compiler. What happens will depend on the architecture and compiler version.

    This particular feature in Linux is somewhat mis-used in drivers. As osgx points out in semantics of hot attribute, any hot or cold function called with in a block can automatically hint that the condition is likely or not. For instance, dump_stack() is marked cold so this is redundant,

     if(unlikely(err)) {
         printk("Driver error found. %d\n", err);
         dump_stack();
     }
    

    Future versions of gcc may selectively inline a function based on these hints. There have also been suggestions that it is not boolean, but a score as in most likely, etc. Generally, it should be preferred to use some alternate mechanism like cold. There is no reason to use it in any place but hot paths. What a compiler will do on one architecture can be completely different on another.

    0 讨论(0)
  • 2020-11-22 13:24

    These are GCC functions for the programmer to give a hint to the compiler about what the most likely branch condition will be in a given expression. This allows the compiler to build the branch instructions so that the most common case takes the fewest number of instructions to execute.

    How the branch instructions are built are dependent upon the processor architecture.

    0 讨论(0)
  • 2020-11-22 13:25
    long __builtin_expect(long EXP, long C);
    

    This construct tells the compiler that the expression EXP most likely will have the value C. The return value is EXP. __builtin_expect is meant to be used in an conditional expression. In almost all cases will it be used in the context of boolean expressions in which case it is much more convenient to define two helper macros:

    #define unlikely(expr) __builtin_expect(!!(expr), 0)
    #define likely(expr) __builtin_expect(!!(expr), 1)
    

    These macros can then be used as in

    if (likely(a > 1))
    

    Reference: https://www.akkadia.org/drepper/cpumemory.pdf

    0 讨论(0)
  • 2020-11-22 13:27

    They cause the compiler to emit the appropriate branch hints where the hardware supports them. This usually just means twiddling a few bits in the instruction opcode, so code size will not change. The CPU will start fetching instructions from the predicted location, and flush the pipeline and start over if that turns out to be wrong when the branch is reached; in the case where the hint is correct, this will make the branch much faster - precisely how much faster will depend on the hardware; and how much this affects the performance of the code will depend on what proportion of the time hint is correct.

    For instance, on a PowerPC CPU an unhinted branch might take 16 cycles, a correctly hinted one 8 and an incorrectly hinted one 24. In innermost loops good hinting can make an enormous difference.

    Portability isn't really an issue - presumably the definition is in a per-platform header; you can simply define "likely" and "unlikely" to nothing for platforms that do not support static branch hints.

    0 讨论(0)
提交回复
热议问题