-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bizarre decimal-to-double behavior difference on same machine, same code #102149
Comments
Tagging subscribers to this area: @dotnet/area-system-numerics |
The actual output doesn't change. What has changed is the formatting of double. You can use See also #59982 etc. |
Right, I will check that. The weird part isn't how the number converts, but how it converts, or formats, differently on the same machine, though. But I will check the bits to see if they are identical. Also, it does seem to be related to Dynatrace in some way, which I'll also check. |
@huoyaoyuan it seems it's not just the string formatting that's different. The raw bits in the "4" case are C0B20BBD8939BE6E whereas they are C0B20BBD8939BE6F in the "5" case. The abnormal case does, however, stop when Dynatrace is not used, for some reason. |
What's your .NET Framework version installed on your system? I can't reproduce it with .NET Framework 4.8.1. |
I assume we have .NET 4.8 installed, I don't know. Whatever comes with Windows 10 version 14393 (which is from 2016, "Redstone"). But all these programs are .NET Core (.NET 8). The installed runtimes on the machine are
|
All right, the situation with "the problem disappered when Dynatrace was removed" isn't quite that clear. It's much more bizzare: When the server is started, and the test is done, the normal result is returned (the call is made from a client, which provides the number; the server sends back a long string with output in various formats including the raw bits). When the test is repeated, without restarting the server (which runs as a Windows service), the correct value is still returned... for a while. After about 1-2 minutes, it starts returning the abnormal value (i.e. the "5" case) instead, from the same running program. |
Looks like a problem with tiered compilation. Repro:
It starts with |
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
@jkotas that sounds promising. I can't exactly reproduce that myself (I also tried with variously switching tiered compilation off or asking for aggressive optimization for the method, or nothing at all), but would the cause then be that the two JIT compilers have a behaviroial difference? |
Try:
Yes, it looks like a bug in the JIT compiler. |
@EgorBo, PTAL. |
From a quick look, it looks to be somewhere in CoreLib behaving differently for R2R and Tier0 or Tier1. Most likely |
As a side question, why are you using |
Alright, so looks like the issue is in "unsigned int -> float" conversion difference for AVX512 (JIT) and SSE2 (crossgen) |
Minimal repro: using System;
using System.Runtime.CompilerServices;
class Prog
{
public static unsafe void Main()
{
double dbl = Test(9303915604039947368);
Console.WriteLine(*(ulong*)&dbl);
}
[MethodImpl(MethodImplOptions.AggressiveOptimization |
MethodImplOptions.NoInlining)]
static double Test(ulong x) => x;
} It prints different values with |
; Assembly listing for method Prog:Test(ulong):double (FullOpts)
vcvtusi2sd xmm0, rcx
ret
; Assembly listing for method Prog:Test(ulong):double (FullOpts)
vxorps xmm0, xmm0, xmm0
vcvtsi2sd xmm0, xmm0, rcx
test rcx, rcx
jge SHORT G_M52525_IG03
vaddsd xmm0, xmm0, qword ptr [reloc @RWD00]
G_M52525_IG03:
ret
RWD00 dq 43F0000000000000h @tannergooding does this ring a bell to you? it sounds like AVX512's impl is correct so probably we had a bug in our pre-AVX512 impl? |
#43895 tracks the issue, it's known and something we should fix. It's just been pushed out release after release as "low priority". Given we normalized the |
Right. It's life insurance mathematics. Double is used to do expensive calculations that would take too long with decimal. This isn't a money amount as such. |
Description
I made a dotnet class library with a single method:
I then wrote a small console program that calls this, like this:
I get:
That's fine, I guess, and this can be reproduced on various machines and online dotnet playgrounds. However, on the same machine using the same, previously compiled, class library, but calling it from inside a larger .NET 8-based server we have running there in test, we instead get:
Which amounts to a difference in the LSB in the Int64 representation of the double (using BitConverter). Since this is financial software, people are wondering about this, and I can't explain it. This only seems to happen on this particular machine (and only when invoked via our larger server, using Assembly.Load and IoC).
Reproduction Steps
As described above. We haven't been able to reproduce the abnormal result in any other contexts so far.
Expected behavior
The version ending in 4. Well, it's hard to say. I think the version ending in 5 seems more correct, but every other context, machine and online playground seems to give the one ending in 4.
Actual behavior
When we call the method in the dll from our (ultimately .NET 8 console program started as Windows service), we get the version ending in 5.
Regression?
No response
Known Workarounds
No response
Configuration
The problem happens on the same machine, but the environment is slightly different. Common environment variables that might influence this (but that are present both in the 4 and 5 case):
Environment variables unique to the case where we get the abnormal behavior:
I have tried to manually set the COMPlus variable but it doesn't reproduce the abnormal behavior. I haven't investigated if the tracing can be related.
Other configuration:
.NET 8.0.2
Microsoft Windows 10.0.14393
Both programs run as framework-dependent.
Other information
No response
The text was updated successfully, but these errors were encountered: