当前位置: 首页 > 知识库问答 >
问题:

为什么现代C++编译器不优化像这样的简单循环呢?(Clang,MSVC)

鲁辉
2023-03-14
#include <stdio.h>
#include <time.h>

static int const N = 0x8000;

int main()
{
    clock_t const start = clock();
    for (int i = 0; i < N; ++i)
    {
        int a[N];    // Never used outside of this block, but not optimized away
        for (int j = 0; j < N; ++j)
        {
            ++a[j];  // This is undefined behavior (due to possible
                     // signed integer overflow), but Clang doesn't see it
        }
    }
    clock_t const finish = clock();
    fprintf(stderr, "%u ms\n",
        static_cast<unsigned int>((finish - start) * 1000 / CLOCKS_PER_SEC));
    return 0;
}

共有1个答案

柳深
2023-03-14

未定义的行为在这里是无关紧要的。将内循环替换为:

    for (int j = 1; j < N; ++j)
    {
        a[j-1] = a[j];
        a[j] = j;
    }

...有同样的效果,至少和铿锵。

问题是内循环既从A[j]加载(对于某些j)又存储到A[j](对于某些j)。因为编译器认为以后的加载可以看到这些存储,所以不能删除任何一个存储,因为它们的值被用来(作为以后的存储的输入)。因此,循环仍然对内存有副作用,因此编译器看不到可以删除它。

 类似资料:
  • 在我的系统上,行-主顺序访问平均花费(试用),而列-主顺序访问在我的系统上花费(试用),这是相当重要的。 从表面上看,这应该是一件非常简单的事情来优化。 为什么现代编译器不优化这些场景?

  • 这是CppCon谈话中的一个例子https://www.youtube.com/watch?v=F6Ipn7gCOsY 目标是首先从A打印Hello,然后允许线程B启动。很明显,应该避免繁忙等待,因为它占用大量CPU。 作者说, 循环可以由编译器进行优化(通过将 的值放入寄存器中),因为编译器看到 从不Hibernate,因此永远不会被更改。但是,即使线程从不Hibernate,另一个线程仍然可以

  • (这个问题与此密切相关,但它是一个更具体的问题,我希望能就此得到答案)

  • 问题内容: 这段代码使我凝视了几分钟: (这里的第137行) 我以前从未见过,而且我也不知道Java有一个“ loop”关键字(NetBeans甚至没有像关键字一样给它上色),并且它在JDK 6中可以很好地编译。 有什么解释? 问题答案: 它不是一个keyword,而是一个label。 用法:

  • 为了更好地理解编译器,特别是汇编语言,我一直在实验一段简单的代码,其中计算第一个数字的总和,这应该导致或. 如代码所示,有两个功能: 在第一个函数中,I从O循环到N,即

  • 然而,gcc和clang都没有这样优化它--它们都在优化级别生成以下内容: 我的问题是:是因为代码太特殊而不需要优化,还是因为不是对的引用,所以不需要这样的优化?似乎唯一的原因可能是可能有一个非-或-值,但在读取它时没有未定义的行为,但我不确定这是否可能。