【问题标题】:Compiler optimization causing the performance to slow down编译器优化导致性能下降
【发布时间】:2011-02-13 16:22:37
【问题描述】:

我有一个奇怪的问题。我有以下代码:

template<clss index, class policy>
inline int CBase<index,policy>::func(const A& test_in, int* srcPtr ,int* dstPtr)
{
    int width = test_in.width();
    int height = test_in.height();

    double d = 0.0; //here is the problem
    for(int y = 0; y < height; y++)
    {

        //Pointer initializations

        //multiplication involving y
        //ex: int z = someBigNumber*y + someOtherBigNumber;
        for(int x = 0; x < width; x++)
        {
            //multiplication involving x
        //ex: int z = someBigNumber*x + someOtherBigNumber;
            if(soemCondition)
            {
                // floating point calculations
            }
            *dstPtr++ = array[*srcPtr++];
        }
    }
}

内部循环执行了近 200,000 次,整个函数需要 100 毫秒才能完成。 (使用 AQTimer 分析)

我在外循环外发现了一个未使用的变量double d = 0.0; 并将其删除。在此更改之后,突然该方法需要 500 毫秒来执行相同数量的执行。 (慢 5 倍)。

这种行为可以在具有不同处理器类型的不同机器上重现。 (Core2,双核处理器)。

我正在使用优化级别为O2 的VC6 编译器。 以下是使用的其他编译器选项:

 -MD -O2 -Z7 -GR -GX -G5 -X -GF -EHa

我怀疑编译器优化并删除了编译器优化/O2。在该功能变得正常后,它需要 100 毫秒作为旧代码。

有人能解释一下这种奇怪的行为吗?

为什么当我删除未使用的变量时编译器优化会降低性能?

注意:汇编代码(更改前后)看起来相同。

【问题讨论】:

  • 你确定程序集看起来一样吗?它是“看起来一样”还是完全一样?

标签: c++ visual-c++ visual-c++-6 compiler-optimization


【解决方案1】:

如果汇编代码在更改前后看起来相同,则错误与您对函数计时的方式有关。

【讨论】:

    【解决方案2】:

    VC6 有很多问题。众所周知,在某些情况下会生成不正确的代码,而且它的优化器也不是那么先进。编译器已经有十多年的历史了,甚至很多年都没有得到支持。

    实际上,答案是“您使用的是有问题的编译器。预计会有错误的行为,尤其是在启用优化时。”

    我不认为升级到现代编译器(或简单地测试代码)是一种选择?

    显然,生成的程序集不能相同,否则不会有性能差异。

    唯一的问题是 区别在哪里。对于一个有缺陷的编译器,很可能是代码中一些完全不相关的部分突然以不同的方式编译并中断。不过,最有可能的是,为该函数生成的汇编代码相同,而且差异是如此微妙,以至于你没有注意到它们。

    【讨论】:

    • 大胆猜测一下,double 会迫使后面的浮点例程以 8 字节堆栈对齐,这可以显着提高使用 double 时的性能。
    • 是的,这是可能的。对齐问题可能会导致这种幅度的放缓
    • 不幸的是,它是一个巨大的遗留项目。移植到最新的 VC 需要付出很多努力:(
    • @aJ:太糟糕了。但在过渡时可能值得开始(或者至少,尝试说服你的老板相信它)。当然这需要时间,同时您可能还必须维护 VC6 版本,但坚持使用 VC6 也会给您带来持续的不必要的痛苦。不管怎样,我感受到了你的痛苦。 ;)
    【解决方案3】:

    widthheight 声明为 const {unsigned} 整数。 {应该使用 unsigned,因为高度和宽度永远不会是负数。}

    const int width = test_in.width();
    const int height = test_in.height();
    

    这有助于编译器进行优化。使用const 的值,它可以将它们放在代码或寄存器中,知道它们不会改变。此外,它使编译器不必猜测变量是否在变化。

    我建议打印出带有未使用的double 和没有的版本的汇编代码。这将使您深入了解编译器的思考过程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 2012-04-17
      • 1970-01-01
      相关资源
      最近更新 更多