Я разработал игру, в которой периодически добавляются векторы друг к другу. Например: position += movement;
- это движение, которое выполняется на каждом такте игры для каждого юнита на игровом поле.
Вектор выглядит следующим образом, ofc с дополнительными методами:
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);
}
}
Я хочу максимально оптимизировать эти вычисления, потому что в игровом поле много таких единиц, и эти вычисления выполняются чаще, чем запрашивать значения векторов для других операций.
Моя идея теперь состоит в том, чтобы сохранить координаты X и Y в двух отдельных массивах для более быстрого расчета и собрать новые векторы из класса владельца или менеджера. Может быть, что-то вроде этого:
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];
}
}
Здесь можно добавить Vector
из двух holder
с (VectorHolder.Add
) с очень высокой производительностью. Однако доступ к X
или Y
для Vector
сейчас довольно медленный.
По моей идее, Вектор не будет хранить holder
и position
. Скорее, он будет хранить указатели на X
и Y
, так что мне не нужно будет напрямую обращаться к массивам держателей.
Однако я не знаю, как прикрепить (fixed
) указатели к массивам навсегда, не делая их полем fixed
с заранее определенной длиной. Кроме того, мой метод не очень хорош в долгосрочной перспективе, потому что память держателя будет фрагментирована, и поэтому инструкции SIMD будут снижаться в производительности, потому что будет также вычисляться все больше и больше пустых слотов Vector
.
Мой вопрос сейчас такой: есть ли что-то подобное уже в .NET Framework или в NuGet, и я просто упустил это из виду? Что-то, что в лучшем случае также заботится о фрагментации и т. Д.? Если нет, как я могу закрепить память постоянно, чтобы я мог работать с ней, не вызывая fixed
? У вас есть лучшее предложение для решения моей проблемы, чем мой подход?
Обратите внимание: код в этом вопросе является только псевдокодом, который может не работать, если вы скопируете его в IDE. Код только для лучшего понимания вопроса и, конечно, не будет с фиксированными значениями и т. Д. В реальной реализации.