Identical math code working differently on C# and C++

This topic is 1330 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

So basically I prototyped and developed a math code (for vechicle simulations) in C# and it works perfectly. Now when I port the code to C++

so that I could acces it in a C# environment through a DLL I get some junky behaviour.

For example when I run my physics program, the cars driving wheels start accelerating with no reason and it seems like it's mostly caused by rolling resistance, wich by the way works great in C# environment.

This rolling resistance relys on a value that is received from C# environment (from C# float to c++ float)

Another problem is caused by slip ratio and slip angle, the wheels start shaking at low speeds, wich again does not happen in the C# version.

Slip calcs both rely also on values received from C# environment.

So might the float conversion from C# to C++ be the case?

This stands in my exportFunctions.cpp:

These 2 velocityes are used for the calculations that cause those bug's.

And no I cant share the code, but I can give closer information on how it looks like.

Thanks!

Edit:

Strange part is that this acceleration issue only occurs in Debug build. If I build the dll as a release, then this issue is vanished, but small friction error still remains. Actually it's only causing the smoke to come out of the tires and tireq squal sound to emmit, but physically it seems to be ok.

But I still suspect that there is some sort of a error somewhere, because debug & release should work identically shouldnt they?

Share on other sites

But I still suspect that there is some sort of a error somewhere, because debug & release should work identically shouldnt they?

I know .net/C# can produce different values for floating calculations depending on optimizations made by the JIT (floating point calculations are implicitly converted to double in one case but not the other) . I haven't seen any differences between Debug and Release, but I have seen differences between debugger attached and no debugger attached (see here).

Share on other sites

I have seen differences between debugger attached and no debugger attached (see here).

I think float's size is 4 for both C# and C++ and I'm not sure why'd there be a problem when passing a float from C# to C++
but after looking this I got confirmed, that there can be a difference...

Anyway thanks for explaining.

Share on other sites

Still fighting with this.
After setting the flotaing point model to /fp:fast in my compiler (msvc2010) it should have now get the exact same float's from the dll but the "flickering" issue still remains, and I suspect its from very small values like 3.21-e8 etc. because when the car is stand still, it still causes minimalistic movements.
Now when I pass them to my DLL something gets messed... So maybe its the way I pass them?

Anyway this is how I pass these speccific values in C# side:

namespace Example
[
public class Wheel
{
#region Members
public IntPtr nativeWheelObject;
#endregion Members

public Wheel()
{
return;
}

#region Wrapper methods
#endregion Wrapper methods
}

internal class Sim
{
#region PInvokes
#endregion PInvokes
}
}


This much code I can show.

Share on other sites

What have you done to debug the issue? Can't you set breakpoints on either side of the .net/native transition to verify the values are the same?

Also, what makes you think it's a problem with the interop, rather than with the port of your actual math code?

Share on other sites

I atached the debugger to the program and set the breaking point to where the problem occurs.

c++ lonVel    -0.036019072    float
c# lonVel    -0.029392920    float

As you can see there is a noticable difference. Even after /fp:fast

I also tryed to use the values a double and convert it to float and that didnt work at all. Probably did it wrong anyways.

The reason why I think my math port isnt the case, is that the math is rather simple and straight forward and mostly copy/paste from the C# code. And the actual proof that the transfered values are different.
But I guess the math gets a bit messed aswell because I also transfer the TimeStep from C# and use it in the math calcs.

Share on other sites

Specifying /arch:SSE2 might get you a bit closer.

However, you shouldn't even expect your C# code to produce identical results on all systems - it will almost certainly differ between x86 and x64 systems for example.

Share on other sites

/arch:SSE2

This didnt help also. Saddly I need these 2 values to be correct, otherwise my math calcs will be broken... This numerical chage doesnt seem huge, but it's really huge for my calcs.

Is there any tutorial or a post atleast, on how to pass a small float wit hatleast 90-99% of accuracy from C# environment to c++ environment. And t obe more specific I'm using c# mono.
I dont want to believe that there isnt a way, when there clearly must be a way. Maybe a new custom data type? one that is compatible with C# float's?

I'm really worried because this has been a huge setback in my coding for a while. I cant release my products, because of this. My product works ok in C# but I need to port the code to C++ for security reasons, as you know C# can be easily decompiled.

Share on other sites

perhaps you could try to pass it over the boundary as double and cast it back to float on the C side.

Just to make sure, you are saying that you have a function:

void myCFunction(float value);

On the C side.. and if you call it from C# with a value myCFunction(0.2899344f); you receive something different on the C side?

