我正在尝试在C#.NET和Mono中编写优化代码,用于游戏。 (是的,我有正当理由使用C#而不是C ++)。
我注意到C#似乎没有正确优化其运算符。运算符的运行速度是使用Vector4数学手动内联代码的两倍。 以下是我在.NET 4.5中运行9999999次的一些简单基准测试:
// Test 1
for (uint i = 0; i != 9999999; ++i)// 230 MS
{
vector += vector2;
vector2 -= vector;
}
// Test 2
for (uint i = 0; i != 9999999; ++i)// 185 MS
{
vector = vector.Add(ref vector2);
vector2 = vector2.Sub(ref vector);
}
// Test 3
for (uint i = 0; i != 9999999; ++i)// 116 MS
{
vector.X += vector2.X;
vector.Y += vector2.Y;
vector.Z += vector2.Z;
vector.W += vector2.W;
vector2.X -= vector1.X;
vector2.Y -= vector1.Y;
vector2.Z -= vector1.Z;
vector2.W -= vector1.W;
}
// EDIT Test 1 SOLVED ----------------------------------
// When the Operators are created like so, they actually perform the BEST!
// Sry MS for complaining :(... Although SIMD support would be nice :)
struct Vector4
{
public static Vector4 operator +(Vector4 p1, Vector4 p2)
{
p1.X += p2.X;
p1.Y += p2.Y;
p1.Z += p2.Z;
p1.W += p2.W;
return p1;
}
public static Vector4 operator -(Vector4 p1, Vector4 p2)
{
p1.X -= p2.X;
p1.Y -= p2.Y;
p1.Z -= p2.Z;
p1.W -= p2.W;
return p1;
}
}
for (uint i = 0; i != 9999999; ++i)// 75 MS
{
vector += vector2;
vector2 -= vector;
}
我想知道是否有任何.NET IL优化工具?我看了,但还没找到任何东西。或者更清楚,无论如何要优化我的C#代码或IL代码以提高性能。
我真的希望看到运营商的表现至少达到185毫秒。它也是有道理的。
以下是用于测试的应用的链接: Download
答案 0 :(得分:3)
你自己的回答和评论都强烈暗示为什么调用.Add比使用加法运算符更快。
+
的语义是操作数保持不变。做1 + 2你不会期望1后面的值是3吗?因此,遵循最小惊喜的规则,各种实现中的加法运算符遵循这种语义。
这也意味着vector4的加法运算符需要创建一个新的Vector4对象。这个新对象的内存可能已经被分配(例如堆栈),但这没有多大帮助,因为我们必须在分配给返回类型的任何内容时复制该值。
Add实例方法的语义与加法运算符不同。它会改变其中一个实例,因此不必创建新对象。
您发布的答案中的加法运算符的语义与add
答案 1 :(得分:2)
我找到了解决我问题的方法......虽然我仍然喜欢有关.NET IL优化器的任何信息。另外有趣的是,为什么使用运算符实际上更快,然后自己手动倾斜代码?
要在.NET上使用Vector4运算符获得最佳性能,请执行以下操作:
public static Vector4 operator +(Vector4 p1, Vector4 p2)
{
p1.X += p2.X;
p1.Y += p2.Y;
p1.Z += p2.Z;
p1.W += p2.W;
return p1;
}
public static Vector4 operator -(Vector4 p1, Vector4 p2)
{
p1.X -= p2.X;
p1.Y -= p2.Y;
p1.Z -= p2.Z;
p1.W -= p2.W;
return p1;
}
不要这样做:
public static Vector4 operator +(Vector4 p1, Vector4 p2)
{
return new Vector4(p1.X+p2.X, p1.Y+p2.Y, p1.Z+p2.Z, p1.W+p2.W);
}
//ect...