Search Unity

Turning burst on/off returns different result

Discussion in 'Data Oriented Technology Stack' started by tertle, Sep 13, 2019.

  1. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,667
    I hate floats~

    So to start with, I'm not actually sure you'd consider this is a bug but is more of a warning to others as a result of this I wasted hours of extremely tedious debugging.

    Ok, so I had an issue with some really long algorithm that that behaved unexpectedly under rare circumstances, but only with burst enabled. This was super annoying because debugging with burst compiler is very hard and trying to find some input values that triggered the issue was a pain.

    I finally managed to narrow it down and I've even managed to replicate it in a simple unit test.

    Code (CSharp):
    1.                 var a = -2.898688f;
    2.                 const float eps = 0.0000001f;
    3.  
    4.                 if (a < a + eps)
    5.                 {
    6.                     // If burst is not enabled, will follow this path
    7.                 }
    8.                 else
    9.                 {
    10.                     // If burst enabled, will follow this path
    11.                 }
    Reducing eps by 1 magnitude solves all my issues.

    Full unit test.

    Code (CSharp):
    1. using NUnit.Framework;
    2.     using Unity.Burst;
    3.     using Unity.Collections;
    4.     using Unity.Jobs;
    5.     using Unity.Jobs.LowLevel.Unsafe;
    6.     using UnityEngine;
    7.  
    8.     /// <summary>
    9.     /// The BurstComparisonTest.
    10.     /// </summary>
    11.     public class BurstComparisonTest
    12.     {
    13.         // Requires synchronous compilation
    14.         [Test]
    15.         public void Test()
    16.         {
    17.             using (var output1 = new NativeList<int>(Allocator.TempJob))
    18.             using (var output2 = new NativeList<int>(Allocator.TempJob))
    19.             {
    20.                 JobsUtility.JobCompilerEnabled = false;
    21.  
    22.                 new Job { Output = output1 }.Schedule().Complete();
    23.  
    24.                 Debug.Log($"No Burst {output1[0]}");
    25.  
    26.                 JobsUtility.JobCompilerEnabled = true;
    27.  
    28.                 new Job { Output = output2 }.Schedule().Complete();
    29.  
    30.                 Debug.Log($"Burst {output2[0]}");
    31.  
    32.                 Assert.AreEqual(output1[0], output2[0]);
    33.             }
    34.         }
    35.  
    36.         [BurstCompile]
    37.         private struct Job : IJob
    38.         {
    39.             public NativeList<int> Output;
    40.  
    41.             public void Execute()
    42.             {
    43.                 var a = -2.898688f;
    44.                 const float eps = 0.0000001f;
    45.  
    46.                 if (a < a + eps)
    47.                 {
    48.                     // This path not burst
    49.                     this.Output.Add(-1);
    50.                 }
    51.                 else
    52.                 {
    53.                     // This path burst
    54.                     this.Output.Add(1);
    55.                 }
    56.             }
    57.         }
    58.     }
     
    Last edited: Sep 13, 2019
    Griz, Abbrew, Antypodish and 3 others like this.
  2. tim_jones

    tim_jones

    Unity Technologies

    Joined:
    May 2, 2019
    Posts:
    19
    Thanks for flagging this up for people hitting this type of problem in the future.

    You can also customise floating-point handling to some extent using a couple of properties on the [BurstCompile] attribute, specifically FloatPrecision and FloatMode. See the docs for more details about how these work.
     
    brunocoimbra likes this.
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,667
    Something to note is that even using high precision does not help or change anything in this case.