【问题标题】:Vectorization: when is worth manually unrolling loops?矢量化:什么时候值得手动展开循环?
【发布时间】:2020-05-06 09:51:04
【问题描述】:

我想大致了解什么时候我可以期望编译器对循环进行矢量化,以及什么时候我应该展开循环来帮助它决定使用矢量化。

我了解细节非常重要(什么编译器、什么编译选项、什么架构、如何在循环中编写代码等),但我想知道是否有一些现代编译器的通用指南。

我将更具体地举一个简单循环的例子(代码不应该计算任何有用的东西):

    double *A,*B; // two arrays
    int delay = something
    [...]


    double numer = 0, denomB = 0, denomA = 0;
    for (int idxA = 0; idxA < Asize; idxA++)
    {
        int idxB = idxA + (Bsize-Asize)/2 + delay;
        numer  += A[idxA] * B[idxB];
        denomA += A[idxA] * A[idxA];
        denomB += B[idxB] * B[idxB];
    }

我可以期望编译器对循环进行矢量化,或者像下面这样重写代码是否有用?

    for ( int idxA = 0; idxA < Asize; idxA+=4 )
    {
        int idxB = idxA + (Bsize-Asize)/2 + delay;
        numer  += A[idxA] * B[idxB];
        denomA += A[idxA] * A[idxA];
        denomB += B[idxB] * B[idxB];

        numer  += A[idxA+1] * B[idxB+1];
        denomA += A[idxA+1] * A[idxA+1];
        denomB += B[idxB+1] * B[idxB+1];

        numer  += A[idxA+2] * B[idxB+2];
        denomA += A[idxA+2] * A[idxA+2];
        denomB += B[idxB+2] * B[idxB+2];

        numer  += A[idxA+3] * B[idxB+3];
        denomA += A[idxA+3] * A[idxA+3];
        denomB += B[idxB+3] * B[idxB+3];
    }

【问题讨论】:

  • 测量。识别可能的瓶颈。 测量。更改代码/编译选项。 测量。除非您衡量不需要进行任何更改(并且大多数情况下,在衡量之后您意识到不需要进行任何更改)。
  • @luca 是的,任何先验预测都必然会失败,因为编译器的决策机制过于复杂。只需检查/测量即可。它非常防故障
  • 现代编译器将对给定架构使用任何可用的“技巧”来优化代码。我会说你永远不应该展开(除非你有衡量影响的方法),因为你可能会迫使编译器选择一些效率较低的优化方法(例如,simd 与否,...)
  • 不是“measure”?正确,在我的理解中没有指导方针。
  • 如果没有非关联数学优化,您的代码的任何一个版本都不会从矢量化中显着受益

标签: c++ c vectorization loop-unrolling


【解决方案1】:

简短的回答,正如其他人所说:如果您不指定编译器或目标架构,则没有一般准则。

作为评论,这些天让编译器优化代码通常会更好,因为它“知道”更好的架构可能性。在某些情况下,展开循环不会更快。

如果有人看到并需要它,GCC 中有 -funroll-loops 标志。

【讨论】:

    【解决方案2】:

    我从其他答案和 cmets 中得知,不建议手动展开循环:编译器知道得更好。

    但是,compiler might fail to vectorize 您的代码取决于编译中使用的优化选项。为什么?因为浮点加法和乘法是neither associativenor commutative。这个prevents the compiler from reordering operands,反过来会在您希望代码被矢量化的某些场景中阻止矢量化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-03
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 2014-01-10
      • 2011-06-28
      • 2020-03-18
      相关资源
      最近更新 更多