C语言中的序列点是啥意思

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言中的序列点是啥意思相关的知识,希望对你有一定的参考价值。

参考技术A 序列点,就是按时间顺序排列的点,在程序中,按计算顺序的时间排列的点或位置。

比如在C语言中有些“复杂表达式”(逗号表达式,连续赋值表达式)意思表达很含混,只有整个计算式计算完后,才尘埃落定,“副作用消失”,那么,计算式计算完后才算一个 “序列点”。

sfence 文档中的“序列化操作”是啥意思?

【中文标题】sfence 文档中的“序列化操作”是啥意思?【英文标题】:What does "serializing operation" mean in the sfence documentation?sfence 文档中的“序列化操作”是什么意思? 【发布时间】:2018-05-23 05:34:30 【问题描述】:

documentation 代表 sfence 说:

对所有存储到内存的指令执行序列化操作 在 SFENCE 指令之前发出。

“序列化操作”是什么意思?

这是否意味着确保在sfence 指令之前发出的所有存储到内存指令都已完成,然后再继续执行sfence 之后的指令

【问题讨论】:

您阅读过英特尔文档的其余部分吗?应该有一些部分解释什么是序列化操作。 是的,序列化指令也是全内存屏障;它们有效地刷新了整个管道 (Does lock xchg have the same behavior as mfence?),这与 Intel 上的 lfence 不同,后者只是序列化指令执行,而不是存储缓冲区。 Why is (or isn't?) SFENCE + LFENCE equivalent to MFENCE? 您正在阅读旧版本的文档。 new version 删除了上面的语言,并用更清晰的语言替换了它,除其他外,处理器确保 SFENCE 之前的每个商店都是全球可见的,然后 SFENCE 之后的任何商店都是全球可见的。是关于你将要得到的一个很好的一句话总结。 【参考方案1】:

sfence 确保程序顺序中的所有先前存储在程序顺序中的任何后续存储变得全局可见之前变得全局可见。与您所写的内容相比,有两个不同之处。首先,sfence 不会序列化之前发布的商店;它序列化所有以前的商店,无论它们是否已发行。其次,它仅针对所有后来的商店进行序列化;不是所有以后的说明。这就是sfence 上下文中“序列化操作”的含义。

您只引用了文档中的第一句话,但每句话都很重要。

【讨论】:

我认为(并希望)OP 使用的是英特尔的术语,其中“已发布”的意思是“重命名并插入到无序内核中”。这是按程序顺序发生的,因此sfence 之前的所有指令都已经发出。您假设另一个约定,其中发出/调度交换的含义。你说得对,sfence 订购了所有 个以前的存储,而不仅仅是那些已经分派到执行端口并将某些内容写入存储缓冲区的存储。 @PeterCordes - 可能英特尔在这里只是玩弄术语。我不认为他们真的想说订单与调度或问题有任何关系(无论命名约定如何),因为这是一个内部细节,在任何 ISA 文档中都没有用(如果他们正在向欧盟谈论问题)这真的没有任何意义,因为那是无序的)。正如哈迪所说,它们实际上只是意味着“按程序顺序排在第一位”。令人困惑的是,他们提到了之前发生的商店,但没有提到之后发生的商店,好像有一些不对称 - 但没有。 这可能只是内部细节的一些泄漏:它的工作方式主要是确保任何优秀的商店(弱排序的)进入 L1 或以其他方式排序 - 但实际上是两个商店的方式围栏。 current doc 完全改变了语言并且更加清晰,不是在谈论“序列化”,而是谈论排序保证,并消除了不对称的暗示。序列化只在简短描述中提到:“序列化存储操作。” 在英特尔手册中,serialization 这个词的使用也有点过重,因为“序列化指令”是一种特殊的东西(如您所知),@987654327 @ 不是其中之一。 IMO当前的文本要好得多。当我说不对称的暗示消失时,我也撒了谎——第一句话是:在 SFENCE 指令之前相对于所有内存存储命令处理器执行。 但是,下一个语句将其清除 IMO: 处理器确保 SFENCE 之前的每个商店都是全局可见的,然后 SFENCE 之后的任何商店成为全球可见的。 @BeeOnRope 是我自己还是突然对 [x86] 内存顺序/屏障/栅栏问题的兴趣大增?【参考方案2】:

英文单词Serial - adjective form:

    连续发生而不是同时发生

    计算机。 a) 一次一项的数据处理操作的表面或实际执行的或与之相关的(区别于 平行线)。

    b) 的或与之相关的每个传输或处理 序列中整体的一部分,作为一个字节的每个位或一个字节的每个字节 计算机字(区别于并行)。

(Serialization 也可以意味着将对象表示转换为比特流或字节流,可以存储到磁盘或通过程序外部的网络发送。但 不是含义适用于sfence)。

数据库https://en.wikipedia.org/wiki/Serializability 是一个更密切相关的概念。


SFENCE 订购早期商店相对于 SFENCE 本身的全球可见性,以及后来的商店。 序列化 = 对事物施加顺序,阻止它们重叠或并行发生。


请注意,在英特尔术语中,“序列化指令”具有特殊含义:在任何后续指令执行之前刷新存储缓冲区和乱序指令流水线的指令。 (它们可以解码,甚至可以发送到乱序核心,但不能执行)。 How many memory barriers instructions does an x86 CPU have?

