【问题标题】:Can and does the compiler optimize out two atomic loads? [duplicate]编译器是否可以优化两个原子负载? [复制]
【发布时间】:2017-06-08 19:12:37
【问题描述】:

在这种情况下,两种负载是否会合二为一? 如果这取决于架构,那么说英特尔的现代处理器会是什么情况?我相信原子负载相当于英特尔处理器中的正常负载。

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() 只是使用两个加载相同原子变量的两个场景。编译器能否将这种两次加载的场景折叠成一次加载并重用它?

【问题讨论】:

  • 抱歉,为什么你同时拥有run1run2?您能否更具体地回答您的问题?
  • @Brian 简单的两种情况。已编辑。

标签: c++ gcc x86 atomic compiler-optimization


【解决方案1】:

编译器可以优化掉原子负载吗?

您的run1() 实现可以安全地优化为

void run1() {
    auto a = atomic_var.load(std::memory_order_relaxed);
    auto b = a;
   // Some code using a and b;
}

在原始程序中,每次调用run1() 时,这两个负载可能在访问atomic_var 的总顺序中彼此相邻。在这种情况下,相邻的load() 操作将返回相同的结果。

由于不能排除这种可能性,因此允许编译器优化第二个load()。这可以为任何内存顺序参数完成,而不仅仅是宽松的原子。

对于run2(),这取决于。您没有指定/*some conditions*/。如果有什么东西,可能会对原子变量产生可见的副作用(比如不透明的函数调用或访问 volatile 变量等),那么就无法对其进行优化。否则有可能。

编译器是否优化了两个原子加载?

取决于您的编译器。并且可能取决于您传入的编译器选项。可能取决于您的平台。关于编译器是否应该优化原子,存在一些争论。有N4455 No Sane Compiler Would Optimize Atomicsthis video 作为主题的开始。

GCC 和 clang 目前没有将两个 load() 操作优化为一个。

【讨论】:

  • 所以,目前的答案是标准允许,但现代编译器不这样做,这仍然是讨论的主题。
  • 这可能是正确的。至少在这种情况下,他们没有优化(很多)。也许他们在其他情况下会这样做。当然,现代优化编译器在其内存排序允许的情况下围绕原子执行存储和加载的重新排序。对于 C++ 程序员来说,C++ 标准是编写代码的接口。依赖编译器是否优化某些东西通常不是一个好主意,因为否则任何新的编译器更新都会引入错误。
  • 最近的一个问题询问了关于合并重复存储的相同问题。我的答案与您在此处的答案基本相同,包括链接 N4455(还有wg21.link/p0062)。还有一些关于为什么编译器选择不这样做的东西,直到解决这个问题。
  • 无论如何,所以我把它作为新的副本关闭了。
  • "关于编译器是否应该优化原子存在一些争论" 但没有争论在这种简单的情况下优化是否有效
【解决方案2】:

GCC (6.3) 和 Clang (3.9) 目前都没有将这两种负载优化为一个。

唯一知道的方法是查看生成的程序集:https://godbolt.org/g/nZ3Ekm

【讨论】:

  • 标准允许吗? volatile 不是说您每次都需要加载吗?为什么这算原子。
  • @themagicalyang:std::atomic不一定要用volatile,应该可以把memory_order_relaxed下的两个负载结合起来。你可以在 GCC 的 bug tracker 上提交一份报告,看看他们怎么说。如果你这样做,请务必在此处链接到它!
  • @themagicalyang:如果你想要一个 volatile std::atomic<int> ,那么就使用它。但是您忽略了atomic_var 的定义,所以我们没有理由假设它是volatile
  • 很多关于这方面的信息可以在 JF Bastien 的优秀帖子中找到:open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4455.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 1970-01-01
  • 2015-09-08
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多