JIT .Net编译器错误?

时间:2013-12-20 10:38:50

标签: c# .net visual-studio-2010 jit

以下代码的结果不同如果在后台启动调试器或没有调试器。如果优化已经开启,那么差异就在那里。

结果如下:

- >与优化: 1000 2008年 3016 1001 2009年 3007 ...

- >没有优化(如预期的那样) 1000 1008 1016 1001 1009 1017 ...

代码:

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace OptimizerTest
{   
    public class Test
    {
        int dummy;

        public void TestFunction(int stepWidth)
        // stepWidth must be a parameter
        {
            for (int step = 0; step < stepWidth; step++)
            {
                dummy = step + 1000;
                // addition with constant ( same value as later !)
                for (int x = 0; x < 20; x += stepWidth)
                {
                    int index = x + 1000 + step;
                    // constant must be same as above and ?!?! 
                    // int index = x + step + 1000; works !!!!!
                    Console.Write("\n\r" + index);
                }
            }
        }

        [MethodImpl(MethodImplOptions.NoOptimization)]
        public void TestFunctionNoOptimization(int stepWidth)
        {
            for (int step = 0; step < stepWidth; step++)
            {
                dummy = step + 1000;
                for (int x = 0; x < 20; x += stepWidth)
                {
                    int index = x + 1000 + step;                        
                    Console.Write("\n\r" + index);
                }
            }
        }
    }

    class Program
    {
        /// <summary>
        /// Result differs from Start with F5 to Ctrl-F5
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Test test = new Test();
            Console.Write("\n\r---------\n\roptimized result\n\r-------------" );
            test.TestFunction(8);
            Console.Write("\n\r---------\n\rnot optimized result\n\r-------------");
            test.TestFunctionNoOptimization(8);
            Console.Write("\n\r---------\n\rpress any key");
            Console.ReadKey();
        }
    }
}

错误的行为取决于内循环的迭代次数(x <5,一切正常)。非常有趣的是,当我使用

时不会发生
   int index = x + step + 1000; 

而不是

   int index = x + 1000 + step; 

我正在使用Visual Studio 2010 SP1并尝试使用.NET Framework从2.0到4.0.3。我总是看到同样的结果。

有人知道这个错误还是可以重现?

1 个答案:

答案 0 :(得分:20)

是的,这绝对是一个抖动优化器错误。其他SO用户重现它的原因是因为只有x64抖动似乎有这个bug。您必须将项目的平台目标设置为AnyCPU,取消VS2012上的“首选32位”选项以及更新。

我没有仔细研究潜在的原因,但似乎在尝试消除常见的step + 1000子表达式时摸索。子表达式消除是标准抖动优化之一。但是它错误地将表达式代码合并到循环中,而不是像写入的那样将它保持在循环之外。例如,当您写下来时,您会看到错误消失:

  dummy = step + 999;

最新的.NET 4.5.1版本(我机器上的clrjit.dll,v4.0.30319.34003)中仍然存在此错误,同样存在于v2抖动中(mscorjit.dll,v2.0.50727.7905)机)。

代码有点过于合成,无法推荐一个可靠的解决方法,你已经找到了一个,所以你可以继续驾驶你的项目。一般来说,我建议您使用以下方法消除子表达式:

  int index = x + dummy;  

应该向Microsoft报告,您可以通过在connect.microsoft.com上发布错误报告来实现。如果你不想花时间让我知道,我会照顾它。