sfence 在这个意义上不是“序列化指令”;它只针对彼此和常规商店订购 NT 商店。 (常规存储已经相互排序,因此sfence 如果没有 NT 存储在运行,则无效。正确的释放语义所需要做的就是将常规存储按正确的顺序放置,例如使用编译器屏障停止编译时重新排序。)

Intel 对sfence 的定义中的“serializing”只是该术语的通俗英文意思,并不是x86 特殊含义的“serializing instruction”。


Intel's ISA ref manual entry for sfence的当前措辞

英特尔将开头的段落改写为“订单”而不是“序列化”,除了简短描述:序列化存储操作。

主要说明是:

相对于 SFENCE 指令之前的所有内存存储来排序处理器执行。处理器确保在 SFENCE 之后的任何存储变得全局可见之前,SFENCE 之前的每个存储都是全局可见的。 SFENCE 指令根据内存存储、其他 SFENCE 指令、MFENCE 指令和任何序列化指令(例如 CPUID 指令)进行排序。它没有按照内存负载或 LFENCE 指令排序。

不过,第一句话还是有点假。 执行没有顺序,只提交到 L1d 缓存。

【讨论】:

您可能想指出,英特尔已从当前版本的手册中删除了 OP 发布的文本,因此我们都在讨论一些过时的内容,其中当前文本更加清晰并且没有依靠“序列化”而不是“排序”。 @BeeOnRope:好主意,更新和引用。描述的第一句话有点假,谈论相对于商店的顺序执行。我们知道它们的意思,但如果我们不知道,我们可能想知道它是否确实对乱序执行产生了影响,而不仅仅是存储缓冲区的提交结束。 是的,第一句话仍然有一点混乱......但它说“相对于所有内存存储”,所以你可以将它理解为“仅命令 处理器执行就像订购商店所必需的那样”,结果却是“根本没有”。如果您认为第二句话是有道理的,这确实是关键,因为它澄清并具体说明了第一句话的结果。不幸的是它说的是处理器执行,因为这听起来像某种指令序列化一样诱人,但我们知道它不是...... @LewisKelsey:这是实现 SFENCE 的一种有效但非常缓慢的方法!这将使它比所需的要强大得多,例如 MFENCE。 (但是,AMD SFENCE 可能是这样的;AMD 对 SFENCE 的保证比 Intel 更强)。 SFENCE 只需要在存储缓冲区中插入一个标记,以阻止 NT 存储在任一方向传递它。 (正规商店已经被强烈订购)。请参阅此答案的“额外阅读”部分:Does a memory barrier acts both as a marker and as an instruction? @LewisKelsey:同一行的两个连续存储可以在存储缓冲区内合并或合并,并在一个缓存写入操作中一起提交。请参阅Unexpectedly poor and weirdly bimodal performance for store loop on Intel Skylake 以及评论所在的答案。 SFENCE 可能会阻止这种合并,但否则 x86 不执行 StoreStore 重新排序意味着存储必须按程序顺序从存储缓冲区提交到 L1d(与弱排序 ISA 不同)。【参考方案3】:

sfence 防止栅栏前的商店相对于栅栏后的商店重新排序。就是这样。不要专注于“序列化”部分:英特尔已删除您从当前版本的手册中引用的文本(您链接了一个过时的源)。

new text says1(强调我的):

相对于所有内存存储在 SFENCE 指令。 处理器确保每个商店之前 SFENCE 成为 SFENCE 之后在任何商店之前都是全局可见的 全局可见。 SFENCE 指令的顺序是关于 内存存储、其他 SFENCE 指令、MFENCE 指令和任何 序列化指令(例如 CPUID 指令)。它不是 根据内存负载或 LFENCE 指令排序。

可以使用弱排序内存类型来实现更高的处理器 通过诸如乱序问题之类的技术来执行, 写组合和写折叠。消费者的程度 的数据识别或知道数据是弱排序的 在应用程序之间,并且可能不为该数据的生产者所知。 SFENCE 指令提供了一种高效的方法 确保产生弱排序的例程之间的商店排序 使用这些数据的结果和例程。

第二行(强调的)是关键:这家伙是来订购商店的。

它不会(必然)使商店变得可见更快 - 这在像 x86 这样的连贯架构上自然发生。它不一定会序列化栅栏周围的指令,包括商店:它只是确保商店没有明显地在栅栏上重新排序。

这里有个秘密:这条指令在 x86 代码中几乎没有用处。 x86 内存模型已经保证正常存储已经相对于彼此完全排序:来自给定 CPU 的存储对所有其他 CPU 都是按程序顺序可见的,因此sfence 不会添加任何内容. sfence 可能有用的唯一例外是像 non-temporal stores 这样相对晦涩的东西,或者像 WC 内存类型这样真正晦涩的东西。如果您不使用它,则不需要此说明。


1 我还链接了一个非官方来源,因为没有我知道的官方 HTML 来源 - 但我检查了它在 sfence 上是最新的2018 年 5 月。

【讨论】:

以上是关于C语言中的序列点是啥意思的主要内容,如果未能解决你的问题,请参考以下文章

C语言中的冒号(:)是啥意思?

C语言中的“class”是啥意思啊?讲下其作用及用法。麻烦了

C语言中的VOID()是啥意思

C语言中的“局部变量”是啥意思?

C语言编辑,这个vs中的错误提示是啥意思

c里面冒号的意思,C语言中的冒号(:是啥意思