gpt4 book ai didi

rust - 有没有办法绕过原子操作的成本?

转载 作者:行者123 更新时间:2023-12-03 11:36:12 26 4
gpt4 key购买 nike

我有一个计数器,目前是一个原子 u32,在我的代码的热门部分使用,它通常只增加 1。偶尔,它会从代码的一个非常不同的部分读取,但如果确实发生了,该值必须准确(至少在同一线程上)。但是,我怀疑原子性可能会对性能产生不良影响。我必须解决的一个想法是让主计数器是非原子的,但以原子方式写入第二个计数器。

原子写入比读取便宜吗?比如它不需要清除(那么多)缓存吗?

最佳答案

长话短说

如果您只有一个写入线程和一个读取线程,您所需要的只是使用带有 relaxed memory ordering or acquire/release 的原子。 .

详情

在 x86 上,它将被转换为普通的 add/mov 指令,因此不会对性能产生影响。

这是一个正常的计数器增量:

example::normal_inc:
add dword ptr [rip + example::normal_u32], 1
ret

这是一个松散排序的原子计数器增量:

example::atomic_inc:
add dword ptr [rip + example::atomic_u32], 1
ret

在 x86 上没有区别,因此没有性能影响。但是代码正确吗?

Relaxed loads/stores 不保证跨线程的顺序,但保证同一线程上的顺序和原子性。什么意思?

对于一个作者和一个读者的情况,这意味着如果线程 W 更新计数器,线程 R 最终将看到更改,并且该值将有效,因为保证了原子性。例如,如果计数器为 0,线程 W 将其增加到 1 和 2,则保证线程 R 最终会看到 2,而它永远不会看到 42 或一些其他的随机数。

不能保证的是这个数字将与其他原子或非原子变量对齐。假设,如果线程 W 将元素添加到列表,然后增加计数器,线程 R 可能会以相反的顺序看到这些事件,即首先增加计数器,然后一个新元素出现在列表中。

从线程 W 的角度来看,仍然可以保证的是事件的顺序。使用列表的相同示例,可以保证对于线程 W,列表元素将在计数器增加之前出现,因为所有这些更改都发生在同一线程内,而不是跨不同的线程。

由于 x86 具有非常强大的内存排序,即使是 aquire/release ordering on the atomics 仍然使用正常的 add/mov 操作。参见 memory ordering on Wikipedia .

获取/释放语义不仅保证了原子性,还保证了顺序。以列表为例,线程W 添加一个列表元素,然后释放 一个计数器。当线程 R acquires 计数器时,可以保证列表元素在那里。在 x86 上,此保证不会产生额外费用。

另请参阅上面关于 Godbolt 的示例:https://godbolt.org/z/4EsY4j

关于rust - 有没有办法绕过原子操作的成本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66201972/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com