优化XNA中的高流量功能

时间:2009-10-31 10:55:13

标签: c# .net optimization xna

我有一个每次更新被调用数十万次的函数,我需要优化它。现在,我通常遵循“不要太快优化”的规则,但这是一个关键功能,几乎所有代码的时间都用在了,所以你能提出的任何建议都会有所帮助。我也不熟悉可用于优化XNA或c#代码的任何提示和技巧。你能救我吗?

if (linearPosition.Y < _min.Y || linearPosition.Y > _max.Y)// the nonlinear space commisioned doesn't cover it so that's the behavior i want, same case with next line
{
    return linearPosition;
}
if (linearPosition.X < _min.X || linearPosition.X > _max.X)
{
    return linearPosition;
}
PositionData[] fourNearestPoints = new PositionData[4] 
{
    new PositionData {distance = float.MaxValue},
    new PositionData {distance = float.MaxValue},
    new PositionData {distance = float.MaxValue},
    new PositionData {distance = float.MaxValue}
};

for (int x = 0; x < _restPositions.GetLength(0); x++)
{
    for (int y = 0; y < _restPositions.GetLength(1); y++)
    {
        PositionData temp = new PositionData
        {
            indexX = x,
            indexY = y,
            value = _restPositions[x,y],
            distance = (linearPosition - _restPositions[x,y]).Length()
        };
        if (temp.distance < fourNearestPoints[0].distance)
        {
            fourNearestPoints[3] = fourNearestPoints[2];
            fourNearestPoints[2] = fourNearestPoints[1];
            fourNearestPoints[1] = fourNearestPoints[0];
            fourNearestPoints[0] = temp;
        }
    }
}
Vector2 averageRestVector = new Vector2((fourNearestPoints[0].value.X +
    fourNearestPoints[1].value.X +
    fourNearestPoints[2].value.X +
    fourNearestPoints[3].value.X) / 4,
    (fourNearestPoints[0].value.Y +
    fourNearestPoints[1].value.Y +
    fourNearestPoints[2].value.Y +
    fourNearestPoints[3].value.Y) / 4);
Vector2 averageDeformedVector = new Vector2((_deformedPositions[fourNearestPoints[0].indexX, fourNearestPoints[0].indexY].X +
    _deformedPositions[fourNearestPoints[1].indexX, fourNearestPoints[1].indexY].X +
    _deformedPositions[fourNearestPoints[2].indexX, fourNearestPoints[2].indexY].X +
    _deformedPositions[fourNearestPoints[3].indexX, fourNearestPoints[3].indexY].X) / 4,
    (_deformedPositions[fourNearestPoints[0].indexX, fourNearestPoints[0].indexY].Y +
    _deformedPositions[fourNearestPoints[1].indexX, fourNearestPoints[1].indexY].Y +
    _deformedPositions[fourNearestPoints[2].indexX, fourNearestPoints[2].indexY].Y +
    _deformedPositions[fourNearestPoints[3].indexX, fourNearestPoints[3].indexY].Y) / 4);

Vector2 displacement = averageDeformedVector - averageRestVector;
return linearPosition + displacement;

2 个答案:

答案 0 :(得分:2)

我要尝试的第一件事就是丢失fourNearestPoints数组...也许只使用4个变量用于4个最近的位置。你总是通过常量索引来对待它,所以这应该是一个简单的改变,特别是如果你命名为数组索引:

PositionData fourNearestPoints_0 = ...,
             fourNearestPoints_1 = ...,
             fourNearestPoints_2 = ...,
             fourNearestPoints_3 = ...;

接下来我要看的是_restPositions用法;我不知道GetLength(在此用途中)是否会被优化,所以我会尝试预先缓存它。在线性数组中,.Length已经过优化(至少在完整的CLR中) - 但不是GetLength AFAIK:

int width = _restPositions.GetLength(0), height = _restPositions.GetLength(1);
for (int x = 0; x < width; x++)
{
    for (int y = 0; y < height; y++)

也;什么是PositionDatastructclass?我很想尝试这两种方法 - 确保它是不可变的,并通过构造函数传递数据以使IL更瘦:

PositionData temp = new PositionData(x, y, _restPositions[x,y],
        (linearPosition - _restPositions[x,y]).Length());

在下文中,您正在做一些在大多数情况下被丢弃的工作:

    PositionData temp = new PositionData
    {
        indexX = x,
        indexY = y,
        value = _restPositions[x,y],
        distance = (linearPosition - _restPositions[x,y]).Length()
    };
    if (temp.distance < fourNearestPoints[0].distance)
    {
        fourNearestPoints[3] = fourNearestPoints[2];
        fourNearestPoints[2] = fourNearestPoints[1];
        fourNearestPoints[1] = fourNearestPoints[0];
        fourNearestPoints[0] = temp;
    }

我愿意:

var distance = (linearPosition - _restPositions[x,y]).Length();
if (distance < fourNearestPoints_0.distance) {
    fourNearestPoints_3 = fourNearestPoints_2;
    fourNearestPoints_2 = fourNearestPoints_1;
    fourNearestPoints_1 = fourNearestPoints_0;
    fourNearestPoints_0 = new PositionData(x, y, _restPositions[x,y], distance);
}

我也对distance=...行感兴趣;那里有很多我们看不到可能需要更多工作 - -运算符和Length()方法。


我是否正确地认为Length()涉及平方根? (贵)您可以通过在平方距离工作来避免这种情况。您可能需要使用不占用根的方形长度方法来显式显示此方法,并比较整个方形长度,但可以节省大量CPU周期。这可以LengthSquared()获得。

答案 1 :(得分:2)

首先,尝试使用一维数组而不是_restPositions的矩形数组 - CLR针对基于零的一维数组进行了优化。只需在数组中保留一个索引,并在每次迭代时递增它:

int index = 0;
// I'm assuming you can pass in width and height separately
for (int x = 0; x < width; x++)
{
    for (int y = 0; y < height; y++)
    {
        PositionData temp = new PositionData
        {
            indexX = x,
            indexY = y,
            value = _restPositions[index],
            distance = (linearPosition - _restPositions[index]).Length()
        };
        if (temp.distance < fourNearestPoints[0].distance)
        {
            fourNearestPoints[3] = fourNearestPoints[2];
            fourNearestPoints[2] = fourNearestPoints[1];
            fourNearestPoints[1] = fourNearestPoints[0];
            fourNearestPoints[0] = temp;
        }
        index++;
    }
}

如果您可以使PositionData的构造函数采用适当的值而不是具有单独的属性设置器,则可能也可以帮助。

您还要多次索引到fourNearestPoints - 任何不使用四个局部变量的原因?它不会做太多,但你永远不会知道......