int
データ型を使用し、整数のオーバーフローに依存する高速ハッシュ関数を実装したいと思います。MSDNによると、オーバーフローによって例外がトリガーされないようにするにはunchecked
、そのコードにブロックを使用する必要があります。
unchecked
その計算だけをブロックで囲んでいると仮定します。そのため、コードにパフォーマンスや移植性の問題が発生しますか?
int
データ型を使用し、整数のオーバーフローに依存する高速ハッシュ関数を実装したいと思います。MSDNによると、オーバーフローによって例外がトリガーされないようにするにはunchecked
、そのコードにブロックを使用する必要があります。
unchecked
その計算だけをブロックで囲んでいると仮定します。そのため、コードにパフォーマンスや移植性の問題が発生しますか?
チェックされたプロセス命令を1つだけ追加します。
checked
{
int y = x * x;
05297978 mov eax,dword ptr [ebp-10h]
0529797B imul eax,dword ptr [ebp-10h]
0529797F jno 05297986 //if not overflow: goto 05297986
05297981 call 72A29522 //invoke exception
05297986 mov dword ptr [ebp-14h],eax
}
unchecked
{
int yy = xx * xx;
0529799E mov eax,dword ptr [ebp-18h]
052979A1 imul eax,dword ptr [ebp-18h]
052979A5 mov dword ptr [ebp-1Ch],eax
}
原則として、チェックされていない演算の方がわずかに高速であると期待できますが、反対の質問をする価値はほとんどありません(つまり、「チェックされたものを使用するとパフォーマンスが低下しますか?」)。
チェックされている場合とチェックされていない場合は、、、、など+
の演算子の処理方法に関してわずかに異なるルールがあることを意味します。手元のケースに適したルールを使用する必要があります。*
-
この場合、絶対にチェックを外したいので、コードにこれを記載する必要があります。これにより、実際には移植性が向上します。これは、コンパイラスイッチがどのように使用されても同じ動作をするためです。
技術的には、checked
ブロックだけが遅くなるはずです。unchecked
したがって、ブロック(フレームワークがより少ないチェックを実行する必要があるブロック)が遅くなる可能性はないと思います。コンテキストスイッチなどではありません。JITは、オーバーフロー/アンダーフローをチェックするための命令を発行しません。さて、誰かがオーバーフローをシミュレートしてMonoを移植する必要がある「特別な」プロセッサを作成した場合、またはオーバーフローがIntelプロセッサとは異なる結果を引き起こす場合、unchecked
ブロックは遅くなります(JITがそれを「シミュレート」する必要があるため) )。ただし、.NETの基本タイプはECMA標準で定義されていることに注意してください。符号付きintは、たとえば2の補数に基づいている必要があり、サイズは8、16、32、64ビットである必要があります。「奇妙な」ためのスペースはあまりありません
2つのメソッドを作成しました。1つはによってラップされ、もう1つはによってラップさchecked
れunchecked
ます。ILを調べると、唯一の違いはmul
演算(乗算演算を実行)です。mul.ovf
チェックされている場合とチェックされていない場合が生成されます- mul
。
要約すると、単一のCPU操作の違いはパフォーマンスに影響を与えないと思います。唯一の違いは、を使用したオーバーフローの場合ですchecked
。この場合、OverflowExceptionが生成され、実行が明らかに遅くなります。
次のMicrosoft中間言語(MSIL)命令は、OverflowExceptionをスローします。
- mul.ovf。
- ..。
[Test]
public void Checked()
{
checked
{
int i = int.MaxValue;
i = i * 100;
Debug.WriteLine(i);
}
}
[Test]
public void UnChecked()
{
unchecked
{
int i = int.MaxValue;
i = i * 100;
Debug.WriteLine(i);
}
}
そして、ILDASMを使用してILを参照してください。
CHECKED():
// Code size 27 (0x1b)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4 0x7fffffff
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ldc.i4.s 100
**IL_000b: mul.ovf** !!!
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: box [mscorlib]System.Int32
IL_0013: call void [System]System.Diagnostics.Debug::WriteLine ...
UNCHECKED():
// Code size 27 (0x1b)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4 0x7fffffff
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ldc.i4.s 100
**IL_000b: mul** !!!
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: box [mscorlib]System.Int32
IL_0013: call void [System]System.Diagnostics.Debug::WriteLine(...)