为什么不必要的原子加载没有被优化掉?

问题描述 投票:0回答:1

让我们考虑这个简单的代码:

#include <atomic>

std::atomic<int> a;
void f(){
    for(int k=0;k<100;++k)
        a.load(std::memory_order_relaxed);
}

MSVC、Clang 和 GCC 都执行 100 次 a 负载,虽然看起来很明显它可以被优化掉。我期望函数

f
是一个 nop (请参阅生成的代码 here

实际上,我期望为易失性原子生成代码:

volatile std::atomic<int> va;
void g(){
    for(int k=0;k<100;++k)
        va.load(std::memory_order_relaxed);
}

为什么编译器不优化掉不必要的原子加载?

c++ code-generation atomic compiler-optimization volatile
1个回答
0
投票

如果调用者这样做

g(); atomic_thread_fence(acquire);
,它可能会与另一个线程创建一个发生之前的关系,如果执行了零负载,则该关系将不存在。由于加载结果被丢弃,它现在可以知道它同步的什么,但完全优化掉负载的效果并不完全明显。

也许存在一些计时原因,在某些实际实现上意味着另一个线程中的某些存储应该对该宽松的负载可见。这听起来相当手动,但某些运行时计时条件可能会导致无 UB 执行,而这种执行可能会通过优化所有负载而被破坏。

将 100 个负载压缩为 1 而不是 0 不会出现此问题,但仍然需要特定的优化过程来查找未使用的负载,这些负载未被任何内存排序效果(如栅栏)分隔。似乎很难否认它的安全性。如果代码依赖于每个负载发生作为延迟措施(或用于 MMIO),则应使用 volatile atomic


一般来说,折叠多个加载或存储是一个单独的事情,已经讨论过:

编译器是否可以优化两个原子加载? / 为什么编译器不合并冗余的 std::atomic 写入?

    https://wg21.link/n4455
  • :N4455 没有健全的编译器会优化原子
  • https://wg21.link/p0062
  • :WG21/P0062R1:编译器何时应该优化原子?
  • 如果其他线程同时写入,同一原子对象的两次连续加载可能会或可能不会产生相同的值。如果编译器使 asm 只加载一次,那么它就可以在编译时有效地确定部分运行时内存排序。这通常在一定程度上是可以的,但正如 WG21 文件指出的那样,这并不总是可以,特别是对于商店而言。 (为具有强大内存模型的 ISA 编译 C++ 程序也会使一些 ISO-C++ 允许的内存排序在实际执行中变得不可能,但它不会消除跨线程的顺序一致执行的可能交错。)

这些都不是将 100 个未使用的负载压缩到 1 个的真正障碍,但它与编译器现在选择根本不优化原子有关,因为它与更棘手的问题相关。

实际原因

编译器内部可能会使用一些现有的对

volatile

的支持来处理原子,即不假设多次读取会给出相同的值。这有一个副作用,基本上就像对待他们一样

volatile atomic
对于 GCC,o11c 链接了 

https://gcc.gnu.org/wiki/Atomic/GCCMM/Optimizations

,了解 GCC 在优化原子方面的限制。它声称 [intro.races]/19 将禁止将 int x=a.load(relaxed); int y=a.load(relaxed); 视为

x=y=a.load(relaxed);
。但这是一种误读。它禁止以
other
顺序执行它们,这可能导致 x
a
的修改顺序中具有更新的值,但强制它们都具有相同的修改顺序值并不违反读读连贯规则
[intro.races]/16
注释是总结。该 GCC wiki 页面的最后一次编辑显然是在 2016 年,即 WG21/P0062R1 之前;希望大多数涉及 C/C++ 原子的 GCC 开发人员从那时起就意识到 ISO 标准在纸面上允许优化,即使对于所使用的负载也是如此。 此外,编译器开发人员可能不愿意添加寻找几乎无法盈利的优化的代码。 GCC、LLVM 和 MSVC 等编译器的较大代码库需要更多的开发工作来维护,可能会减慢其他功能的添加和维护速度。

此外,寻找这样的优化会使编译时间变慢。在这里这可能不是问题;现代提前编译器已经将程序逻辑转换为 SSA 形式,即使在比这更简单的情况下,也应该很容易找到未使用的结果(例如,将加载结果分配给优化后未使用的本地变量时)。对于这种微不足道的情况,编译器已经可以警告未使用的返回值。

© www.soinside.com 2019 - 2024. All rights reserved.