【发布时间】: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