使用volatile关键字进行setjmp/longjmp操作的性能开销

3
为了使 setjmp/longjmp 起作用,您需要将本地变量声明为 volatile。如果有人使用 -O3 编译代码,那么 volatile 变量对性能的影响会有多大?在 x86 多核平台上,它会很大还是只有一点点?
在我看来,这只会增加一点点开销,因为那个 volatile 变量仍然可以被缓存,从缓存中读取/写入也非常快。你们有什么看法?

这是否可能在您的代码中造成重大的性能损失?如果是,有什么阻止您使用volatile来测量性能和非性能? - Chris Lutz
1
关于这个问题,除了你已经表达的观点外,没有太多可以概括的。这取决于架构和使用模式。如果有很多负载/存储操作,请查看汇编代码,与相同但非“volatile”代码进行比较。如果仍然不清楚,请进行基准测试,这是唯一确定的方法。此外,您只需要声明那些在“longjmp”之前需要更改并且之后访问的变量为“volatile”。根据我的经验,gcc在检测这些情况方面相当不错。 - Jens Gustedt
Chris,我是从理论角度在谈论。 - MetallicPriest
2个回答

5
作为一个简要说明,volatile的语义都取决于平台/编译器。在一些具有IA64架构的编译器,如MSVC上,volatile关键字不仅可以防止编译器重新排序操作,还会对每个读/写操作执行获取/释放语义,这意味着存在内存屏障操作。另一方面,GCC只能防止编译器在读/写易失性存储器位置之前/之后重新排序操作...在具有弱内存模型的平台上,无法像MSVC那样维护获取-释放语义。
现在,在x86上,由于其严格排序的内存模型,使用volatile关键字的内存屏障的存在并不是一个问题,因此主要的惩罚将只是缺乏重排序和其他优化,这些优化可以由编译器执行。 也就是说,这将取决于您的代码外观。例如,如果您的代码中有一个紧密循环,并且某些带有volatile限定符的变量实际上是循环不变量,则如果这些内存位置被标记为非volatile,则您将无法获得编译器可以执行的某些优化。

2
影响取决于本地变量的数量以及代码对它们的操作。我确信可以举出一个极端的例子来说明volatile的巨大影响(例如声明一个比CPU缓存更大的volatile变量数组)。
实际上,似乎没有人想要维护所有变量都必须是volatile的代码。这意味着包含setjmp的函数可能会很小,很可能只包含setjmp相关内容。在这种情况下,将几乎没有volatile变量,它们的“影响”应该很小。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接