为什么编译器避免合并冗余原子写入
简介
编译器通常坚持“ as-if”规则,允许他们在可观察到的情况下重新排序操作行为保持一致。然而,在连续存储具有相同值的原子变量的情况下,例如:
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); }
编译器倾向于单独发出写入。
C 的限制标准
虽然 C 11 和 C 14 标准在技术上允许合并三个商店,它们不保证观察者会看到 2 的中间值。因此,通过将存储折叠到单个操作中进行优化将违反标准允许任何有效排序的意图。
编译器注意事项
编译器优先考虑优化性能而不是可预测性,这导致了保守的方法。尽管标准允许,但编译器选择不合并原子写入以避免潜在问题,例如当多个存储错误合并时进度条会卡住。
最小惊喜原则
程序员通常期望原子存储按顺序发生,每个存储都按写入的方式执行。如果编译器要合并这些操作,则可能会引入意外行为并违反最小意外原则。
即将推出的 API 增强
C 工作组正在进行讨论使用额外的优化控制来扩展 std::atomic API。这将允许编译器在不违反排序要求的情况下优化原子写入。
替代解决方案
同时,程序员可以使用易失性原子变量防止商店优化。虽然此方法主要解决进度条问题,但它不是理想的长期解决方案。
结论
编译器通常不会将连续的原子写入与相同的原子写入合并值以确保与 C 标准的一致性,避免潜在的性能问题,并坚持最少意外原则。然而,未来的 API 增强可能使编译器能够在未来安全地实现此优化。
以上是为什么编译器不合并相同值的冗余原子写入?的详细内容。更多信息请关注PHP中文网其他相关文章!