Edited by kunos

Share on other sites

The main problem isn't passing values to and from C#.

The way the two different languages transform calculations into assembly is different. Most notably in both cases some of the intermediate calculations may be done at a higher precision than you've specified. There will also be small differences in the results from library functions like sin(). In addition C# depending on which CPU it's run on may generate different assembly when it's JITted, so the C# result almost certainly won't be identical between different PCs.

If you want reproducibility integer maths is much easier to do that with.

C++ can also be easily disassembled. It's impossible to keep any calculation you do on a computer secret from the owner of that computer. If this is for something like license key validation you should switch to something based on public key cryptography.

Share on other sites

C++ can also be easily disassembled.

yes but no... in C# you can get back to the names of the functions and variables. Surely in C++ you will still read the names of the function but the code inside will be much harder to reverse engineering. I understand where the OP is coming from because I went through exactly the same decisions.

I wonder if the OP tested the new .NET native.. that might solve the problem without need to leave C# land.

Share on other sites

perhaps you could try to pass it over the boundary as double and cast it back to float on the C side.

Well I tryed it like this:
C#

public void SetVelocity(float lonRoadVelocity,float latRoadVelocity){Sim.Dll_Wheel_SetVelocity(this.nativeWheelObject,lonRoadVelocity,latRoadVelocity);}


C++

    EXPORT_API void Dll_Wheel_SetVelocity(CarWheel* wheel,double lonRoadVelocity,double latRoadVelocity){    wheel->SetVelocity((float)lonRoadVelocity,(float)latRoadVelocity);}


And the result was, that nothing was transfered... the values stayed 0.

And about the question, to be specific I'm not using C, I'm using C++ (the languages should be different)

And currently I'm passing them the way as you described.

Also after some deeper debuging I found out that strangely the difference happens in my wheel class...

void CarWheel::SetVelocity(float lonVel,float latVel)
{
}


So its internal??? C++ float mismatched with C++ float? I'm confused....

Edit:

The above "internal" was a false alarm I guess.

Because I removed the "SetVelocity" method and pass the values directly, wheel->lonRoadVelocity = lonRoadVelocity;

and there still is difference, I think I was just confused,

Debug Results:

		latRoadVelocity	-0.15862428	float
+		wheel	0x1b75e120 {brake={...} tire={...} suspension={...} ...}	CarWheel *



After /arch:SSE2 and /fp:fast the difference actually is notably smaller. In this case for some reason it only occurs in "latRoadVelocity".

"lonRoadVelocity" seems to be 1:1 o nevery frame I debuged, so I'm getting closer

Share on other sites

hm weird.. in C# if the signature of the function requires a double, it shouldn't compile if you pass a float to it... did you change the signature of the DLL_Set_velocity on the C# side?

Share on other sites

I just noticed there is a inacuracy issue with floats in C++, flaots in C# (atleast in mono) stay the same and are pretty good to work with

but in C++ a float of 0.0091 is actually 0.0091000004 ... that 4 in the end can make a math calc result in wrong calculations.

While "lonRoadVelocity" seems to pass normally now, I dont understnd why the "latRoadVelocity" has a offset, when I pass it the same way...

in C# if the signature of the function requires a double

Sounds right indeed. Maybe it's because I'm using mono?
Anyway when passing a float instead of double, the values stay 0, but when I cast the float to double in C# and pass the double ... well saddly nothing changes.

But like I mentioned, the "lonRoadVelocity" seems to now be 1:1, but for some strange reason the "latRoadVelocity" has an offset.

Edit:

Here are some debug results in a single frame:

In aplication (C#)

and results in msvc2010 debug:

w0
w1
w2
w3


Share on other sites

So the parameters are fine. Now where might that breakpoint be ?

Also: 0.0091000004 is within float precision of 0.0091. It's probably also just a difference with the debug view, not the actual value.

Share on other sites

So the parameters are fine.

At w2 lateral speeds:

actual value 0.043717053

"equal" value 0.030822765
0.043717053 - 0.030822765 = 0.012894288
this is 34.59% of difference how come this be fine?

Breakpoint is at my exportFunctions.cpp

Edit: I just noticed something, the latRoadVelocity seem to be used form the last frame... I'll have a deeper look on my main class

Edit2: This is odd, seems like the values are passed quite accurate now, but the calculations are still messed and the wheel's cant find theyr correct slip's...
Is there a possibility that the math function (wich is quite simple) may produce absolutely different results, causing the math to break?