是否可以哄 std::atomic<T> 输出 CMPXCHG16B

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

对于我对在 Windows x64 上使用原子互锁操作不感兴趣的类型,是否可以诱导 std::atomic 输出 CMPXCHG16B,或者我只需要接受它并手动执行原子操作?我可以让 GCC/Clang 在 Linux 上执行此操作,所以我怀疑这只是 Microsoft 标准库的问题。

struct Byte16
{
    int64_t a, b;
};

std::atomic<Byte16> atm;
Byte16 a = { 1, 2 };
atm.compare_exchange_strong(...); // This has a lock on Windows, not on Linux version of code
c++ windows visual-studio c++11 icc
2个回答
0
投票

到了2024年,MSVC仍然不可能实现无锁

std::atomic<Byte16>

lock cmpxchg16b
的广泛可用性已经得到认可,但由于 VS 2015 和 VS 2022(以及中间的所有内容)之间的 ABI 兼容性,维护人员不可能重新定义
std::atomic
结构,直到下一次 ABI 更改为止。

但是,由于后来添加了

std::atomic_ref
,所以一开始就可以使用
lock cmpxchg16b
。它仍然会根据 CPU 检查有条件地使用它。要绕过 CPU 检查,请将
_STD_ATOMIC_ALWAYS_USE_CMPXCHG16B
定义为
1
进行编译。

如果您需要的是

std::atomic_ref
而不是
atomic
,则可以将
atomic_ref
与单个对象中的基础值捆绑在一起,如下所示:

template<class T>
struct atomic_x : std::atomic_ref<T>
{
    template<class... A>
    atomic_x(A ... a) : std::atomic_ref<T>(Value), Value(a...) {}

    alignas(std::atomic_ref<T>::required_alignment) T Value;
};

演示:https://godbolt.org/z/jvqd3f71K


请注意,这样的 16 字节

std::atomic_ref
即使对于加载和存储也将
lock cmpxchg16b
。也许可以使它们简单地加载和存储 - 请参阅 SSE 指令:哪些 CPU 可以执行原子 16B 内存操作? - 但这还没有在 MSVC STL 中实现。


-2
投票

在 Windows 中使用 __m128

#include <emmintrin.h>
//...
  std::atomic<__m128> a, c;
  __m128 b;
  a.compare_exchange_strong(b,c);
///...
© www.soinside.com 2019 - 2024. All rights reserved.