在这种情况下,两个负载是否会合并为一个? 如果这是依赖于架构的,那么英特尔的现代处理器会出现什么情况呢?我相信原子负载相当于英特尔处理器的正常负载。
void run1() {
auto a = atomic_var.load(std::memory_order_relaxed);
auto b = atomic_var.load(std::memory_order_relaxed);
// Some code using a and b;
}
void run2() {
if (atomic_var.load(std::memory_order_relaxed) == 2 && /*some conditions*/ ...) {
if (atomic_var.load(std::memory_order_relaxed) * somevar > 3) {
/*...*/
}
}
}
run1()
和run2()
只是使用两个相同原子变量的两个场景。编译器是否可以将两个加载的场景折叠到一个加载中并重用它?
答案 0 :(得分:4)
GCC(6.3)和Clang(3.9)目前都没有将两个负载优化为一个。
要知道的唯一方法是查看生成的程序集:https://godbolt.org/g/nZ3Ekm
答案 1 :(得分:3)
run1()
的实施可以安全地优化到
void run1() {
auto a = atomic_var.load(std::memory_order_relaxed);
auto b = a;
// Some code using a and b;
}
在原始程序中,每次atomic_var
调用run1()
时,两个加载可能在load()
的访问总顺序中彼此相邻。在这种情况下,相邻的load()
操作将返回相同的结果。
由于无法排除这种可能性,因此允许编译器优化第二个run2()
。这可以针对任何内存顺序参数来完成,而不仅仅是为了放松原子。
取决于/*some conditions*/
。您没有指定load()
。如果有什么东西,可能会对原子变量产生明显的副作用(比如不透明的函数调用或访问volatile变量等),那么就无法对其进行优化。否则它可能是可能的。
取决于您的编译器。可能还有你传入的编译器选项。可能它取决于你的平台。关于编译器是否应该优化原子,存在一些争论。有N4455 No Sane Compiler Would Optimize Atomics和this video作为主题的开头。
GCC和clang目前还没有优化两个db.mongoAuditEvent.aggregate([
{$group: {_id : "$corrId", currentEvent: {"$last": "$event.status"}, events: { $push: "$$ROOT"} }},
{$sort: {"timestamp": 1} },
{$skip: 0 },
{$limit: 10}
], {allowDiskUse: true}).pretty()
操作。