如何使用循环展开和重新关联?

时间:2018-06-08 03:32:23

标签: c loops optimization loop-unrolling

我正在尝试使用循环展开来优化我的代码。

这是原始代码

int a[N]; //arbitrary array
int vara; //arbitrary variable
int varb; //arbitrary variable
for (int i=0;i<N;i++)
     a[i]=(a[i+1]* vara) + varb;

所以我试着这样做

for (int i=0;i<N-1;i+=2)
{
    int a=a[i+1]*vara;
    int b=a[i+2]*vara;
    int c=a+varb;
    int d=b+varb;
    a[i]=c;
    a[i+1]=d;
}

我认为这样可行,因为我允许编译器一次进行多次迭代的加法和乘法,我认为这会增加指令级并行性。然而这样做根本不会加速我的代码,我做错了什么?

我们非常感谢优化此代码的任何其他建议。

1 个答案:

答案 0 :(得分:1)

您的编译器很可能已经在高优化级别展开,可能您需要-funroll-loops或类似的东西。但即使是文档也警告说,这不是一个获得速度的神奇选择,因为它会花费指令缓存和程序空间。

循环展开基本上就是你所做的:只需要更少的循环迭代并完成多个较小迭代的工作。它的速度是否更快依赖于循环体和运行代码的实际机器。

展开也真的有意义,如果跳转是昂贵的并且指令级并行增益,这给出了反依赖性和现代处理器中调整的分支预测器是不可能的。

也就是说,你需要至少运行一些带有统计分析的微基准测试。

如果我不得不冒险提高你的速度:删除对数组中下一个元素的依赖。然后它变成基本向量乘法累加,这对于向量化很简单。