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 <ddam...@gmail.com >> <mailto:ddam...@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@lists.ximian.com >> <mailto:Mono-list@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@lists.ximian.com >> <mailto:Mono-list@lists.ximian.com> >> http://lists.ximian.com/mailman/listinfo/mono-list >> >> >> >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> Mono-list maillist - Mono-list@lists.ximian.com >> http://lists.ximian.com/mailman/listinfo/mono-list > _______________________________________________ > Mono-list maillist - Mono-list@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. _______________________________________________ Mono-list maillist - Mono-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-list