[Mono-list] More .NET and mono floating point inconsistencies
ddambro
ddambro at gmail.com
Sat Feb 21 21:06:11 EST 2009
Kornél,
Thank you for looking into this issue for me. After adding a few more
explicit float conversions and removing some temporary variables, I was able
to create a version of my program that runs the same on both mono
(svn127604) and .NET. However, I am interested in what you said about
doubles. If I'm understanding correctly, if I use doubles instead of floats
I shouldn't have to worry about these rounding inconsistencies? I think we
started with doubles, but moved to floats because they were supposedly
faster, but if what you say is true, I might try and change everything over
when I have time. Checking Google only reveals that there is some conflict
as to if floats are faster than doubles in C#. Plus if I ever decide to use
the SIMD instructions, I can only do half as much work at a time. But even
if there is a performance loss it might be worth it to avoid constantly
having to test new versions for .NET/mono compatibility.
David
Kornél Pál wrote:
>
> David,
>
> I've evaluated your test cases and found that the behavior exposed by
> your tests cases is not a bug.
>
> For the first sight this seems to be a bug is MS.NET, but it isn't a bug
> of MS.NET either.
>
> ECMA specs (part3, 1.1.1 Numeric data types) explicitly state the
> following:
>
> When a floating-point value ... is put in a storage location, it is
> automatically coerced to the type of the storage location. ... However,
> the value might be retained in the internal representation for future
> use, if it is reloaded from the storage location without having been
> modified. ... This freedom to carry extra precision is not permitted,
> however, following the execution of an explicit conversion (conv.r4 or
> conv.r8) ...
>
> This means that unlike integer variables, floating point store/load
> pairs are not (necessarily) cause conversion.
>
> On the other hand if you need deterministic behavior, you should issue
> an explicit conv.r4 (x = (float)y; in C#) because this is an
> implementation detail of the current MS JIT compiler that may change in
> the future even in that compiler.
>
> Although ECMA specs permit the native float type to have additional
> precision, you will most likely never notice the same behavior with
> double (float64), because both Mono and MS.NET configure the FPU to
> round each arithmetic operations to 64-bits.
>
> Also note that there is no performance gain from using float (float32),
> because the FPU still operates in 64-bit mode that has to be converted
> to 32-bits. As a result if you want performance you shouldn't use
> float32 at all.
>
> A simplified test case:
> float f1=200;
> float f2=162.980057f;
> float f3 = (1 - (f2 / f1));
> float f4 = f3*f3;
> Console.WriteLine(f4.ToString("R", CultureInfo.InvariantCulture));
>
> Adding an extra conversion you will get the behavior of Mono on MS.NET
> as well:
> float f1=200;
> float f2=162.980057f;
> float f3 = (float)(1 - (f2 / f1));
> float f4 = f3*f3;
> Console.WriteLine(f4.ToString("R", CultureInfo.InvariantCulture));
>
> Kornél
>
> Rodrigo Kumpera wrote:
>> I have commited the fixed from Kornél for all bugs that have tests.
>>
>> On Fri, Feb 20, 2009 at 12:14 AM, ddambro <ddambro at gmail.com
>> <mailto:ddambro at gmail.com>> wrote:
>>
>>
>> Hi,
>>
>> Thanks for looking into my issues. I hope my post didn't come across
>> as
>> rude or anything, I was really just looking to ask if it was better
>> to post
>> issues here or directly to Bugzilla. I'm sure there are far more
>> important
>> issues than my weird floating point inconsistencies.
>>
>> For the curious, I am an AI researcher working on Evolutionary
>> Computation.
>> I tend to use Windows and .NET to run my code, but my research group
>> has
>> several large computing clusters that could massively speed up my
>> experiments, but they only run Linux. Also academia tends to shy
>> away from
>> "Windows Only" software, so if I can say "Runs in Linux" when I
>> release my
>> code to the public, it's a pretty big boon for me as well as the
>> people who
>> want to run it. However, because of the floating point issues
>> described,
>> experiments run on mono are not compatible with experiments run on
>> .NET, as
>> over the course of a simulation, the small errors propagate over
>> thousands
>> of time steps into large differences in the final AI behavior.
>> Thus, if I
>> used both mono and .NET, not only would I have to be mindful of which
>> experiment was run on which platform when I do analysis and
>> demonstrations,
>> but when I release my results to the public I would also have to mark
>> arbitrary sets of experiments as "mono only" or ".NET only."
>>
>>
>> Kornél Pál wrote:
>> >
>> > Hi,
>> >
>> > Thanks for the test cases, I'll invetigate these as well and try
>> to fix
>> > them.
>> >
>> > The best way to get bugs fixed is to produce test cases and
>> report them
>> > in buzilla.
>> >
>> > You can help more if you are able to provide a patch to fix the
>> bugs.
>> >
>> > Note that for some reasons Novell guys seem to ignore this bug
>> mostly
>> > because they have other things to do and their approval is
>> required for
>> > these changes.
>> >
>> > Could you please describe your scenario (application name,
>> purpose, etc.
>> > if they are public) where you need these floating point roundings
>> and
>> > describe why these bugs are critical for you.
>> >
>> > Providing some description may raise component owners' attention.
>> >
>> > Kornél
>> >
>> > ddambro wrote:
>> >> I previously posted about some differences I noticed between the
>> floating
>> >> point math in .NET and mono
>> >>
>>
>> http://www.nabble.com/Mono-and-.Net-Floating-Point-Inconsistencies-to21428695ef1367.html
>> >> here . The bug report can be found
>> >> https://bugzilla.novell.com/show_bug.cgi?id=467201 here . The
>> patch
>> >> provided (Thank you!) fixes several issues I was encountering,
>> but
>> >> unfortunately it led me to discover a couple more. The
>> following two
>> >> code
>> >> samples were tested x86 machines using Linux mono 2.2 with the
>> patch
>> >> found
>> >> in the bug report, a clean Windows mono 2.0.1, and the latest
>> version of
>> >> .NET targeting 3.0 framework and x86.
>> >>
>> >> ---
>> >> 1.
>> >>
>> >> using System;
>> >> using System.Runtime.CompilerServices;
>> >>
>> >> class Testing
>> >> {
>> >> [MethodImpl(MethodImplOptions.NoInlining)]
>> >> public static void Main()
>> >> {
>> >> float f1=200;
>> >>
>> >> float distance=Distance(300, 500, 387.5f, 362.5f);
>> >>
>> >> float dist = 1 - (distance / f1);
>> >>
>> >> float distSqud = dist * dist;
>> >>
>> >> Console.WriteLine(distSqud.ToString("R"));
>> >>
>> >> foreach (byte b in BitConverter.GetBytes(distSqud))
>> >> Console.WriteLine(b);
>> >>
>> >> }
>> >>
>> >> public static float Distance(float x1, float y1, float x2,
>> float y2)
>> >> {
>> >> float xDist = x1 - x2;
>> >> float yDist = y1 - y2;
>> >> float dist = (float)Math.Sqrt(xDist * xDist + yDist *
>> yDist);
>> >> return dist;
>> >> }
>> >>
>> >> On .NET this code produces:
>> >> 0.0342619047
>> >> 54
>> >> 86
>> >> 12
>> >> 61
>> >>
>> >> and on mono it produces:
>> >> 0.03426191
>> >> 55
>> >> 86
>> >> 12
>> >> 61
>> >>
>> >> ---
>> >> 2.
>> >>
>> >> using System;
>> >> using System.Runtime.CompilerServices;
>> >>
>> >> class Testing
>> >> {
>> >> [MethodImpl(MethodImplOptions.NoInlining)]
>> >> public static void Main()
>> >> {
>> >> float distance = Distance(616.161255f, 391.2928f,
>> 550.8382f,
>> >> 131.006973f);
>> >> Console.WriteLine(distance.ToString("R"));
>> >>
>> >> foreach (byte b in BitConverter.GetBytes(distance))
>> >> Console.WriteLine(b);
>> >> }
>> >>
>> >> public static float Distance(float x1, float y1, float x2,
>> float y2)
>> >> {
>> >> float xDist = x1 - x2;
>> >> float yDist = y1 - y2;
>> >> float dist = (float)Math.Sqrt(xDist * xDist + yDist *
>> yDist);
>> >>
>> >> Console.WriteLine(dist.ToString("R"));
>> >>
>> >> foreach (byte b in BitConverter.GetBytes(dist))
>> >> Console.WriteLine(b);
>> >>
>> >> return dist;
>> >> }
>> >> }
>> >>
>> >> On .NET this code produces:
>> >> 268.3576
>> >> 198
>> >> 45
>> >> 134
>> >> 67
>> >> 268.3576
>> >> 198
>> >> 45
>> >> 134
>> >> 67
>> >>
>> >> and on mono it produces:
>> >> 268.357635
>> >> 199
>> >> 45
>> >> 134
>> >> 67
>> >> 268.357635
>> >> 199
>> >> 45
>> >> 134
>> >> 67
>> >>
>> >> ---
>> >> These seem to be very similar to the issues I was encountering
>> before,
>> >> but
>> >> they are not fixed by the patch. What is the best way to
>> resolve these
>> >> inconsistencies?
>> >>
>> >> Thanks,
>> >> David
>> > _______________________________________________
>> > Mono-list maillist - Mono-list at lists.ximian.com
>> <mailto:Mono-list at lists.ximian.com>
>> > http://lists.ximian.com/mailman/listinfo/mono-list
>> >
>> >
>>
>> --
>> View this message in context:
>>
>> http://www.nabble.com/More-.NET-and-mono-floating-point-inconsistencies-tp22018718p22114104.html
>> Sent from the Mono - General mailing list archive at Nabble.com.
>>
>> _______________________________________________
>> Mono-list maillist - Mono-list at lists.ximian.com
>> <mailto:Mono-list at lists.ximian.com>
>> http://lists.ximian.com/mailman/listinfo/mono-list
>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Mono-list maillist - Mono-list at lists.ximian.com
>> http://lists.ximian.com/mailman/listinfo/mono-list
> _______________________________________________
> Mono-list maillist - Mono-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
>
>
--
View this message in context: http://www.nabble.com/More-.NET-and-mono-floating-point-inconsistencies-tp22018718p22142912.html
Sent from the Mono - General mailing list archive at Nabble.com.
More information about the Mono-list
mailing list