【问题标题】:Is it an out of order execution case?这是一个乱序执行案例吗?
【发布时间】:2020-11-25 22:09:45
【问题描述】:

考虑下面的代码。


#include <iostream>
#include <random>
#include <chrono>
#include <memory>
const int N = 1 << 28;
int main()
{
    const int seed = 0;
    std::mt19937 gen;
    std::uniform_real_distribution<double> dis;
    std::normal_distribution<double> normal;
    std::unique_ptr<bool[]> array = std::unique_ptr<bool[]>(new bool[N]);

    for (int i = 0; i < N; i++)
    {
        if (dis(gen) > 0.5)
            array[i] = true;
        else
            array[i] = false;
    }

    int sum = 0;
    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; i++)
    {
        if (array[i])
            sum++;
    }
    auto t2 = std::chrono::high_resolution_clock::now();

    std::cout << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() << " microsecond" << std::endl;
    std::cout << sum << std::endl;




         sum = 0;
     t1 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; i++)
    {
            sum+=array[i];
    }
     t2 = std::chrono::high_resolution_clock::now();

    std::cout << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() << " microsecond" << std::endl;
    std::cout << sum << std::endl;
}

如果我用std::cout &lt;&lt; sum &lt;&lt; std::endl; 注释行,则执行时间将显示为零(或足够接近)。我已经在不同的编译器上检查过它,包括带有 O3 编译标志的 icpc、icl (v19.1.2) 和 g++ (v9.2)。

这是乱序(动态)执行的例子吗?

【问题讨论】:

  • 如果你注释掉这些行,优化器可能会让你的程序什么都不做,因为这不会有任何明显的副作用(除了执行时间)。

标签: c++ g++ icc dynamic-execution


【解决方案1】:

没有线条

std::cout << sum << std::endl; 

编译器会意识到删除这个

for (int i = 0; i < N; i++)
{
    if (array[i])
        sum++;
}

没有可观察到的效果(计算 sum 的两个循环也是如此)。因此也是这个

for (int i = 0; i < N; i++)
    {
        if (dis(gen) > 0.5)
            array[i] = true;
        else
            array[i] = false;
    }

可以在没有明显效果的情况下移除。

这是所谓的 as-if-rule 的一个示例。简而言之,只要可观察到的行为不改变,编译器就可以做任何事情。更多详情请见What exactly is the "as-if" rule?

顺便说一下,测量运行时间并不能算作程序的可观察行为。

【讨论】:

  • 如何测量执行时间而不用担心“as-if”规则?
  • @user3786219 这很难可靠地做到。要么你测量真正的应用程序,而不仅仅是微基准。然后你确定优化的代码就是你想要测量的。或者你使用一个工具,例如quick-bench.com。我不太了解,但正如您所见,它具有抑制不需要的优化的特殊功能 (benchmark::DoNotOptimize(created_string);)
  • @user3786219 简单的答案是:始终使用结果,例如在屏幕上打印。但如前所述,很难确保您衡量的是您真正想要衡量的内容。
  • @user3786219 quick-bench.com 会有所帮助。
  • @user3786219:在进行微基准测试时,您总是必须担心编译器优化问题。这就是重点:准确查看编译器在使用某些结果的周围代码的给定上下文中做了什么,但不关心本地临时变量的结果。以及该 asm 在给定 CPU 上的运行情况。所以是的,当然你必须控制代码的哪些部分是编译器必须产生的必要输出。
猜你喜欢
  • 1970-01-01
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多