【问题标题】:ARM atomics performanceARM 原子性能
【发布时间】:2014-09-08 08:25:26
【问题描述】:

我在 Intel CPU 和 ARM CPU(Mac/iOS,编译器:Clang)上运行相同的代码。通过分析应用程序,我注意到,在 iOS/ARM 上,原子操作是前 3 项,而在 Intel 上,它们甚至不在前 10 名。是真的吗,在 ARM 上原子操作是 那么多 慢? (相对当然)

【问题讨论】:

  • Herb Sutter 的“原子武器”演讲说 Arm7 和 PowerPC 是 C++ 拥有如此精细的内存排序选项的原因:在那些架构上,顺序一致性非常昂贵,你需要使用宽松的订购以获得合理的性能。
  • 哇,谢谢,这非常有用。
  • 虽然 Herb Sutter 的演讲非常有趣且富有启发性,但它可能并不能真正解决问题。您应该提供一些代码和反汇编以便更好地理解。
  • 比较苹果和橙子只会让你到目前为止。根据基准测试,ARM 系统会快得多,同样,英特尔系统也会快得多。两者都很容易演示。
  • 原子操作是前 3 项。我们需要查看代码。原子可以意味着很多事情。我猜您是在谈论来自 C++x11 的 Clang C++ 原子,例如 n2427Clang/BSD 是否针对 x86 进行了优化,C++ 标准是否针对 x86 进行了优化,或者 x86 是更好的无锁 CPU。我猜工具或您的代码有问题。我们不知道该工具的版本,甚至没有您的代码。

标签: c++ multithreading arm atomic intel


【解决方案1】:

需要注意的一点是,由于实施细节,您不一定看到整个故事。

在 ARM 的 load-linked/store-conditional 范例下,任何原子操作都至少 4 条指令 - load-exclusive、1、store-独占的,有条件的分支,必要时重试。其他所有核心都完全没有注意到这一点,继续做自己的事情。

然而,在 x86 上,指令可以直接在内存上操作,原子操作通常是通过将 LOCK 前缀粘贴到单个指令上来实现的。这意味着两件事:首先,您永远不能在您的原子“例程”中被打断,因为它是一条指令。其次,当总线被锁定时,没有其他内核可以访问内存,因此它有效地暂停了所有内容的执行,直到它完成2。总之,这些意味着采样分析器很少(如果有的话)捕捉到“正在进行”的原子操作,无论它实际需要多长时间。

[1] 好的,所以原子交换只有 3 条指令,但其他任何东西中间都有一条或多条指令。

[2] 现代核心的情况稍差一些,现代核心只会锁定自己的缓存,而不是一切,以避免影响访问不相关区域的其他核心,但硬件缓存 -连贯性仍然可以防止其他任何人干扰。

【讨论】:

  • 在 x86 上,但是指令比 arm 指令长得多(当使用 mem 操作数时),内容是未对齐传输等,是微编码等。架构不同,因此您永远不能期望每一行高级代码在架构和平台上都执行相同的操作,就这么简单。
  • 此外,如果在原子例程中花费的时间过多是由于多个线程中的大量 STREX 故障,那么调查争用的原因是非常值得的。数据布局在这里很重要 - 在同一个独占保留颗粒(通常 == 缓存行)中尝试同时对两个变量进行原子操作可能会严重影响性能。
  • 不幸的是,我认为内存锁定不会成为问题,因为我的应用程序在单线程上运行。原子是从互斥体中调用的,在我的情况下这不是必需的,但它们存在于库中,因为它是线程安全的。显然我可以简单地删除这些互斥体并重新编译库,但我很好奇是什么导致了性能瓶颈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2013-06-06
  • 2018-09-22
  • 2014-02-13
  • 2020-02-11
相关资源
最近更新 更多