【问题标题】:Optimization Techniques for C++C++ 的优化技术
【发布时间】:2012-12-08 00:37:45
【问题描述】:

几天前在 Facebook 的演讲中 - slidesvideo,Andrei Alexandrescu 谈到了可能证明我们错了的常见直觉。对我来说,幻灯片 7 中出现了一个非常有趣的观点,他指出假设 “更少的指令 = 更快的代码” 是不正确的,更多的指令不一定意味着更慢的代码。

我的问题来了:他的演讲(大约 6 分 20 秒)的音频质量不太好,我不太理解解释,但据我所知,他正在比较已退休的指令与最优性一种性能级别的算法。

但是,据我了解,这是无法做到的,因为这是两个独立的结构级别。指令(尤其是实际停用的指令)是一项非常重要的衡量标准,基本上,它可以让您了解实现目标的性能。如果我们忽略一条指令的延迟,我们可以概括出更少的退役指令 = 更快的代码。当然,在某些情况下,即使在循环内执行复杂计算的算法也会产生更好的性能,因为它会更早地中断循环(想想图遍历)。但是,在复杂性级别上与算法进行比较,而不是说这个循环有更多指令并且比另一个更好,难道不是更有用吗?从我的角度来看,更好的算法最终会减少退休指令。

有人可以帮助我了解他的示例将走向何方,以及如何存在(显着)更多退休指令导致更好性能的情况?

【问题讨论】:

  • 例如,Branch prediction。在链接的示例中 - 添加指令(在进行迭代之前对数组进行排序)实际上允许更快的代码,因为分支预测对于排序的数组来说要好得多。
  • 缓存回收也会降低性能。例如:stackoverflow.com/questions/7905760/…
  • 另一个不错的 (imo) 示例是除以常数。最快的方法是实际分割,但最快的方法有点复杂:gmplib.org/~tege/divcnst-pldi94.pdf
  • @harold:幸运的是,对于这样的优化,编译器知道它的管道优化是手背上的。

标签: c++ algorithm optimization


【解决方案1】:

质量确实很差,但我认为他导致了这样一个事实,即 CPU 对计算有好处,但在内存寻道方面表现不佳(RAM 比 CPU 慢得多)和分支(因为 CPU 作为管道工作) ,而分支可能会导致管道中断)。

以下是一些指令越多越快的情况:

  1. Branch prediction - 即使我们需要执行更多指令,但这会导致更好的分支预测,CPU 的流水线将有更多时间充满,并且会“丢弃”更少的操作,这最终会带来更好的性能。例如,This thread 展示了如何做同样的事情,但首先排序 - 提高了性能。

  2. CPU Cache - 如果你的代码更加缓存优化,并遵循principle of locality - 它更有可能比没有的代码更快,即使代码没有做一半指令的数量。 This thread 给出了一个小型缓存优化的示例 - 如果没有缓存优化,相同数量的指令可能会导致代码慢得多。

  3. 执行哪些指令也很重要。有时 - 某些指令的执行速度可能比其他指令慢,例如 - 除法 可能比整数加法慢。

注意:以上所有内容都取决于机器,并且它们如何/是否实际改变性能可能因一种架构而异。

【讨论】:

  • 关于分支预测:我不确定这是否仍然有效。是的,有时分支预测会产生严重影响(取决于拱门,我在这里使用 X86),但如果我从 Xeon 7560 上的线程运行示例,未排序的版本会快几个百分点。所以回到第一方?
  • 关于你的第2点:你提到的例子并没有改变退役指令的数量,而是改变数据结构的顺序以利用缓存结构。还有其他例子吗?
  • @grundprinzip:如前所述,分支预测在不断变化——从一种架构到另一种架构不同。为了找到适合您硬件的杀手锏,您可能需要特定分支预测器方面的专家。恐怕我不是他们中的一员。
  • @grundprinzip:关于#2:您可以在缓存优化循环中的每次迭代中添加一个虚拟指令,您将在优化版本中获得更多指令和可能更快的代码(同样,取决于架构,当然,编译器优化依赖)。此外,磁盘优化也有不同的变化。具有大量磁盘查找的代码 - 但它们是顺序的可能比具有较少随机磁盘查找的代码更快,因为磁盘不是随机访问,并且顺序读取比随机访问读取快 很多 .
【解决方案2】:

指令数量本身并不是一个很好的衡量标准。

更少的废弃指令(因为没有更多的事情要做)= 更快的代码。

更少的废弃指令(因为它们必须等待依赖)= 更慢的代码。

有时,代码中的指令越多也意味着停用的指令越多,因为它们可能会用完在情况 2 中会被浪费的执行槽。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    相关资源
    最近更新 更多