优化简单方法

时间:2016-04-15 17:07:39

标签: c# optimization unity3d

在下面给出的方法中,有很多投射,据我所知,它对于CLR非常有用。我想优化它,但是我不能改变这种方法签名。

public uint GetValueBetween (uint beginColor, uint endColor , float percent)
{
    int difference = (int)endColor - (int)beginColor; // can be signed negative integer

    float fValue = UnityEngine.Mathf.Abs((float)difference) * percent; // percent must be given in range 0.0 - 1.0, that is why I am not dividing it by 100;

    if (difference < 0)
    {
        return beginColor - (uint)UnityEngine.Mathf.RoundToInt (fValue);
    }

    return (uint)UnityEngine.Mathf.RoundToInt (fValue);
}

关于如何移除强制转换的想法很少,比如不在Int32 uint中将此方法的第一行转换为pgsql 3次,但只需检查哪个数字更大并采用全部代码的其余部分。

无论如何,我想问你一下,你有什么想法。

4 个答案:

答案 0 :(得分:3)

在相同大小的类型(例如uint和int)之间进行转换通常是零成本的,因为它只是从unsigned更改为signed cpu指令。

从int到float的转换可能非常昂贵,首先是因为它需要非平凡的格式转换(所有浮点值都规范化为一位数,因此计算N为1.xxxxx * 2 ^ N),并且因为浮点寄存器是现代CPU中的向量,所以您将一个值加载到一个寄存器中,该寄存器可以容纳8到32个值。

由于您根本没有实际使用浮点值,并且由于您将Abs应用于有符号值,因此只需将浮点百分比缩放到适当的整数即可轻松消除大部分成本value(我在这里使用100,但你可以选择一个更大的值,只记得除以每个语句末尾的整数等值,你可以测试是否更快乘以2的幂而不是10的幂,以防浮点单元为此进行优化而烦恼。

public uint GetValueBetween (uint beginColor, uint endColor , float percent)
{
    if(endColor < beginColor)
    {
        uint difference = beginColor - endColor;
        return beginColor - ((uint)(percent * 100.0) * difference) / 100;
    }
    else
    {
        uint difference = endColor - beginColor;
        return ((uint)(percent * 100.0) * difference) / 100;
    }
}

我将差异拆分为一个单独的变量,以说明条件中的关键差异,但如果您愿意,可以内联。

答案 1 :(得分:0)

根据您的回答请求,我会执行以下操作...

public uint GetValueBetween(uint beginColor, uint endColor , float percent)
{
    float difference = endColor - beginColor; // can be signed negative integer

    // percent must be given in range 0.0 - 1.0, that is why I am not dividing it by 100;
    float fValue = UnityEngine.Mathf.Abs(difference) * percent;
    var rounded = (uint)UnityEngine.Mathf.RoundToInt(fValue);
    if (difference < 0)
    {
        rounded = beginColor - rounded;
    }

    return rounded;
}

不一定更“高效”,但至少它有点清洁。

答案 2 :(得分:0)

虽然我不相信这种方法会成为性能瓶颈,但至少可以简化这种方法来删除分支:

public uint GetValueBetween(uint beginColor, uint endColor, float percent)
{
    return (uint) UnityEngine.Mathf.RoundToInt( ( 1 - percent ) * beginColor + percent * endColor );
}

答案 3 :(得分:0)

你的方法与Unity的LerpUnclamped完全相同。这就是它的代码。

public static float LerpUnclamped (float a, float b, float t)
{
    return a + (b - a) * t;
}

因为它来自Unity,我觉得复制很好。所以你的方法可以像这样重写。

public uint GetValueBetween (uint beginColor, uint endColor , float percent)
{
    return beginColor + (uint)((endColor-beginColor)*percent);
}