Passing matrix by ref or by val?

Performance-wise, is it recommended to pass around matrices by reference or by value? Will it give any measurable boost / might mess up something in MonoGame? (I know the difference between ref and val no need to explain).

In general it sounds like its better to pass matrix by ref to functions (knowing that they won’t change inside), but maybe there’s a reason why I shouldn’t in MonoGame…

Thanks!

Passing by ref may be slightly faster because less data needs to be copied. Matrices consist of 16 32-bit values, which is quite large for a struct (in fact MS guidelines say to avoid structs larger than 16 bytes, but for game dev because GC is important Matrix is a struct anyway). I don’t know how ref works internally, but I got speed ups by using ref for large structs in a program I wrote a while ago.

Anyways, as always if you have an application that needs this level of optimization you should probably try both options and profile. In general you don’t need to worry about what you pick.

That’s what I think too, I just wanted to know if there are any reasons not to do it in MG. Thanks, I’ll try it out and post results.

Nope, nothing special about the way MG does things :slight_smile:
Thanks for posting back, I’m curious!

By ref passes a single 32- or 64-bit pointer to the struct instance. Any changes made to the parameter are made directly to the original struct instance.

1 Like

Well I don’t see any difference between ref and value.

I draw couple thousand entities all over the screen, which lowers my FPS to 12. Every draw makes like 3-4 calls that send matrices as params. Changing those to ref made no difference at all on FPS.

I know its not the scientific way to measure it, but I wanted to see if it gives any practical improvement or not, and how it behaves in actual rendering.

Apparently not much. I’ll still leave it as ref though, since it doesn’t harm.

When you pass a variable by reference all you are doing is passing a pointer to the original declaration of the variable in memory, making it more efficient.

However, passing by reference also opens up the ability of the method in which the variable is passed to update it since it is not a copy of the variable.

When passing by value, you can also update the passed variable but the updates will only be relevant to the scope of the called method, not the original variable being passed.

Good coding standards stipulate that if the variable is not to be updated, pass by value, otherwise pass by reference.

In this case you are looking for a performance boost but not the ability to update so you may want to consider changing the technique you are using such as making your matrix a static value if it can be used on a global scale.

You’ll only notice if your application makes very heavy use of matrices and passes them around a lot. In your case it’s also likely that the GPU is the bottleneck, so it won’t matter either way.

The application I talked about earlier was a path tracer that created millions of bounding boxes and passed them around a lot. Changing those bounding boxes from structs to classes improved performance of part of the program a bit.

A Matrix is 4 * 16 = 64 bytes. that’s very big indeed.

Passing a Matrix by ref can be a good idea only if the Matrix supplied lives on the stack and not heap.
There would be performance improvement, obviously.

@GeonBit

Paraphrased from the textbook “Fundamentals of Computer Graphics”:

Efficiency is achieved through careful tradeoffs, and these tradeoffs are different for different architectures. But for the foreseeable future, a good heuristic is that programmers should pay more attention to memory access patterns than to operation counts.
A reasonable approach to making code fast is to proceed in the following order, taking only those steps which are needed:

  1. Write the code in the most straight-forward way possible.
  2. Compile in optimized mode.
  3. Use whatever profiling tools exist to find critical bottlenecks.
  4. Examine data structures to look for ways to improve data locality. If possible, make data unit sizes match the cache / page size on the target architecture.

In all situations, profiling is needed to be sure of the merit of any optimization for a specific machine and compiler.

Back in times of XNA, I switched to ref to make computations on matrices, and got about 10fps+ on an average 75fps. (ie:85fps)
With 8 matrices multiplications (self rotation, rotation about an orbit, WVP, invWVP, etc)
It’s definitely faster by ref.

Passing matrics by ref to an effectparameter … I did not know it was possible. I’ll have a look at this when I have time, but SetValue sends data onto the gpu, how can it pass a pointer ?

No that’s not what I meant, in my own code I pass the matrices around… before the effect. I don’t think there’s a way to pass matrix as ref to GPU… maybe it’s the future, GPUs with direct, fast access to PC’s memory :slight_smile:

is it recommended to pass around matrices by reference or by value?
.
in my own code I pass the matrices around… before the effect.

The real question is what are you passing when you pass a instance of a struct by value? To say your passing a copy value reference to the instantiated struct. Anyways…

It’s cheaper generally to pass a struct without the ref keyword unless its very large which then means it maybe should be a class. Returning it then copying it isn’t always so clear though.

My rule of thumb is that with structs i pass by value unless two structs must change each other or they must do some copying back and forth. In that case i do something like the below or i might use the out keyword.

myMatrix1.M( ref myMatrix2);
public void M(ref a){ … a.M11 = this…M11; this.M22 = a.M22; }

There is no point in doing extra assignments to a temp matrix inside then passing it back out if both matrices must assign to each other. If myMatrix1 only needs to read the values from myMatrix2 i just pass it without the ref keyword however if the struct is really big it might be cheaper to pass by ref however in that case it probably should be a class instead of a struct.

Class instances are more so canidates for getting a benifit from using the ref keyword.