【问题标题】:memory-ordering of std::atomic<T> on certain CPUs某些 CPU 上 std::atomic<T> 的内存排序
【发布时间】:2019-12-19 16:39:26
【问题描述】:

使用 std::atomic 你可以做原子增量,比较交换等等。在成功和不成功的比较交换的情况下,您可以选择为内存排序提供一个值,或者您可以提供两个值,一个用于成功,一个用于不成功的比较和交换。有了这个,你可以 f.e.加快释放互斥体,在成功操作的情况下只需要释放行为。

但我想知道的是:哪种 CPU 架构通过其 ISA 支持这种区别?

【问题讨论】:

  • ARMv8 以及我认为可能所有使用 LL/sc 的架构。
  • 释放互斥锁通常使用释放语义来实现。这实际上是发布语义得名的地方。
  • LL/SC 是否要求对成功和不成功的操作进行可能的区分?
  • 您的问题是关于比较和交换的吗?您基本上是在问是否存在在两种内存顺序不同时生成的代码与使用两者中更强的一种内存顺序生成的代码不同的架构?
  • IIRC ll/sc 实际上并不执行任何排序本身 [至少在我熟悉的拱门上] - 它取决于包装器(在本例中为 std::atomic::try_xxx)在交换之前和之后添加它需要的任何栅栏 - 当然 那个 代码可以添加它喜欢的任何强度的任何栅栏,并且可以考虑交换是否失败。

标签: c++ multithreading std cpu-cache


【解决方案1】:

有了这个,你可以 f.e.加快释放只需要的互斥锁 操作成功时的释放行为。

互斥锁释放会如何失败?

释放未锁定的互斥锁是一个编程错误。

纯粹的释放操作几乎从来不会在有条件的情况下完成,而获取操作则是。引用计数是一个可能的例外。

但我想知道的是:哪种 CPU 架构支持这样的 通过它的 ISA 来区分?

在比较和设置之后无条件插入栅栏指令的所有那些。

再次引用计数的情况(这可能是互斥锁实现之外 RMW 操作最常见的用法):

  • 只有计数达到 0 的情况才显着
  • 计数只需要“可靠”就可以在有所有者的情况下保持非空
  • RC 实现了具有合法引用并看到计数达到 0 的互斥

本质上 RC 就像一个 RW 锁:

  • 根据定义,W 锁定与所有 R 解锁同步
  • 具有 W 锁优先级
  • 当有线程等待W锁时,让每一个R -unlock 尝试 W 锁定。

在这种情况下,您将 R-unlock(因此释放)并且如果 W-lock 处于挂起状态,并且没有其他 R-lock 处于活动状态 W-(re)lock。 (是的,我知道这个类比没有意义,因为您不会在执行 R-unlock 的同一线程中重新锁定 W-relock,但无论如何。)

在这种情况下,您需要为 W-lock 设置获取栅栏。

因此,通常任何弱排序的 CPU 都不会在加载时隐式获取。

这对于 RC 和 RW 锁等原语很重要,您可以尝试将最后一个 R 锁转换为 W 锁(尝试锁提升)。

【讨论】:

    猜你喜欢
    • 2015-05-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 2022-09-24
    • 1970-01-01
    相关资源
    最近更新 更多