Likely to be a bit unlikely

Two new C++20 attributes to guide the compiler with branching: [[likely]] and [[unlikely]]. For the moment, there are reports of being useful, including in the standard lib. But maybe not always so - here is a failure case. This failed me at least for clang 14 & gcc 11.4 (same ballpark results). I ran a simple test1:

  • trying to guide the compiler over a simple if/else branch
  • the test data is tilted two thirds on one branch to one third on the other (dataset A)
  • line (1) shows the results for the unadorned code, with dataset A. This is what is supposed to tbe improved.
  • line (2) shows how much it can be improved (100%, double the trhoughput) if the data changes such that the CPU’s branch predictor is at full guess (dataset B)
  • but the attributes, applied right (4) or wrong (5) have no effect over (1). Nada.
  • but can it be improved in code? Yes. Line (3) shows Pikus’ branchless coding techniques applied for dataset A. It extracts two third of the branch predictor’s max performance - as expected since data is tilted two thirds.
    --------------------------------------------------------------------------------------------
    Benchmark                                 Time             CPU   Iterations items_per_second
    --------------------------------------------------------------------------------------------
(1) BM_branched2/4194304               13171485 ns     13167412 ns           49       318.537M/s
(2) BM_branched2_predicted/4194304      5838291 ns      5836906 ns          122       718.583M/s
(3) BM_branchless2/4194304              6861796 ns      6861647 ns          104       611.268M/s
(4) BM_branched2_unlikely_ok/4194304   13556063 ns     13555432 ns           53       309.419M/s
(5) BM_branched2_unlikely_KO/4194304   13514676 ns     13513525 ns           53       310.378M/s

There is some hope though: cppreference2 shows an 18% improvement, for some compilers, with the attributes on (and with a totally different use case):

[v11.4 -O3 : 18% improvement] g++   
Time: 0.470174 sec (with attributes)
Time: 0.555561 sec (without attributes)
Time: 0.263195 sec (std::cos)

[v14 -O3 : 2.2% improvement] clang++  
Time: 1.850241 sec (with attributes)
Time: 1.817005 sec (without attributes)
Time: 0.835945 sec (std::cos)

Written on January 3, 2024