【问题标题】:Execution Time of the function函数的执行时间
【发布时间】:2014-03-01 09:58:02
【问题描述】:

我试图减少这个函数的执行时间,我把执行时间缩短到了

系统:0.001s

有什么办法可以进一步减少这个函数的执行时间?

 int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n)
   {
      int i;
      uint32_t ri, c=0;
      for (i = 0; i < n; i ++)
          {
             ri = a[i] + b[i] + c;
             c = ((ri < a[i]) || ((ri == a[i]) && c));
             r[i] = ri;
          }
      return ((int) c);
   }

【问题讨论】:

标签: c performance optimization profiling


【解决方案1】:

我猜,您大部分时间都在条件表达式中丢失:如果大多数现代 CPU 无法正确预测它们,大多数现代 CPU 讨厌分支。因此,大多数循环引入的分支都很好,因为它们在整个循环中只会被错误预测一次。然而,在进位条件下进行分支可能会导致 50% 的分支被错误预测,并且每个错误预测值 10 到 20 个周期。更糟糕的是,&amp;&amp;|| 运算符是序列点,这对优化器来说是一个障碍。

所以,我会尝试消除这些条件:

int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n) {
    int i;
    uint64_t ri, c=0;
    for (i = 0; i < n; i ++) {
        ri = (uint64_t)a[i] + (uint64_t)b[i] + c;
        c = ri >> 32;
        r[i] = (uint32_t)ri;
    }
    return ((int) c);
}

在这里,我使用了 64 位算术,因为现代 CPU 执行 64 位算术与 32 位算术一样快。但是,如果 64 位算术在您的硬件上速度较慢,您可以回退到 32 位算术:

int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n) {
    int i;
    uint32_t ri, c=0;
    for (i = 0; i < n; i ++) {
        uint32_t curA = a[i], curB = b[i];
        uint32_t lowA = curA & 0xffffu, highA = curA >> 16;
        uint32_t lowB = curB & 0xffffu, highB = curB >> 16;
        uint32_t lowR = lowA + lowB + c;
        uint32_t highR = highA + highB + (lowR >> 16);
        c = highR >> 16;
        r[i] = (highR << 16) + lowR;
    }
    return ((int) c);
}

尽管这看起来像一个怪物,但它只有 12 个简单的操作,应该在所有硬件上以一个周期的延迟执行,即。 e.整个循环体的计算应该少于 12 个周期,因此,瓶颈应该是内存总线(这是你无法避免的)。

【讨论】:

    【解决方案2】:

    您可以摆脱下标符号并改用指针算法,据说这样更快,但是我不知道实际节省了多少 CPU 时间。

     int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n)
       {
          int i;
          uint32_t ri, c=0;
          for (i = 0; i < n; i ++)
              {
                 ri = *(a + i) + *(b + i) + c;
                 c = ((ri < *(a + i)) || ((ri == *(a +i)) && c));
                 *(r + i) = ri;
              }
          return ((int) c);
       }
    

    原因见:Accessing array values via pointer arithmetic vs. subscripting in C

    【讨论】:

    • 对于现代优化编译器,比如gcc,有两个版本的function()是相同的,它会为它们生成相同的汇编代码。
    • a[b]定义 与 C 中的 *(a + b) 相同。这就是为什么 a[b] 等同于 b[a] - 下标运算符只是语法糖用于指针算术。你的方法不应该对任何理智的编译器产生任何加速。
    【解决方案3】:

    c = (ri

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-19
      • 2013-03-27
      • 1970-01-01
      • 2021-07-15
      • 2020-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多