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*/ }