我想知道为什么没有编译器准备将相同值的连续写入合并到单个原子变量,例如:
#include <atomic>
std::atomic<int> y(0);
void f() {
auto order = std::memory_order_relaxed;
y.store(1, order);
y.store(1, order);
y.store(1, order);
}
Run Code Online (Sandbox Code Playgroud)
我尝试过的每个编译器都会发出三次上面的编写.什么合法的,无种族的观察者可以看到上述代码与具有单次写入的优化版本之间的差异(即,不是"假设"规则适用)?
如果变量是易变的,那么显然不适用优化.在我的情况下有什么阻止它?
这是编译器资源管理器中的代码.
考虑下面的C++ 11片段.对于GCC和clang,这会编译为两个(顺序一致的)foo.C++内存模型是否允许编译器将这两个加载合并到一个加载中并对x和y使用相同的值?
我认为它不能合并这些负载,因为这意味着轮询原子不再起作用,但我找不到内存模型文档中的相关部分.
#include <atomic>
#include <cstdio>
std::atomic<int> foo;
int main(int argc, char **argv)
{
int x = foo;
int y = foo;
printf("%d %d\n", x, y);
return 0;
}
Run Code Online (Sandbox Code Playgroud) c++ memory-model compiler-optimization language-lawyer stdatomic
我现在正在学习C++ 11内存阶模型,并想明白之间的差别memory_order_relaxed和memory_order_consume.
具体而言,我正在寻找一个简单的例子,其中一个不能代替memory_order_consume用memory_order_relaxed.
有一篇很好的文章详细阐述了一个memory_order_consume可以应用的简单但非常具有说明性的例子.下面是文字复制粘贴.
例:
atomic<int*> Guard(nullptr);
int Payload = 0;
Run Code Online (Sandbox Code Playgroud)
制片人:
Payload = 42;
Guard.store(&Payload, memory_order_release);
Run Code Online (Sandbox Code Playgroud)
消费者:
g = Guard.load(memory_order_consume);
if (g != nullptr)
p = *g;
Run Code Online (Sandbox Code Playgroud)
我的问题包括两部分:
memory_order_consume用memory_order_relaxed在上面的例子?memory_order_consume不能被替换memory_order_relaxed?Let's consider this trivial code:
#include <atomic>
std::atomic<int> a;
void f(){
for(int k=0;k<100;++k)
a.load(std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)
MSVC, Clang and GCC all perform 100 loads of a, while it seems obvious it could have been optimized away. I expected the function f to be a nop (See generated code here)
Actually, I expected this code generation for a volatile atomic:
volatile std::atomic<int> va;
void g(){
for(int k=0;k<100;++k)
va.load(std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)
Why do compilers not optimize away unnecessary atomic loads?
正如我从测试用例中看到的:https : //godbolt.org/z/K477q1
生成的程序集加载/存储原子放松与普通变量相同:ldr 和 str
那么,松弛原子变量和普通变量之间有什么区别吗?
使用解锁的布尔值比使用std::atomic<bool>始终以宽松的内存顺序完成操作的方法有效率吗?我认为两者最终都可以编译为同一机器代码,因为单个字节实际上在X64硬件上是原子的。我错了吗?
我似乎无法在商店之后获得原子对象的地址。
例如
std::atomic<int> i;
std::atomic<int>* p = &++i; // doesn't work
auto* p = &++i; // doesn't work
// below works:
++i;
auto* p = &i;
Run Code Online (Sandbox Code Playgroud)
这里发生了什么,为什么?
澄清一下:我知道它返回一个 r 值。为什么它不返回原始对象,this?这是一个有目的的设计选择还是一个疏忽?
更具体地说,这个要求的幕后发生了什么?
c++ ×8
stdatomic ×4
atomic ×3
c++11 ×3
memory-model ×2
volatile ×2
c++-faq ×1
c++17 ×1
performance ×1
x86-64 ×1