在下面给出的方法中,有很多投射,据我所知,它对于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次,但只需检查哪个数字更大并采用全部代码的其余部分。
无论如何,我想问你一下,你有什么想法。
答案 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);
}