objarni's picture

GL.LoadMatrix(Matrix4) overload..?

I wanted to use the LoadMatrix method of the GL class.. found lots of overloads, but none of them taking a Matrix4 (or ref to it ..) as an argument.

Is this a known issue or should I put up an item about it somewhere..? (where?)

Overall I'm so far very pleased with my OpenTK experience.. Keep up the good work!


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
objarni's picture

Thanks!

Do you have any idea why immutability makes is even worse? I see no apparent reason why 'Vector2 Add(Vector2,Vector2)' should be any slower if the Vector2 is immutable..? (Compared with 'void Add(Vector2)' the reason is clear! No new vector, just update 'this' members!)

Inertia's picture

Thank you JTalton!

I'm sure there's alot of users who will favor double over single precision, and tbh I find "a.Add(ref b);" pretty attractive ;)

Maybe start a new topic for discussing the VectorXd structs, it will go under inside this topic.

JTalton's picture

The question is - what does making a struct immutable give you?

Immutable classes make a lot of sense where you can share an object by many other objects and not have to worry that the object will change. This is why the .NET strings are implemented this way. It allows strings to be referenced from many different places without fear of the string being modified. Only the reference is passed when making function calls etc. Setting a = b changes what a is referencing.

Immutable structs can never really be immutable. Every variable of the struct is it's own copy. Modifying it will only modify that copy. Setting a = b copies the contents of b into a.

If Vector was immutable:
It is true that in Vector Add( Vector a, Vector b) you cannot modify a or b in the function. This function makes a copy of each of the input parameters and a copy for the output parameter. That ends up being expensive.

Calling by ref passes a reference to the struct with is a lot faster than having a copy made.

Basically it comes down to the fact that since structs are value types (i.e. their own copy) they really can't be made immutable.

objarni's picture

[Immutability]
I agree that the general approach today is to use modifiable (mutable) structs for Vectors, Quaternions and Matrices, for performance reasons. I believe I am not the only one who views the syntax as not the most elegant available in C#.

My question is simply academic: why would the performance of the operation

static VectorN Add(ref VectorN, ref VectorN)

.. depend on whether the struct VectorN is immutable or not? Since it has to allocate a new VectorN and do N additions. No VectorN member is modified at all.

Do you have the benchmarks for the operations available, eg. for Matrix4? It would be interesting to know how this "scales up" to structs with more members (comparing ref'ed structs to classes especially).

JTalton's picture

I do not think the performance of static VectorN Add(ref VectorN, ref VectorN) would be any different with immutable vs non-immutable structures.

My testing shows that static void Add(ref VectorN, ref VectorN, out VectorN) is a much faster function, and since it is using out, you need to be able to modify the out VectorN.

static VectorN Add(ref VectorN, ref VectorN) probably pushes the result from the function onto the stack and then has to do a copy to the variable that is being assigned in the operation. ( i.e. c = Add(a, b) ) That would explain the performance being 4 times as long.

Time | Function
-----------------------------------------
 236 : Vector4D.Add(ref a, ref b, out c);
1110 : c = Vector4D.Add(ref a, ref b);

The other problem with using immutable structs and static VectorN Add(ref VectorN, ref VectorN) is that since the parameters are passed as ref, in the function someone could call a = b, which even if the struct is immutable will still overwrite the fields in the struct essentially modifying the source Vector that was passed into the function. Thus the struct really is not immutable. Removing the ref adds even more overhead and slows the function down.

Immutable Classes
With immutable classes you have to allocate a new class to return, since you cannot modify the class. This call into the .NET memory manager usually will increase the execution time by double vs structs which are put on the stack. When I tested the Vector as a class, my timing numbers went up a good bit.

Looking on the net, I found a web page with the following numbers when they were testing the same thing:

Struct:            0.05
Immutable Struct:  0.10
Immutable Class:   0.25

The mutable struct is the fastest since they modify its data directly.

I do not have any performance tests setup for the matrix code.

I do whole heartedly agree that Add( ref a, ref b, out c ) is a ton uglier than c = Add( ref a, ref b ) which is uglier than c = Add( a, b ) which is uglier than c = a + b but it is MUCH faster.