【问题标题】:Array Bounds Check Elimination in the CLR?CLR 中的数组边界检查消除?
【发布时间】:2012-03-07 11:08:30
【问题描述】:

我最近阅读了 Dave Detlefs 的 this article,他在其中介绍了 CLR 执行数组边界检查消除的几个案例。我决定自己测试一下,所以我做了以下操作:

  • 打开 Visual Studio 2010 Ultimate SP1
  • 创建了一个控制台应用程序类型的新 C# 项目(默认针对 .NET 4 客户端配置文件)
  • 添加如下代码(所有子方法直接摘自文章):

    class Program {
        static void Main(string[] args) {
            int[] array = new int[30];
            Test_SimpleAscend(array);
            Test_SimpleRedundant(array, 3);
    
            foreach (int i in array) {
                Console.WriteLine(i);
            }
        }
    
        static void Test_SimpleAscend(int[] a) {
            for (int i = 0; i < a.Length; i++)
                a[i] = i;
        }
    
        static void Test_SimpleRedundant(int[] a, int i) {
            int k = a[i];
            k = k + a[i];
        }
    }
    
  • 切换到释放模式;验证在构建选项中选中了“优化代码”

  • 为每个数组访问添加断点,开始调试(F5)并打开反汇编窗口

下面是 a[i] = i; 的反汇编。在 Test_SimpleAscend 中:

                a[i] = i;
00000024  mov         eax,dword ptr [ebp-4] 
00000027  mov         edx,dword ptr [ebp-8] 
0000002a  cmp         eax,dword ptr [edx+4] 
0000002d  jb          00000034 
0000002f  call        64FD6E08 
00000034  mov         ecx,dword ptr [ebp-4] 
00000037  mov         dword ptr [edx+eax*4+8],ecx 

cmp/jb/call 是边界检查,实际上强制执行调用会抛出 IndexOutOfRangeException。

所有数组访问都是一样的,包括 Test_SimpleRedundant 中的冗余访问。那么我的测试方法是否有问题,或者 CLR 实际上并没有消除边界检查?我希望我错了,如果是这样,我想知道如何才能真正获得数组边界检查消除。

【问题讨论】:

  • 当您说“开始调试”时,我假设您从 Visual Studio 环境启动了附加调试器的应用程序。在这种情况下,您需要确保启用 JIT 编译,因为它不是默认的。 JIT 编译器是执行此优化的编译器,而不是 C# 编译器。
  • 如果禁用边界检查会发生什么?这通常是人们在使用像 C# 这样的托管语言时期望拥有的功能。
  • 确保优化实际启用的最简单方法是在不调试的情况下启动应用程序,然后将调试器附加到它。
  • @M.Babcock:他不希望边界检查被禁用;他希望 JIT 能够检测到永远不会超过界限,从而优化检查。
  • @M.Babcock 这不是关于禁用它,而是在我们可以静态证明索引在数组边界内的情况下优化一些检查。在这种情况下,边界检查是多余的,只会降低执行速度。

标签: c# arrays optimization clr bounds-check-elimination


【解决方案1】:

感谢 Cody Gray 的评论,我已经设法回答了我自己的问题:

默认情况下,调试时禁用 JIT 优化。要解决此问题,可以转到调试 -> 选项和设置 -> 调试 -> 常规,然后取消选中“仅启用我的代码”和“在模块加载时抑制 JIT 优化”。

另见https://docs.microsoft.com/en-us/visualstudio/debugger/jit-optimization-and-debugging

启用优化后,边界检查将被删除。

我将把它留在这里用于文档目的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-29
    • 2022-01-13
    • 2014-03-09
    • 2014-07-13
    • 2013-06-22
    • 1970-01-01
    • 2013-02-19
    • 2011-05-27
    相关资源
    最近更新 更多