C ++ 11:16字节的atomic <>变量是否自动对齐到16字节的边界以允许CMPXCHG16B指令?

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

16字节atomic<>变量是否在16字节边界上自动对齐,从而允许编译器/运行时库有效地使用x86 CMPXCHG16B指令吗?还是我们应该总是为所有此类变量手动指定alignas(16)

c++ x86-64 memory-alignment stdatomic compare-and-swap
1个回答
3
投票

如果库完全使用std::atomic<>而不是16字节对象的互斥量,则alignas的任何体面实现都将使用lock cmpxchg16b本身来提高lock cmpxchg16b的效率。

[并非所有实现都可以,例如,我认为MSVC的标准库使用标准互斥锁回退使16字节对象完全无锁。

您不需要alignas(16)上的atomic<T>

[如果您要使用T的普通atomic_ref对象,则只需要对原子进行手动对齐。 atomic_ref<>没有对齐现有T对象的机制。设计的当前版本公开了您应该使用的required_alignment成员。这样做是为了您的正确性。 (否则,您得到的UB可能意味着撕裂,或者对于拆分lock RMW而言,只是[[extremely降低了系统范围的性能。)]

// for atomic_ref<T> alignas(std::atomic_ref<T>::required_alignment) T sometimes_atomic_var; // often equivalent, and doesn't require checking that atomic_ref<T> is supported alignas(std::atomic<T>) T sometimes_atomic_var; // use the same alignment as atomic<T>

[请注意,在缓存行边界上未对齐的lock cmpxchg16b拆分仍然是原子的,但是非常慢(与任何lock ed指令相同:原子RMW的原子性保证不取决于对齐)。更像是实际的总线锁定,而不仅仅是本地到此内核cache lock delaying MESI responses

窄原子绝对需要自然对齐以确保正确性,因为纯负载和纯存储可以编译为asm pure load or store where HW guarantees require some alignment

但是16字节对象只能通过lock cmpxchg16b保证是原子的,因此.load().store()必须通过lock cmpxchg16b实现。 (使用CAS(0,0)加载以获取旧值,或者将0替换为自身或不执行任何操作,然后使用CAS重试循环进行存储。这很烂,但比互斥锁要好一些。它没有read-您希望从无锁load获得的可扩展性,这是GCC7和更高版本不再将atomic<16-byte-object>宣传为无锁的原因之一,尽管它仍会在调用的libatomic函数中使用lock cmpxchg16b而不是内联lock cmpxchg16b

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