在C ++ 11中允许对循环进行编译器优化 [英] Allowed compiler optimizations on loops in C++11

查看:126
本文介绍了在C ++ 11中允许对循环进行编译器优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否允许C ++ 11兼容的编译器从以下位置优化/转换此代码:

Is a C++11-compliant compiler allowed to optimize/transform this code from:

bool x = true; // *not* an atomic type, but suppose bool can be read/written atomically
/*...*/
{
    while (x); // spins until another thread changes the value of x
}

等效于无限循环:

{
    while (true); // infinite loop
}

从单线程程序的角度来看,上述转换当然是有效的,但这不是一般情况.

The above conversion is certainly valid from the point of view of a single-thread program, but this is not the general case.

还可以在C ++ 11之前的版本中允许这种优化吗?

Also, was that optimization allowed in pre-C++11?

推荐答案

绝对.

由于x没有标记为volatile,并且似乎是具有自动存储期限和内部链接的本地对象,并且该程序未对其进行修改,所以这两个程序是等效的.

Since x is not marked as volatile and appears to be a local object with automatic storage duration and internal linkage, and the program does not modify it, the two programs are equivalent.

在C ++ 03和C ++ 11中,这都是按常规规则,因为认为访问非易失性对象是程序的副作用" :

In both C++03 and C++11 this is by the as-if rule, since accessing a non-volatile object is not considered to be a "side effect" of the program:

[C++11: 1.9/12]: 访问由易失性glvalue(3.10)指定的对象,修改对象,调用库I/O函数或调用执行任何这些操作的函数都是副作用,这些副作用是执行环境状态的变化.对表达式(或子表达式)的求值通常包括 值计算(包括确定对象的身份以进行glvalue评估以及获取先前分配给对象的值以进行prvalue评估)和副作用的初始化.当返回对库I/O函数的调用或评估了对易失对象的访问时,即使该调用或volatile访问所隐含的某些外部操作(例如I/O本身)也被认为是完全的副作用.可能尚未完成.

[C++11: 1.9/12]: Accessing an object designated by a volatile glvalue (3.10), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression (or a sub-expression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects. When a call to a library I/O function returns or an access to a volatile object is evaluated the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile access may not have completed yet.

C ++ 11确实为 global 对象腾出了空间,使其在一个线程中更改其值,然后在另一个线程中读取该新值:

C++11 does make room for a global object to have its value changed in one thread then that new value read in another:

[C++11: 1.10/3]:线程T在特定点处可见的对象的值是该对象的初始值,T分配给该对象的值或分配给该对象的值.根据下面的规则.

[C++11: 1.10/3]: The value of an object visible to a thread T at a particular point is the initial value of the object, a value assigned to the object by T, or a value assigned to the object by another thread, according to the rules below.

但是,如果您这样做的话,由于您的对象不是原子的:

However, if you're doing this, since your object is not atomic:

[C++11: 1.10/21]:如果程序的执行在不同线程中包含两个冲突的动作,则其中至少一个不是原子的,并且两个动作都没有发生在另一个线程上,则该程序的执行将引起数据争用.任何此类数据争用都会导致未定义的行为.

[C++11: 1.10/21]: The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.

而且,当调用未定义的行为时,任何事情都可能发生.

And, when undefined behaviour is invoked, anything can happen.

[C++11: 1.10/25]:实现应确保原子或同步操作分配的最后一个值(按修改顺序)将在有限的时间内对所有其他线程可见.

[C++11: 1.10/25]: An implementation should ensure that the last value (in modification order) assigned by an atomic or synchronization operation will become visible to all other threads in a finite period of time.

同样,请注意,该对象必须是 atomic (例如std::atomic<bool>)才能获得此保证.

Again, note that the object would have to be atomic (say, std::atomic<bool>) to obtain this guarantee.

这篇关于在C ++ 11中允许对循环进行编译器优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