为什么GCC使用mov/mfence而不是xchg来实现C11的atomic_store?

11

C++ and Beyond 2012:Herb Sutter - atomic<> Weapons,第2部分中,Herb Sutter(约在0:38:20左右)认为应该使用xchg而不是mov/mfence来实现x86上的atomic_store。他似乎还暗示这个特定的指令序列是所有人都同意的。然而,GCC使用后者。为什么GCC使用这个特定的实现方法?


1
这个之前问题的答案已经基本涵盖了:https://dev59.com/0WEh5IYBdhLWcg3wjEDn#22283062 - Ross Ridge
1个回答

3
简单来说,movmfence方法更快,因为它不会像xchg那样触发冗余的内存读取,而后者需要花费更多时间。x86 CPU 保证线程之间的写入顺序严格一致,因此足够了。
请注意,一些非常旧的CPU存在一个mov指令的错误,这使得xchg必需。但这已经是很久以前的事情了,对大多数用户来说,解决这个问题并不值得付出额外的开销。
感谢@amdn提供关于老款Pentium CPU中引起xchg必需的信息。

我很好奇为什么Herb Sutter在2012年主张使用xchg,因为他似乎对这个主题很有了解。 - tibbe
1
@tibbe 我个人的猜测是,在过去的某个时候,xchg 更好,我发现一些过时的文档中提到 mfence + mov 在某些 Athlon 处理器上速度较慢,在一些早期的 Pentium 处理器上则无法正常工作。也许这些建议曾经是明智的,但现在已经有点过时了。不过他可能在演讲之前做了一些研究,并且那时使用的 CPU 甚至更加过时,我可以想象他可能得出了这样的结论。然而,几乎所有的文档都说,如果不是非常老的 CPU,mov mfence 路径在现代 CPU 上更快。 - Vality
1
在实践中,mov+mfence速度较慢;GCC最近为seq_cst存储切换了使用方式,现在像其他编译器一样使用xchg。它已经需要将缓存行的副本转换为独占所有权状态(除了全行写入,提交存储需要一个最新的行副本),因此额外的读取根本不重要。另请参见Does lock xchg have the same behavior as mfence?,并注意Skylake微码更新,使mfence具有类似于lfence的OoO exec屏障,而不像xchg - Peter Cordes
@PeterCordes 这可能现在是真的。距我上次调查这个问题已经过去了约十年(看答案的年龄)。我现在没有时间更新这个答案,但如果你能写一个更加最新的答案(大致说一下你在评论中所说的),我相信OP会很感激,我也会很乐意点赞。 - Vality
1
有现成的问答涵盖了这个问题,也许我们可以将其标记为重复。我再找了一些,发现LOCK XCHG和MOV+MFENCE之间的逻辑和性能差异是什么?,它本身就有一些重复的链接。我的回答在x86上哪个写屏障更好:lock+addl还是xchgl?至少提到了它。啊,终于找到了一个关于性能差异的好答案:为什么具有顺序一致性的std::atomic存储使用XCHG? - Peter Cordes

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