Search Unity

Official Unity.Mathematics available on github

Discussion in 'Entity Component System' started by xoofx, Apr 10, 2018.

Thread Status:
Not open for further replies.
  1. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    I will look into this further and see what we can do. To be clear, in the generated code (below), you're referring to line 12?


    Code (CSharp):
    1.     IL2CPP_EXTERN_C inline  IL2CPP_METHOD_ATTR float math_sin_m7CB1E8DF153CC3E22A6C366F3F5F98571CF77BA9_inline (float ___x0, const RuntimeMethod* method)
    2.     {
    3.         static bool s_Il2CppMethodInitialized;
    4.         if (!s_Il2CppMethodInitialized)
    5.         {
    6.             il2cpp_codegen_initialize_method (math_sin_m7CB1E8DF153CC3E22A6C366F3F5F98571CF77BA9NewAssembly_MetadataUsageId);
    7.             s_Il2CppMethodInitialized = true;
    8.         }
    9.         {
    10.             // public static float sin(float x) { return (float)System.Math.Sin(x); }
    11.             float L_0 = ___x0;
    12.             IL2CPP_RUNTIME_CLASS_INIT(Math_tFB388E53C7FDC6FCCF9A19ABF5A4E521FBD52E19_il2cpp_TypeInfo_var);
    13.             double L_1 = sin((((double)((double)L_0))));
    14.             return (((float)((float)L_1)));
    15.         }
    16.     }
     
    firstuser likes this.
  2. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    1.
    Code (CSharp):
    1. IL2CPP_RUNTIME_CLASS_INIT(Math_tFB388E53C7FDC6FCCF9A19ABF5A4E521FBD52E19_il2cpp_TypeInfo_var);
    Shouldn't be generated at all if class doesn't have static constructor.

    2.
    This may be even more costly as described on https://jacksondunstan.com/articles/4545
    Code (CSharp):
    1. static bool s_Il2CppMethodInitialized;
    2. if (!s_Il2CppMethodInitialized)
    3. {
    4.     il2cpp_codegen_initialize_method (math_sin_m7CB1E8DF153CC3E22A6C366F3F5F98571CF77BA9NewAssembly_MetadataUsageId);
    5.     s_Il2CppMethodInitialized = true;
    6. }
    7.  
    I'm not sure what it does but couldn't simply all
    Code (CSharp):
    1. il2cpp_codegen_initialize_method
    for every method be run at game start?

    3.
    Code (CSharp):
    1. IL2CPP_EXTERN_C IL2CPP_METHOD_ATTR float math_sin_m7CB1E8DF153CC3E22A6C366F3F5F98571CF77BA9 (float ___x0, const RuntimeMethod* method)
    Looks like
    const RuntimeMethod* method
    is not used at all?

    Usage:
    Code (CSharp):
    1. float L_9 = math_sin_m7CB1E8DF153CC3E22A6C366F3F5F98571CF77BA9((2.435f), /*hidden argument*/NULL);
    No idea what /*hidden argument*/ comment means.

    4. Function is not inlined - the biggest performance issue. Maybe all small static methods could be generated as inlined?
     
    firstuser and Vincenzo like this.
  3. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    It's still accessing a static variable on every call.
     
  4. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Yes but at least it doesn't call static method - in my test case that fixed major part of performance problems.
     
  5. Vincenzo

    Vincenzo

    Joined:
    Feb 29, 2012
    Posts:
    146
  6. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    Internally, we've made a change to IL2CPP that runs static constructors eagerly instead of lazily. I haven't yet checked what the performance impact of this is for Unity.Mathematics, but I plan to do this soon. I will report back when I have numbers!
     
    madebynoxc, Vincenzo and Kamyker like this.
  7. Vincenzo

    Vincenzo

    Joined:
    Feb 29, 2012
    Posts:
    146
    So that gets rid of that static bool s_Il2CppMethodInitialized; calls all the time?
    so we can now expect a Math.Sin in code to just inline to:

    1. float L_0 = ___x0;
    2. double L_1 = sin((double)L_0);
    3. return ((float)L_1);

      Or that is still not there?
     
  8. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Don't forget about:
    That's main bottleneck in case of sin.
     
  9. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    This is without burst compilation?
     
  10. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Yes, lack of inline makes that call very slow. As you can see on https://github.com/Unity-Technologies/Unity.Mathematics/blob/master/src/Unity.Mathematics/math.cs most functions already have AggressiveInlining but somehow that's not the case for all of them, see lines 1126 - 1800.

    In burst case it doesn't matter:
     
    glenneroo likes this.
  11. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    There's more:
    This shows how far il2cpp is from maximum possible speed.

    TL;DR

    Code A (used in Mathematics):
    Code (CSharp):
    1. public static float3 operator + (float3 lhs, float3 rhs) { return new float3 (lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); }
    Code B: (used in default Unity)
    Code (CSharp):
    1. public static Vector3 operator +(Vector3 a, Vector3 b)
    2. {
    3.    a.x += b.x;
    4.    a.y += b.y;
    5.    a.z += b.z;
    6.    return a;
    7. }
    Without burst:
    Code A is faster when running without il2cpp.
    Code B is faster when running with il2cpp (as il2cpp is not optimized properly).

    Fortunately Mathematics version have AggressiveInlining making it probably faster in both cases but not as fast as possible :).
     
    CPlusSharp22 likes this.
  12. Aka_ToolBuddy

    Aka_ToolBuddy

    Joined:
    Feb 25, 2014
    Posts:
    550
    Either you misunderstood my post, or I am misunderstanding your TL;DR of it, so here is my own formulation of the TL;DR
    In the following, no Unity.Mathematics or Burst are involved:

    Code A : the default Vector3 operator + implementation
    Code (CSharp):
    1. public static Vector3 operator +(Vector3 a, Vector3 b)
    2. {
    3.     return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
    4. }
    Code B : a custom, optimized, Vector3 operator + implementation
    Code (CSharp):
    1. public static Vector3 operator +(Vector3 a, Vector3 b)
    2. {
    3.    a.x += b.x;
    4.    a.y += b.y;
    5.    a.z += b.z;
    6.    return a;
    7. }
    B-IL-instructions are faster than A-IL-instructions because it avoids calling the constructor. But when those IL instructions are converted to c++ using IL2CPP, B-CPP becomes slower than A-CPP when compiled in a windows desktop IL2CPP build
     
    Last edited: Jun 11, 2020
  13. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    KwahuNashoba likes this.
  14. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    I've done my test and here are my findings:

    1. Aggressive inlining does indeed provide massive performance improvements (around 10x faster) for functions like sin(). We will be fixing this.

    2. The il2cpp change we have internally that runs static constructors eagerly at startup rather than lazily at call time yields about a 15% performance improvement in certain circumstances. We expect method calls on types with static constructors will see some amount of improvement. If the type does not have a static constructor, then you won't see a difference. I plan on adding the new attribute to run static constructors eagerly on all Mathematics types so we can be sure they run at highest possible speed with il2cpp.

    3. The perf improvement described in #2 is only seen on types that have a new attribute on them. During my test, I found that System.Math also suffers from calling static constructors lazily. We will look into adding the new attribute to this type as well, which should remove the IL2CPP_RUNTIME_CLASS_INIT() call that occurs just before calling sin() or whatever other function.
     
  15. Vincenzo

    Vincenzo

    Joined:
    Feb 29, 2012
    Posts:
    146
    Good work guys!

    Isn't there a chance to get il2cpp to work in such a way what it starts to generate SIMD for the maths library like burst?
    What about mathf/Quaternion/vector3 classes?
     
  16. Indiefreaks

    Indiefreaks

    Joined:
    Nov 12, 2012
    Posts:
    89
    Not sure that is the right place to ask but I'm hitting my head to actually understand how to use the cnoise and pnoise methods found in the package... Could you please redirect me to any resource that could be handy? Thanks.
     
  17. oscarAbraham

    oscarAbraham

    Joined:
    Jan 7, 2013
    Posts:
    431
    Hi. Are there any plans to make the attribute for eagerly calling static constructors public? It'd be awesome.

    If that is the case, does that attribute also remove the call to il2cpp_codegen_initialize_method? I don't know if I'm right to think it has something to do with initializing static stuff, it seems to get added when using static members, but it's also added in some other cases that I can't seem to relate to static stuff. That call doesn't seem to slow things too much when performing simple benchmark loops, but it seems to have a significant impact when executing many different methods that have that il2cpp_codegen_initialize_method call in benchmark loops. : ) Thanks.
     
  18. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    I don't want to speak for our VM team (who is in charge of IL2CPP), but it seems like it could be done with quite a bit of effort. My question is, what is the situation where you cannot use burst? Our recommendation would be that you use burst to get the vectorized code generation.
     
  19. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    It will be public in the sense that if you create an attribute with the same name, then in a future version of Unity that supports that attribute, il2cpp will recognize that attribute to run the static constructors at start up rather than lazily at runtime.
     
    oscarAbraham likes this.
  20. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    What about the noise functions are you stuck on? All of this code is based on Stefan Gustavson's work on noise, You can see his demo code here https://github.com/stegu/webgl-noise/blob/master/demo/common/noisedemoMain.frag

    Our implementation is nearly a direct copy/paste of his code and works in basically the same way. The gist is you need to provide some texture coordinate into the function and you get back a scalar value. Across the UV(W) texture space, you will see "noise".
     
  21. CPlusSharp22

    CPlusSharp22

    Joined:
    Dec 1, 2012
    Posts:
    111

    Is there an ETA on this or has it already been fixed?

    Also I want to bring attention to this, I'm finding that Unity.Mathematics can take upwards of 7 seconds to compile just alone with no changes to the package. I'm wondering if there's a way to cache it, but perhaps that's a package manager issue. https://forum.unity.com/posts/6143703/
     
  22. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Works fine for me, I'd say make asmdef in Assets folder and reconnect needed libs manually instead of using "Auto Referenced". That's how I use them as default implementation is unusable
     
  23. CPlusSharp22

    CPlusSharp22

    Joined:
    Dec 1, 2012
    Posts:
    111
    Mathematics has it's it's own.

    EDIT: Sorry, to be clear, compiling in editor is pretty quick. This is building out the player standalone, even with +Script Only Build.
     
    Last edited: Jul 29, 2020
  24. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
  25. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    Profiling shows that compiling Unity.Mathematics takes an incredible amount of time, because of the code generation. If only instead of swizzling a more C# friendly approach was taken this wouldnt have been an issue.

    For example in my toolkit there is a `With` extension method for Vectors, which accepts nullable overrides for the different components. I can just write: `a.With(x: a.z)`, a bit more verbose but acceptable and easy to compile.
     
  26. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    Doesn't using nullables for value types cause them to be boxed? That would annilihate performance, plus wouldn't easily compile with Burst.
     
  27. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    Walter_Hulsebos likes this.
  28. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    Ah, it's just a struct with an extra bool. Good to know, but it sounds like it still wouldn't be as fast as SIMD-based swizzles, since the actual function would have a conditional for each vector component.

    The actual bug here is Unity stubbornly re-compiling packages like Mathematics when it shouldn't.
     
    glenneroo, FlavioIT and sand_lantern like this.
  29. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    You're right that it might not be out of the box, but nothing a bit of static analysis couldnt fix. It could be made SIMD as well.

    Sure, thats one bug. I'm just still a bit salty about some of the design choices.
     
    Last edited: Aug 13, 2020
    CPlusSharp22 likes this.
  30. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
  31. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    Any reason for call linear lerp method for quaternion nlerp but for vectors, linear lerp methods are called lerp ?
    It's confusing :/
     
  32. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    It's not returning the lerp value, but the normalized lerp value.
     
    Sylmerria likes this.
  33. Lieene-Guo

    Lieene-Guo

    Joined:
    Aug 20, 2013
    Posts:
    547
    Because quaternion has another lerp method slerp.
     
  34. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    Equal method of quaternion compares strict float value of each member

    Code (CSharp):
    1.         /// <summary>Returns true if the quaternion is equal to a given quaternion, false otherwise.</summary>
    2.         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    3.         public bool Equals(quaternion x) { return value.x == x.value.x && value.y == x.value.y && value.z == x.value.z && value.w == x.value.w; }
    4.  
    But for Quaternion, == method check dot value which is better for quaternion

    Code (CSharp):
    1.     private static bool IsEqualUsingDot(float dot) => (double) dot > 0.999998986721039;
    2.  
    3.     public static bool operator ==(Quaternion lhs, Quaternion rhs) => Quaternion.IsEqualUsingDot(Quaternion.Dot(lhs, rhs));
    4.  
    So, can this difference be a problem ?
     
  35. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    is there a way to do a clamp magnitude with the mathematics package ?

    I have convert a custom method but there is surely a better way to do that

    Code (CSharp):
    1.  
    2. public static float2 ClampMagnitude(float2 vector, float maxLength)
    3. {
    4.     float sqrMagnitude = math.lengthsq(vector);
    5.  
    6.     if (sqrMagnitude <= (double)maxLength * maxLength)
    7.         return vector;
    8.  
    9.     float num1 = math.sqrt(sqrMagnitude);
    10.     vector /= num1;
    11.     vector *= maxLength;
    12.     return vector;
    13. }
     
    Walter_Hulsebos likes this.
  36. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    At a glance it looks like the hash functions are using cantor pairing. Hard to tell for sure with the literals being used. Can someone confirm?
     
Thread Status:
Not open for further replies.