0

考虑下面的代码。


#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 << sum << std::endl;则执行时间将显示为零(或足够接近)。我已经在不同的编译器上检查过它,包括带有 O3 编译标志的 icpc、icl (v19.1.2) 和 g++ (v9.2)。

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

4

1 回答 1

1

没有线条

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

编译器会意识到删除这个

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

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

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

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

这是所谓的 as-if-rule 的一个示例。简而言之,只要可观察到的行为不改变,编译器就可以做任何事情。有关更多详细信息,请参阅“as-if”规则到底是什么?

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

于 2020-11-25T22:13:06.730 回答