8

intデータ型を使用し、整数のオーバーフローに依存する高速ハッシュ関数を実装したいと思います。MSDNによると、オーバーフローによって例外がトリガーされないようにするにはunchecked、そのコードにブロックを使用する必要があります。

uncheckedその計算だけをブロックで囲んでいると仮定します。そのため、コードにパフォーマンスや移植性の問題が発生しますか?

4

4 に答える 4

10

チェックされたプロセス命令を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  
}
于 2016-03-10T08:06:32.127 に答える
8

原則として、チェックされていない演算の方がわずかに高速であると期待できますが、反対の質問をする価値はほとんどありません(つまり、「チェックされたものを使用するとパフォーマンスが低下しますか?」)。

チェックされている場合とチェックされていない場合は、、、、など+の演算子の処理方法に関してわずかに異なるルールがあることを意味します。手元のケースに適したルールを使用する必要があります。*-

この場合、絶対にチェックを外したいので、コードにこれを記載する必要があります。これにより、実際には移植性が向上します。これは、コンパイラスイッチがどのように使用されても同じ動作をするためです。

于 2011-10-20T11:52:20.940 に答える
8

技術的には、checkedブロックだけが遅くなるはずです。uncheckedしたがって、ブロック(フレームワークがより少ないチェックを実行する必要があるブロック)が遅くなる可能性はないと思います。コンテキストスイッチなどではありません。JITは、オーバーフロー/アンダーフローをチェックするための命令を発行しません。さて、誰かがオーバーフローをシミュレートしてMonoを移植する必要がある「特別な」プロセッサを作成した場合、またはオーバーフローがIntelプロセッサとは異なる結果を引き起こす場合、uncheckedブロックは遅くなります(JITがそれを「シミュレート」する必要があるため) )。ただし、.NETの基本タイプはECMA標準で定義されていることに注意してください。符号付きintは、たとえば2の補数に基づいている必要があり、サイズは8、16、32、64ビットである必要があります。「奇妙な」ためのスペースはあまりありません

于 2011-10-20T08:09:58.030 に答える
4

2つのメソッドを作成しました。1つはによってラップされ、もう1つはによってラップさcheckeduncheckedます。ILを調べると、唯一の違いはmul演算(乗算演算を実行)です。mul.ovfチェックされている場合とチェックされていない場合が生成されます- mul

要約すると、単一のCPU操作の違いはパフォーマンスに影響を与えないと思います。唯一の違いは、を使用したオーバーフローの場合ですchecked。この場合、OverflowExceptionが生成され、実行が明らかに遅くなります。

MSDN:

次の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(...)
于 2011-10-20T08:17:44.250 に答える