I developed a game, where periodically vectors are added to each others. For instance: position += movement;
is the movement which is done on every tick of the game for every unit in the playfield.
A vector looks like this, ofc with additional methods in it:
public struct Vector
{
public float X;
public float Y;
public Vector(float x, float y)
{
X = x;
Y = y;
}
public static Vector operator +(Vector l, Vector r)
{
return new Vector(l.X + r.X, l.Y + r.Y);
}
}
I want to optimize those calculations to the maximum, because the playfield has many such units and those calculations are done more often, than querying values of the vectors for other operations.
My idea is now to save the X and Y coordinates in two separate arrays for a faster calculation and to gather new Vectors from a holder or manager class. Maybe something like this:
public class VectorHolder
{
internal float[] x = new float[1024];
internal float[] y = new float[1024];
internal bool[] inUse = new bool[1024];
public Vector NewVector()
{
return new Vector(this, aFreeSlotInTheArrays);
}
public void Add(VectorHolder holder)
{
int simdBlocks = Vector<float>.Count;
for (int position = 0; position < 1024; position += simdBlocks)
{
(new Vector<float>(x, position) + new Vector<float>(holder.x, position)).CopyTo(x, position);
(new Vector<float>(y, position) + new Vector<float>(holder.y, position)).CopyTo(y, position);
}
}
}
public struct Vector
{
internal VectorHolder holder;
internal int index;
internal Vector(VectorHolder holder, int index)
{
this.holder = holder;
this.index = index;
}
public float X => holder.x[index];
public float Y => holder.y[index];
public void Add(Vector vector)
{
holder.x[index] += vector.holder.x[vector.index];
holder.y[index] += vector.holder.y[vector.index];
}
}
Here the Vector
s of two holder
s can be added (VectorHolder.Add
) with very high performance. However the access to X
or Y
of a Vector
now is quite slow.
In my idea, the Vector wouldn't store the holder
and position
. It rather would store pointers to X
and Y
so that I wouldn't need to access the holders arrays directly.
However, I don't know how to pin (fixed
) pointers to arrays permanently, without making them a fixed
field with predefined length. Also my method is not very good on the long run, because the memory of the holder will fragment and therefor the SIMD instructions will decrease in performance because more and more empty Vector
slots will also be calculated.
My Question now is: Is there something like this already in the .NET Framework or on NuGet and I just overlooked it? Something which at best also takes care of the fragmentation, etc? If not, how can I pin memory permanently so that I can work on it without always calling fixed
? Do you have a better suggestion to solve my problem than my approach?
Please note: The code in this question is only pseudo-code which may not run if you copy this to your IDE. The code is just there for better understanding of the question and of course would be not with fixed values, etc. in a real implementation.