计时与"as-if"规则

Timing vs the "as-if" rule

本文关键字:as-if 规则      更新时间:2023-10-16

关于" as-if"的一个很好的问题一般而言,我想知道在测量时间时是否有任何例外。

考虑此(从此处稍作修改):

using std::chrono;
auto begin = steady_clock::now();
auto result = some_lengthy_calculation(some_params);
auto end = std::chrono::steady_clock::now();
std::cout << "Time diff = " << duration_cast<microseconds>(end - begin).count() <<std::endl;
std::cout << "Result = " << result;

允许编译器应用任何导致相同result的优化。这里的重点是"如果"规则不直接适用于测量时间。当然,在应用优化时,测得的时间不是应该恒定的。

所以我的问题是:根据"如果"规则,允许编译器将其重新排列为以下一个?

auto temp = some_lengthy_calculation(some_params); // clever "optimization", precompute some stuff
auto begin = steady_clock::now();
auto result = temp;               // yay, I can use it here to pretend to be faster
auto end = steady_clock::now();
std::cout << "Time diff = " << duration_cast<microseconds>(end - begin).count() <<std::endl;
std::cout << "Result = " << result;

甚至更优化:

std::cout << "Time diff = " << 42 <<std::endl;
std::cout << "Result = " << some_lengthy_calculation(some_params);

我假设没有理智的编译器会这样做,但是是什么使编译器无法执行"?

"。

tl; dr ...

  • 人们可以观察优化和非优化代码之间的运行时差
  • 如果允许编译器优化实施测量时间,那么什么阻止编译器根本不为时机创建任何代码?

为了应用AS-IF规则,编译器必须证明所提出的更改对可观察的行为没有影响。您是正确的,时间的流逝不是可观察到的行为。但是,在重新排序功能的情况下,必须证明调用该函数的顺序不会影响可观察的行为。

使用定时功能始终涉及一些用于测量时间的机制,这些机制将无法证明可以证明这是安全的。例如,它可能涉及无法检查的不透明系统API功能或驱动程序功能的调用。如果我们以最透明的示例,每次采用状态时,它只是按1个单位前进的单调软件时钟,则无法证明呼叫顺序并不重要,因为这确实很重要。

<</p>

编译器不会做到这一点,您可以确定。

在纯理论中,将允许使用系统时间涉及系统呼叫,这是编译器的完整黑匣子。

编译器无法在黑匣子功能调用周围重新排序,因为它不能假设这不会有任何副作用或包含任何障碍。