8

我想实现一个快速散列函数,它将使用int数据类型并依赖整数溢出。MSDN 说,为了保证溢出不会触发异常,我必须unchecked为该代码使用块。

假设我只将那个计算包围在一个unchecked块中。我的代码会因此有任何性能或可移植性问题吗?

4

4 回答 4

10

选中只添加一个流程指令:

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

通常,您可以期望未经检查的算术会稍微快一些,但几乎不值得向您提出相反的问题(即“使用检查会损害我的表现吗?”)。

Checked 和 unchecked 只是意味着关于如何处理 , 和 和 等运算符的规则略有不同+*-应该使用适合手头情况的规则。

在这种情况下,您肯定想要取消选中,因此您应该在代码中说明这一点。这实际上增加了可移植性,因为无论使用什么编译器开关,您都将拥有相同的行为。

于 2011-10-20T11:52:20.940 回答
8

从技术上讲,只有checked块应该变慢。所以我不认为一个unchecked块(一个框架必须做更少检查的块)会变慢。它不是上下文切换或类似的东西。JIT 根本不会发出检查上溢/下溢的指令。现在,很明显,如果有人创建了一个“特殊”处理器,其中必须模拟溢出并在其上移植 Mono,或者溢出导致与 Intel 处理器不同的结果,则unchecked块会更慢(因为 JIT 必须“模拟”它)。但请注意,.NET 的基本类型是在ECMA标准中定义的。例如,有符号整数必须基于二补码,并且它们的大小必须为 8、16、32、64 位。“奇怪”没有太多空间

于 2011-10-20T08:09:58.030 回答
4

我创建了两种方法,一种由 包裹,checked另一种由unchecked. 通过查看 IL,只有一个区别是mul运算(执行乘法运算),mul.ovf生成检查和未检查 - mul

总而言之,我相信单个 CPU 操作的差异不会对性能产生任何影响,唯一的区别是在使用溢出的情况下checked- 在这种情况下会生成溢出异常,这显然会减慢执行速度。

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:

已检查():

// 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 ...

未选中():

  // 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 回答