【问题标题】:(n - Multiplication) vs (n/2 - multiplication + 2 additions) which is better?(n - 乘法) 与 (n/2 - 乘法 + 2 加法) 哪个更好?
【发布时间】:2011-10-27 16:15:03
【问题描述】:

我有一个 C 程序,它有 n 次乘法(单次乘法和 n 次迭代),我发现另一个逻辑有 n/2 次迭代(1 次乘法 + 2 次加法)。我知道两者都是 O(n) 的复杂性。但就 CPU 周期而言。哪个更快?

【问题讨论】:

  • 这在很大程度上取决于您使用的物理硬件和编译器。如果它真的很重要,请在您的目标环境中对其进行基准测试。
  • 这也很大程度上取决于所使用的技术。这个问题太笼统,无法给出好的答案。
  • 测量并找出答案(但请记住,任何结果都将仅适用于您当前的配置)。
  • 谢谢。我尝试了非常大的值。第一个比第二个花费了近 1.6 倍。
  • 如果 n=0,首先更好

标签: c performance optimization implementation cpu-cycles


【解决方案1】:

在您的计算机上进行测试。或者,查看您的处理器的规格并猜测。

旧的逻辑不再适用:在现代处理器上,整数乘法可能非常便宜,在一些新的英特尔处理器上,它是 3 个时钟周期。在这些相同的处理器上,加法是 1 个周期。然而,在现代流水线处理器中,数据依赖造成的停顿可能会导致添加时间更长。

我的猜测是,如果您进行折叠类型的操作,N 次加法 + N/2 次乘法比 N 次乘法要慢,而对于映射类型的操作,我会猜测相反。但这只是猜测。

测试你是否想要真相。

但是:这种简单的大多数算法都受内存限制,并且两者的速度相同。

【讨论】:

    【解决方案2】:

    首先遵循 Dietrich Epp 的第一个建议 - 测量是(至少对于复杂的优化问题)唯一确定的方法。

    现在,如果您想弄清楚为什么一个比另一个快,我们可以试试。有两种不同的重要性能指标:延迟和互惠吞吐量。两者的简短总结:

    延迟:这是指令在一个 依赖链。数字是最小值。缓存未命中, 未对准,异常可能会增加时钟计数 相当。在启用超线程的情况下,使用相同的 另一个线程中的执行单元会导致性能下降。 非正规数、NAN 和无穷大不会增加延迟。这 使用的时间单位是核心时钟周期,而不是参考时钟周期 由时间戳计数器给出。

    倒数吞吐量:平均每个内核时钟周期数 一系列独立的同类指令的指令 在同一个线程中。

    对于桑迪桥的记录。 add r, r/i 的吞吐量(进一步通知 r=register,i=immediate,m=memory)为 0.33,而延迟为 1。

    imul r, r 的延迟为 3,rec。吞吐量为 1。

    因此,正如您所看到的,它完全取决于您的特定算法 - 如果您可以用两个独立添加替换一个 imul,那么您算法的这个特定部分可以获得 50% 的理论加速(在最好的情况下显然加速约 350%)。但另一方面,如果您的添加添加了一个有问题的依赖项,则一个 imul 可能与一个添加一样快。

    另外请注意,我们忽略了所有额外的复杂性,例如内存和缓存行为(通常会对执行时间产生更大、更大影响的事物)或诸如 µop 融合之类的复杂事物。一般来说,唯一应该关心这些东西的人是编译器编写者——仅仅衡量他们努力的结果要简单得多;)

    无论如何,如果您想详细列出这些内容,请参阅 this here(上面对延迟/记录吞吐量的描述也来自该特定文档)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-13
      • 2013-07-20
      • 2020-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多