【问题标题】:Atomic compare, Multi-Processor, C/C++ (Linux)原子比较、多处理器、C/C++ (Linux)
【发布时间】:2012-06-30 01:22:14
【问题描述】:

我在多处理器系统上的共享内存 x 中有一个变量。

void MyFunction(volatile int* x) {
  if (*x != 0) {
     // do something
  }
}

其他进程(可能在不同的处理器上)将使用 gcc 内置原子操作(例如 __sync_bool_compare_and_swap 等)写入 x。

我想我遇到了一些缓存并发问题,有时需要一些时间才能最终用新值更新 x。

我想要的是一种 atomic_compare (没有交换),如果这样的东西存在的话?或“原子读取”。最快的方法是什么? (避免互斥体、锁等)

谢谢

编辑:

我刚刚意识到一个有点骇人听闻的解决方法是使用 __sync_val_compare_and_swap 和我知道它永远不可能的值。那能解决问题吗? (有没有更干净的方法?)

【问题讨论】:

标签: c++ c linux shared-memory atomic


【解决方案1】:

新的 C 标准 C11 有 _Atomic 数据类型和操作来处理这个问题。该标准尚未实现,但 gcc 和 clang 已接近它,它们已经实现了该功能。事实上,函数__sync_bool_compare_and_swap 就是其中的一部分。我已将其封装到 set of headers in P99 中,让您可以使用 C11 接口进行编程。

执行您想要的操作的 C11 函数将是 atomic_load,或者如果您对一致性有特殊要求 atomic_load_explicit。毫不奇怪,正如您所怀疑的,P99 映射到 __sync_val_compare_and_swap(&x, 0, 0)。然后,如果您查看在大多数架构上生成的汇编程序,这将在xint 的情况下转换为简单的加载操作。但这不是语言所保证的,这取决于编译器知道这些事情并合成保证是原子的指令。

【讨论】:

    【解决方案2】:

    最快的方法是什么? (避免互斥体、锁等)

    我很确定您不想避免使用互斥锁。 linux 的 futexes 允许您利用比较和交换的优点(大部分时间),同时保持经典的互斥体语义(发生的“交换”是互斥体之一,而不是受其保护的代码/数据)。我强烈建议您尝试它们并分析解决方案(perfoprofile、VTune 等),看看您的瓶颈是否真的与锁定机制本身有关,而不是缓存利用率、内存吞吐量、CPU 周期、 IO访问、远程节点内存访问等

    我想我遇到了一些缓存并发问题,有时需要一些时间才能最终用新值更新 x。

    好吧,假设您确实需要在处理器之间进行交互,并且您已经测量了从 futex 获得的延迟影响,并且您确定它不能满足您的应用程序的需求。所以,如果是这种情况,一个相对健全的方法可能是这样的:创建一个 32 位整数数组,填充的距离大于或等于目标缓存行的大小。使用当前执行的 CPU 和缓存行大小作为此列表中实际值的索引(因此,如果您的缓存行是 64 字节,您可以将 CPU# 缩放 16 以跳过填充)。您应该只从适当的 CPU 写入这些值,并且可以从任何其他 CPU 轮询它(可能应该在忙等待的主体中调用 CPU 的“暂停”指令之一)。这将是一种检查不同执行线程是否已达到/满足给定条件的有效机制。

    我应该补充一点,这几乎肯定会奏效(有效地用 CPU 效率换取可能更低的延迟),但除了一组非常特殊的硬件之外,它仍然是一个非常脆弱的解决方案。

    【讨论】:

    • 没有互斥锁是多余的,即使在 linux 上也是如此。现代 C 对此有一个答案,它比你想象的更接近 Switch 的估计值。
    【解决方案3】:

    我想要的是一种 atomic_compare(没有交换),如果这样 东西存在吗?或“原子读取”。

    比较已经是原子的。这是一个单读。

    如果处理器之间的延迟已经很糟糕,那么您的代码似乎会从解耦中受益。 IE。稍微分离出依赖关系,这样你就不会依赖内部循环中的这种通信。

    【讨论】:

    • 不,不能保证 C 级别的一次加载操作仅转换为一次低级别读取。在大多数架构上,它将用于int,但不能保证。
    猜你喜欢
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 2022-09-23
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    相关资源
    最近更新 更多