Search Unity

Burst Hint Likely/Unlikely interesting results

Discussion in 'Burst' started by tertle, Apr 22, 2021.

  1. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Originally posted here: https://forum.unity.com/threads/burst-hint-likely-unlikely-interesting-results.1097533/
    Because I forget there is a specific burst forum completely separate to DOTS.

    Doing some profiling using the Hint Likely/Unlikely intrinsic and I'm not sure what is going on here.

    The code

    Code (csharp):
    1.  
    2. public int GetClosestSegmentNew(float3 position)
    3. {
    4.     // Find the first point in the closest line segment to the path
    5.     float closestDist = DistToSegment(position, this.Path[0].Position, this.Path[1].Position);
    6.     int closestSegment = 0;
    7.  
    8.     for (int i = 1; i < this.Length - 1; i++)
    9.     {
    10.         float dist = DistToSegment(position, this.Path[i].Position, this.Path[i + 1].Position);
    11.  
    12.         if (Hint.Unlikely(dist <= closestDist))
    13.         {
    14.             closestDist = dist;
    15.             closestSegment = i;
    16.         }
    17.     }
    18.  
    19.     return closestSegment;
    20. }
    Using Unlikely hint - the correct choice



    24.22 without hint
    20.97 with hint
    A pretty significant improvement

    Using Likely hint - the wrong hint



    Ok now the results are weird. How is it also faster!? It's not as fast (and I repeat this test a lot of times to confirm and it's consistently a little slower than Unlikely) but it's still significantly faster than not having a hint. How?

    and just to confirm it's not something odd, removing the hint.



    Both tests run the same speed as expected.

    So the bad and naive TLDR would be, just add hints to every condition and things will run faster!
    What I'm trying to understand is what is going on here and how both likely and unlikely on a condition could be faster.
     
    Last edited: Apr 22, 2021
    PutridEx and Lukas_Kastern like this.
  2. tim_jones

    tim_jones

    Unity Technologies

    Joined:
    May 2, 2019
    Posts:
    287
    Hi @tertle - that's an interesting finding! Please could you grab the assembly from the two versions (using Burst Inspector) and paste it here?
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    I don't have the original test but I still have the code unchanged it was based off and just throwing it in a simple job like this (which I believe was identical to what I did for the test except a bunch of iterations.)

    Code (CSharp):
    1. this.Job.WithCode(() =>
    2.     {
    3.         var p = random.NextFloat3();
    4.         result.Value = linePath.GetClosestSegment(p);
    5.     })
    6.     .WithName("Unlikely")
    7.     .Run();
    8.  
    9. this.Job.WithCode(() =>
    10.     {
    11.         var p = random.NextFloat3();
    12.         result.Value = linePath.GetClosestSegment2(p);
    13.     })
    14.     .WithName("Likely")
    15.     .Run();
    16.  
    17. this.Job.WithCode(() =>
    18.     {
    19.         var p = random.NextFloat3();
    20.         result.Value = linePath.GetClosestSegment3(p);
    21.     })
    22.     .WithName("None")
    23.     .Run();
    nets these 3 sets of assembly output from burst inspector

    -edit- actually i do seem to have most of the original test sitting around. I'd just have to setup the alternate cases again but if you want to try repo the performance for yourself let me know and I can maybe bundle it up and send it to you privately.
     

    Attached Files:

    Last edited: May 4, 2021
  4. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    I'm not that great at grokking assembly and I'm only meant to be taking a 5 minute break so I haven't checked this in detail in your case, but one possible explanation for both likely and unlikely hints speeding up code is that they both act as hints that the branch is predictable.

    If the compiler assumes by default that the branch is unpredictable, it will probably create branch free code using masking or conditional moves. This may be less efficient than a well predicted branch that almost always completely skips the work. Telling it that it's either likely or unlikely will encourage it to compile to an actual branch.

    p.s. if you're optimising that code, you could probably switch from distance to squared distance and eliminate the sqrts in the tight loop.
     
    apkdev likes this.
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Good observation. If I recall correctly I think the distance value used to be returned and used which is why it was used. However it is not anymore so there is no reason to not remove the sqrt.
     
  6. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    You could still work in squared distances if you're returning it! Keep it squared during the loop, then sqrt once when returning.