Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对于{A=A;B=B;},will;A=A";必须严格执行“之前”;B=B";?_C++_C_Optimization_Compiler Construction_Standards - Fatal编程技术网

C++ 对于{A=A;B=B;},will;A=A";必须严格执行“之前”;B=B";?

C++ 对于{A=A;B=B;},will;A=A";必须严格执行“之前”;B=B";?,c++,c,optimization,compiler-construction,standards,C++,C,Optimization,Compiler Construction,Standards,假设A、B、A和B都是变量,A、B、A和B的地址都不同。然后,对于以下代码: A = a; B = b; < > C++和C++标准明确要求 a= a < /> >在代码> b= b< />之前严格执行吗?考虑到A、B、A和B的地址都不同,编译器是否允许出于优化等目的交换两条语句的执行顺序 编辑:问题的背景如下。在棋盘游戏人工智能设计中,用于优化人们使用的,其正确性在很大程度上取决于执行顺序,如果我们不添加volatile限制。这两个标准都允许这些指令无序执行,只要这不会改变可观察的行为。这

假设
A
B
A
B
都是变量,
A
B
A
B
的地址都不同。然后,对于以下代码:

A = a;
B = b;
< > C++和C++标准明确要求<代码> a= a < /> >在<>代码> b= b< />之前严格执行吗?考虑到
A
B
A
B
的地址都不同,编译器是否允许出于优化等目的交换两条语句的执行顺序

<如果我的问题的答案在C和C++中是不同的,我想知道两者。< /P>
编辑:问题的背景如下。在棋盘游戏人工智能设计中,用于优化人们使用的,其正确性在很大程度上取决于执行顺序,如果我们不添加
volatile
限制。

这两个标准都允许这些指令无序执行,只要这不会改变可观察的行为。这被称为“假设规则”:


请注意,正如评论中指出的,“可观察行为”是指具有已定义行为的程序的可观察行为。如果您的程序有未定义的行为,则编译器可以不对此进行推理。

如果指令没有依赖性,如果最终结果不受影响,这些指令也可能会无序执行。您可以在调试以更高优化级别编译的代码时观察到这一点。

编译器只负责模拟程序的可观察行为,因此,如果重新排序不会违反该原则,则允许重新排序。假设行为定义良好,如果您的程序包含诸如数据竞争之类的内容,那么程序的行为将是不可预测的,正如所评论的那样,需要使用某种形式的同步来保护关键部分

有用的参考资料

一篇有趣的文章介绍了这一点,它说:

内存重新排序的基本规则,这是普遍遵循的 编译器开发人员和CPU供应商可以使用以下措辞:

不应修改单线程程序的行为

一个例子

本文提供了一个简单的程序,我们可以在其中看到这种重新排序:

int A, B;  // Note: static storage duration so initialized to zero

void foo()
{
    A = B + 1;
    B = 0;
}
并显示在更高的优化级别上,
B=0
A=B+1
之前完成,我们可以使用重现该结果,使用
-O3
时产生以下结果():

为什么?

编译器为什么要重新排序?这篇文章解释说,由于体系结构的复杂性,处理器这样做的原因与此完全相同:

正如我在开始时提到的,编译器修改内存的顺序 与处理器进行交互的原因相同—— 性能优化。这样的优化是直接的结果 现代CPU的复杂性

标准

< C++标准草案中,这一部分涵盖了<代码> 1.9 >代码>程序执行(强调我的前进):

本国际标准中的语义描述定义了 参数化非确定性抽象机器。这个国际 标准对一致性的结构没有要求 实现。特别是,它们不需要复制或模仿 抽象机器的结构更确切地说,是一致性实现 需要模拟(仅)抽象的可观察行为 机器如下所述。5

脚注
5
告诉我们这也被称为假设规则:

这一规定有时被称为“仿佛”规则,因为 实施可自由忽略本协议的任何要求 国际标准只要结果符合要求 根据可观察到的情况,已被遵守 程序的行为。例如,实际的实现需要 如果表达式可以推断其值为 未使用,且无影响患者可观察行为的副作用 节目制作完成了

C99草案和C11草案标准在
5.1.2.3节
程序执行中涵盖了这一点,尽管我们必须查看索引,以查看它在C标准中也被称为“如同规则”:

作为−如果规则为5.1.2.3

关于无锁注意事项的更新

本文很好地介绍了这个主题,对于OPs关于无锁共享哈希表实现的关注点,本节可能是最相关的部分:

内存排序

正如流程图所示,任何时候您对 多核(或任意),而您的环境 不保证序贯一致性,必须考虑如何预防

在当今的体系结构中,执行正确内存排序的工具 通常分为三类,这两类可防止和:

  • 一个轻量级的同步或围栏指令,我将在中讨论
  • 一个完整的内存围栏指令,我已经完成了
  • 提供获取或释放语义的内存操作
获取语义防止后续操作的内存重新排序 它以程序顺序运行,并且释放语义防止内存重新排序 在它之前的操作。这些语义特别合适 如果存在生产者/消费者关系,其中 线程发布一些信息,另一个线程读取这些信息。我也会 在以后的帖子中更多地讨论这个问题


因为A=A;B=B;在数据依赖性方面是独立的,这不重要。如果有前一条指令的输出/结果,则影响
movl    $0, B(%rip) #, B
addl    $1, %eax    #, D.1624
{ A=a, B=b; /*etc*/ }