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

Started by
16 comments, last by vadevaman 9 years, 10 months ago

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:

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

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?

Advertisement

One speculation that comes to mind is that you might have some uninitialized variables causing problems in your C++ port. In release mode, you might be getting lucky and the memory usually happens to be already set to 0. But in debug mode, the compiler might specifically be going out of its way to set the memory to "bad" values, so that any problems are painfully evident.

C# on the other hand has more strict rules about initializing variable values, so you can pretty much be guaranteed no junk data.

"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke


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).


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

So after reading this article, as I understand should use double instead in C++ ?

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.

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
	{		
		public bool loging = true;
		#region Members		
		public IntPtr nativeWheelObject; 
	    #endregion Members

		public Wheel()
		{			
        	this.nativeWheelObject = Sim.Dll_Wheel_Add();
			return;
		}
		
		#region Wrapper methods	
		public void SetVelocity(float lonRoadVelocity,float latRoadVelocity){Sim.Dll_Wheel_SetVelocity(this.nativeWheelObject,lonRoadVelocity,latRoadVelocity);}
		#endregion Wrapper methods
	}
	
	internal class Sim
	{
    	#region PInvokes
		[DllImport(pluginName, CallingConvention=CallingConvention.Cdecl)] public static extern void Dll_Wheel_SetVelocity(IntPtr wheel,float lonRoadVelocity,float latRoadVelocity);
		#endregion PInvokes	
	}		
}

This much code I can show.

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?

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.

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.

Why all the downvotes on the OP? Sure, it's a bit open to speculation due to the lack of code, but not all code can be shared and floating-point determinism is a valid and very relevant question.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”


/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.

This topic is closed to new replies.

Advertisement