1

Regarding OOO, lets assume I have one process only (with one thread) that runs this code:

void foo() {

    if (x == 0) {
        return;
    }

    y->data = 5;

}

Now, lets assume I know that y is valid only if x is not zero. from hardware perspective, can the CPU execute y->data = 5 before reading x? It may cause the CPU to access a NULL/garbage pointer and crashs.

And if not, what is the reason for this? because if/while/for/goto are control statements and the CPU will not fetch ahead instructions when it sees a control statement?

A I remember, OOO should be 100% transparent to one thread executing its instructions.

4

2 回答 2

2

取决于你如何看待它。

  • 从用户的角度来看,没有。
  • 从 CPU 的角度来看,是的。

从用户的角度来看,程序的行为必须“好像”它是按顺序运行的。
换句话说,顺序运行和OOE运行之间没有明显的区别。(除了可能的表现)

从 CPU 的角度来看,是的,它实际上可以绕过 if 语句并执行y->data = 5;。但这是因为分支预测而不是OOE。


在现代处理器上,线程可能会错误地预测分支:

if (x == 0) {
    return;
}

并实际尝试执行y->data = 5;...

如果发生这种情况并且y是一个坏指针,它将获得硬件异常,但由于执行仍处于推测模式,该异常被保留。

一旦线程意识到它错误地预测了分支,它将丢弃分支之外的所有内容(包括异常)。

所以最后,没什么好担心的。即使处理器试图做一些它不能做的事情,它也不会影响顺序行为。

换句话说,如果现代处理器弄得一团糟,那不是你的错,它会自行清理。


当你有多个线程时,事情会变得更丑陋,但这超出了这个问题的范围。

于 2013-07-02T19:37:24.323 回答
0

答案是:视情况而定。

C 标准描述了一个抽象机器,其中优化问题是无关紧要的。除了对volatile对象的访问之外,如果它不改变程序的可观察行为,则实现可以自由地重新排序语句。C11 为程序的可观察行为提出了一个定义:

(C11, 5.1.2.3p6) “对符合性实现的最低要求是:

— 对 volatile 对象的访问严格按照抽象机的规则进行评估。

— 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序所产生的结果相同。

— 交互设备的输入和输出动态应按照 7.21.3 的规定进行。这些要求的目的是尽快出现无缓冲或行缓冲的输出,以确保在程序等待输入之前实际出现提示消息。

这是程序的可观察行为"

C11 也有这一段(已经存在于 C99 中):

(C11,5.1.2.3p10)“或者,实现可能会在每个翻译单元内执行各种优化,以便实际语义只有在跨翻译单元边界进行函数调用时才会与抽象语义一致。[...]”

所以在你的例子中,它实际上取决于如何y声明(即它的链接是什么?)以及它在程序中的使用方式。

编译器在现实生活中实际上使用重新排序来优化代码的某些部分,如果它认为它不会影响程序的可观察行为。

于 2013-07-02T19:52:00.303 回答