在计算一段代码时,我是否需要易失性?

时间:2013-12-03 12:14:34

标签: c++ volatile timing

我想自动调整我的代码,因此必须测量某些代码段所需的时间,例如

auto t0 = std::chrono::high_resolution_clock::now();
section_of_code_to_be_timed(arguments);
auto dt = std::chrono::duration_cast<std::chrono::nanoseconds>
         (std::chrono::high_resolution_clock::now()-t0).counts();
// ... using dt to tweak auto-tuning parameters

我担心的是编译器可能会重新安排对std::chrono::high_resolution_clock::now()section_of_code_to_be_timed()的调用,从而使我的时序测量无效。这是一个有效的担心吗?如果是,我可以通过声明t0 volatile或其他方式(如何)来阻止它吗?

(我注意到我可以使用RAII习语,类似于std::lock_guard,似乎没有使用volatile ...)

3 个答案:

答案 0 :(得分:4)

正式还是实际?正式,致电 std::chrono::high_resolution_clock::now()无法观察到 行为,因此编译器可以以任何方式重新排列它们。 实际上,编译器会将它们视为可观察的行为, 所以你在这个分数上不会有任何问题。在另一 亲自动手,你最好做些什么来确保这一点 section_of_code_to_be_timed实际上做了一些事情。 (我经常 使它成为一个类的虚拟成员,引入足够的 间接欺骗大多数编译器。而在功能本身, 我确保它产生一个在外面可见的结果 功能。)

请注意,无论哪种方式,volatile都无关紧要。关于它 确保以正确的顺序写入t0dt (在实践中,它往往不能确保);它没有 关于section_of_code_to_be_timed的保证 t0dt

答案 1 :(得分:1)

使用volatile来控制对异常内存位置(例如硬件寄存器)的访问,其中每次读取和写入都必须按程序指定的顺序进行。正常变量(原子或其他)通常不需要这样的控制。

这两个概念彼此无关。特别是,不要将volatile与其他语言中使用的关键字混淆,以使变量成为原子。在C ++中,volatile与线程交互无关。

答案 2 :(得分:1)

您可以插入“编译器障碍”:遗憾的是,此类构造不是标准的。

在gcc(和clang?)下__asm__ __volatile__ ("" ::: "memory")将充当一个完整的障碍(注意:编译器障碍是一个内存障碍)。

我没有方便,但是http://msdn.microsoft.com/en-us/library/f20w0x5e.aspx表示_ReadWriteBarrier();应该在VC ++下给出类似的效果(尽管它已被弃用)。其他编译器可能支持也可能不支持自己的等价物。

最后,C ++ 11确实提供了atomic_signal_fence,看起来很有希望,但我不清楚它是否做得对。