C++ 为什么不';t标准库以无锁方式为8字节以下的结构实现std::atomic?
假设该体系结构能够以无锁方式支持std::atomic的8字节标量。为什么标准库不为小于8字节的结构提供类似的专门化 这种std::原子专门化的简单实现可以将结构序列化/反序列化(使用C++ 为什么不';t标准库以无锁方式为8字节以下的结构实现std::atomic?,c++,c++17,atomic,lock-free,stdatomic,C++,C++17,Atomic,Lock Free,Stdatomic,假设该体系结构能够以无锁方式支持std::atomic的8字节标量。为什么标准库不为小于8字节的结构提供类似的专门化 这种std::原子专门化的简单实现可以将结构序列化/反序列化(使用std::memcpy)为等效的std::uintx_t,其中x是以位为单位的结构宽度(四舍五入到大于或等于结构宽度的最接近的2次方)。这将是一个很好的定义,因为std::atomic需要这些结构具有很小的可复制性 例如,这里的Something只有3个字节,但是实现调用\uuuuu原子加载和\uuu原子交换,这两
std::memcpy
)为等效的std::uintx_t
,其中x
是以位为单位的结构宽度(四舍五入到大于或等于结构宽度的最接近的2次方)。这将是一个很好的定义,因为std::atomic需要这些结构具有很小的可复制性
例如,这里的Something
只有3个字节,但是实现调用\uuuuu原子加载
和\uuu原子交换
,这两个调用都使用锁表 Linux的atomic
不幸的是(?)没有达到2次方大小<代码>标准::原子arr[10]具有sizeof(arr)=30。()
使用
struct Something{alignas(4)char a;char b,c;}代码>
(不是alignas(4)char a,b,c;
,因为这将使每个char填充为4个字节,以便它们可以对齐。)
大小为非2次方的对象可能跨越缓存线边界,因此不可能总是使用更宽的4字节负载
另外,纯存储总是必须使用CAS(例如,lock cmpxchg
)来避免在对象外部发明对字节的写入:显然,您不能使用两个单独的mov
存储(2字节+1字节),因为这不是原子的,除非您在带有重试循环的TSX事务中这样做
x86加载/存储仅保证用于不跨越8字节边界的内存访问。(在一些供应商/UARCHE上,缓存线边界。或者对于可能无法缓存的加载/存储,基本上需要自然对齐)
你的struct Something{chara,b,c;}代码>没有对齐要求,所以没有C++规则阻止<代码>某物< /Cord>对象跨越2条缓存行。这将使普通的mov加载/存储绝对非原子化
gcc和clang选择使用与T
相同的布局/对象表示实现atomic
(无论是否无锁)。因此,atomic
是一个3字节的对象。因此,原子的数组
必然有一些对象跨越缓存线边界,并且不能在对象外部填充,因为在C中数组不是这样工作的。sizeof()
=3告诉您数组布局这使得无锁的原子的成为不可能。
(除非您使用lock cmpxchg
加载/存储,即使在缓存线拆分时也是原子的,这将在发生这种情况时产生巨大的性能损失。最好让开发人员修复他们的结构。)
atomic
类可以比T
具有更高的对齐要求,例如atomic
具有alignof(atomic_int64_T)==8,这与许多32位平台(包括i386系统V ABI)上的alignof(int64_T)==4不同
如果gcc/clang没有做出保持布局不变的选择,他们可以让atomic
将小对象填充到下一个2次方,并添加对齐,这样它们就可以无锁了。这将是一个有效的实现选择。我想不出有什么坏处
有趣的事实是,gcc的C11\u-Atomic
支持是:\u-Atomic-int64\t
可以在结构内部错位,导致撕裂。他们仍然没有更新原子
类型的ABI以使其自然对齐
但是g++的C++11 std::atomic在头文件中使用了一个模板类,该类在不久前修复了这个bug();确保atomic
具有自然对齐(高达2倍大小),即使T
具有对齐<大小。因此,它们不可能跨越比它们更宽的任何边界。gcc正确地将结构设置为4字节(而不是3字节),请参阅。“叮当声不起作用。@PaulSanders有趣的是,我想知道为什么3字节不起作用。.没有x86指令加载/存储3字节,更不用说原子了。@rustyx啊,对不起,但是你总是可以占用超过2的下一次幂的大小,对吗?”?节§[atomics.types.generic]p3允许这样做-原子专门化的表示不需要与其相应的参数类型具有相同的大小。不过,我想这可能存在移植性问题?@好奇:当我说“强制对齐”时,我的意思是alignas(4)
。噢,缓存线拆分实际上很有意义,谢谢!