【问题标题】:Why this huge difference in execution time happens for this tiny change into c code?为什么对 c 代码的这种微小更改会导致执行时间的巨大差异?
【发布时间】:2013-02-10 16:29:15
【问题描述】:

下面的unix代码需要time命令报告的~9s。

int main()
{
    double u = 0;
    double v = 0;
    double w = 0;
    int i;
    for (i = 0;i < 1000000000;++i) {
        v *= w;
        u += v;
    }
    printf("%lf\n",u);
}

我不明白为什么当我更改 v *= w;withv *= u; 时执行时间几乎翻了一番

【问题讨论】:

  • w 始终为零。编译器可能足够聪明,在第一种情况下根本不运行该循环,因为v 也将始终为零,因此u 也是如此。 (可能更难弄清楚 u 和 v 之间的相互依赖关系。)
  • 你看生成的代码了吗?

标签: c performance


【解决方案1】:

当您将v *= w 更改为v *= u 时,这两个语句之间存在相互依赖关系。因此,第一条语句必须在执行 u += v 之前完成,这可能是提高性能的原因,因为编译器无法并行执行。

【讨论】:

    【解决方案2】:

    可能是因为编译器看到 w 从未被修改过,因此可以编译为常量,而变量 u 已修改,因此必须拥有自己的内存。

    【讨论】:

      【解决方案3】:

      编译器优化 v*= w;到 v = 0;并且可能 u += v 到 u = 0;所以这些操作永远不会发生。

      这是我做的测试。每个版本做 10 次并取平均值。

      for (i = 0;i < 1000000000;++i) {
          v *= w;
          u += v;
      }
      

      4.0373 秒



      for (i = 0;i < 1000000000;++i) {
          v *= u;
          u += v;
      }
      

      7.3733 秒



      for (i = 0;i < 1000000000;++i) {
          v *= 0;
          u += 0;
      }
      

      4.0149 秒

      【讨论】:

      • 为什么它对 v *= u; 不一样,因为它也是 0
      • 可能无法优化 v *= u 和 u += v out,因为它们相互依赖。
      • @curious 虽然它需要额外的推理步骤(它首先必须找出 v 是恒定为零,然后 u 永远不会改变并保持为零 - 在另一种情况下,它只需看到w 恒定为零),这可能会有所作为。
      猜你喜欢
      • 2011-08-10
      • 2013-10-15
      • 1970-01-01
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      • 2016-03-11
      相关资源
      最近更新 更多