7

我正在尝试用 C# .NET 和 Mono 编写用于游戏的优化代码。(是的,我有正当理由使用 C# 而不是 C++)。

我注意到 C# 似乎没有正确优化其运算符。运算符的运行速度是使用 Vector4 数学手动内联代码的两倍。以下是我在运行 9999999 次的 .NET 4.5 中进行的一些简单基准测试:

// 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 毫秒的速度执行。它也只对它有意义。

这是用于测试的应用程序的链接: 下载

4

2 回答 2

3

您自己的答案和评论都强烈暗示了为什么调用 .Add 比使用加法运算符更快。

的语义+是操作数保持不变。做 1 +2 你不会期望 1 之后有 3 的值,对吗?所以要遵循最不意外的规则,各种实现中的加法运算符都遵循这种语义。

这也意味着vector4的加法运算符需要创建一个新的Vector4对象。这个新对象的内存可能已经被分配(例如堆栈),但这并没有多大帮助,因为当它被分配给任何返回类型被分配给时,我们将不得不复制该值。

Add 实例方法的语义不同于加法运算符。它会改变其中一个实例,因此不必创建新对象。

您发布的答案中加法运算符的语义等同于add

于 2012-10-01T18:29:38.423 回答
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...
于 2012-10-01T18:16:22.767 回答