Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不';t标准库以无锁方式为8字节以下的结构实现std::atomic?_C++_C++17_Atomic_Lock Free_Stdatomic - Fatal编程技术网

C++ 为什么不';t标准库以无锁方式为8字节以下的结构实现std::atomic?

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::atomic的8字节标量。为什么标准库不为小于8字节的结构提供类似的专门化

这种std::原子专门化的简单实现可以将结构序列化/反序列化(使用
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)
。噢,缓存线拆分实际上很有意义,谢谢!