矢量化:什么时候值得手动展开循环?

luc*_*uca 5 c c++ vectorization loop-unrolling

我想大致了解何时可以期望编译器对循环进行矢量化,以及何时值得我展开循环以帮助它决定使用矢量化。

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

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

    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];
    }
Run Code Online (Sandbox Code Playgroud)

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

    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];
    }
Run Code Online (Sandbox Code Playgroud)

Wel*_*riv 2

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

顺便说一句,现在通常最好让编译器优化代码,因为它更好地“了解”架构的可能性。在某些情况下,展开循环不会更快。

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