7

ゲームに使用される C# .NET と Mono で最適化されたコードを作成しようとしています。(はい、C++ ではなく C# を使用する正当な理由があります)。

C# は演算子を正しく最適化していないようです。演算子は、Vector4 演算を使用してコードを手動でインライン化する場合と比較して、実行速度が 2 倍遅くなります。以下は、.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コードを最適化してパフォーマンスを向上させます。

オペレーターが LEAST 185ms で動作することを本当に望んでいます。それも理にかなっているだけです。

テストに使用するアプリへのリンクは次のとおりです。 ダウンロード

4

2 に答える 2

3

あなた自身の答えとコメントはすべて、加算演算子を使用するよりも .Add を呼び出す方が速い理由についての強力なヒントを与えてくれます。

のセマンティクス+は、オペランドが未処理のままであるということです。1 +2 を実行しても、後で 1 の値が 3 になるとは思わないでしょうか? SO は、最小の驚きのルールに従うために、さまざまな実装の加算演算子がこのセマンティックに従います。

これは、vector4 の加算演算子が新しい Vector4 オブジェクトを作成する必要があることも意味します。この新しいオブジェクトのメモリは既に割り当てられている可能性があります (スタックなど) が、戻り値の型が割り当てられているものに割り当てられたときにその値をコピーする必要があるため、あまり役に立ちません。

Add インスタンス メソッドのセマンティクスは、加算演算子とは異なります。インスタンスの 1 つを変更するため、新しいオブジェクトを作成する必要はありません。

投稿された回答の加算演算子のセマンティクスは、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 に答える