【问题标题】:Is there a __yield() intrinsic on Arm?Arm 上是否有 __yield() 内在函数?
【发布时间】:2021-11-22 17:17:26
【问题描述】:

我正在尝试为 arm (v7a) 编译一些代码,它有一个

#if defined(__arm__)
    __yield();
#endif

添加到this pull-request

其他分支有 YieldProcessor() 用于 MSC,_mm_pause()__builtin_ia32_pause() 用于 x86 和 x86-64。

编译器找不到符号__yieldarm-v7a-linux-gnueabihf-gcc 7.3.1 带有-mcpu=cortex-a9 -mtune=cortex-a9 -march=armv7-a 选项。此类符号是否在其他一些 ARM 平台、后来的 Gcc 或 Clang 上定义?

在编译器附带的头文件中,我只能找到__gnu_parallel::__yieldsched_yield() 的内联包装器,我想这相当于代码在调用__yield() 的100 次迭代后调用的std::this_thread::yield()。所以我认为不是这样。但我也没有在 gcc 文档中看到 __yield

【问题讨论】:

  • 这太可怕了。如果你写的是真的,那么相同的代码在不同的平台上会非常做不同的事情,具有非常不同的性能特征。此外,与往常一样,让出处理器肯定是程序设计非常糟糕的标志。
  • @EOF 它正在添加它自己的自旋锁。我不会这样做,但我真的说不出它有多少是有用的优化,有多少是令人毛骨悚然的恐怖。
  • @EOF: AFAICT、YieldProcessor()_mm_pause()__builtin_ia32_pause() 都发出 x86 pause 指令,所以它们似乎都是等价的。请注意,这不会为操作系统产生时间片。等待自旋锁正是它的意思。放弃时间片的等待时间太短,但是如果您在紧密循环中读取锁,则对高速缓存行的锤击会降低性能(并浪费功率)。在该循环中放置 pause 指令可以改善情况。

标签: linux gcc arm


【解决方案1】:

__yield 内在函数被指定为ARM C Language Extensions 的一部分(参见 8.4“提示”)。它发出yield instruction,大致相当于x86 pause。它恰好适用于等待自旋锁等情况;它可以防止 CPU 过度敲击缓存行(这会损害性能),可能会节省一些功率,并且在超线程 CPU 的情况下,可以为其他逻辑处理器提供更多的计算单元。

(请注意,它纯粹是一个 CPU 函数,而不是操作系统或库调用;它不会像类似名称的 pause()sched_yield()std::this_thread::yield() 调用那样为操作系统产生 CPU 时间片做。)

虽然 GCC 支持一些 ACLE 内在函数,但它似乎缺少这个。您应该可以用asm volatile("yield"); 代替。 yield 指令没有架构效果(它的执行方式类似于 nop),因此不需要寄存器或内存破坏器。

【讨论】:

  • 在什么情况下 yield 可以在没有内存破坏或获取障碍的情况下被合理使用?
  • @supercat:嗯,yield 本身不会修改内存,如果在读取内存的东西周围使用它可以异步修改,我认为这将是实际的内存操作会有障碍(例如,自旋锁循环中的获取负载或 RMW)。所以我同意可能会希望在附近的某个地方设置一个屏障,但它不需要在yield 本身上,无论它走到哪里,不管你有没有yield,它都必须在那里.
  • @supercat:或者您是否担心在自旋锁循环中,机器可能会使用测试锁的负载重新排序产量,并使循环旋转太快或太慢?我认为这是一个实施质量问题。机器不应该那样做。当然,架构参考中没有任何迹象表明您可能需要性能障碍。而且它对正确性没有影响,它不应该关心产量是否存在。
猜你喜欢
  • 2015-12-14
  • 1970-01-01
  • 2016-09-04
  • 1970-01-01
  • 2015-05-13
  • 2012-11-23
  • 2014-05-06
  • 2017-03-30
  • 2016-12-19
相关资源
最近更新 更多