失去对循环变量的依赖 - 循环优化

时间:2013-01-12 13:55:01

标签: c optimization

我有以下嵌套循环计算:

int aY=a*Y,aX=a*X;
for(int i=0; i<aY; i+=a)
{
    for(int j=0; j<aX; j+=a)
    {
        xInd=i-j+offX;
        yInd=i+j+offY;
        if ((xInd>=0) && (xInd<X) &&
            (yInd>=0) && (yInd<Y) )
            {
             z=yInd*X+xInd;
            //use z
            }
     }
}

我希望尽可能地失去对ijxIndyInd的依赖。换句话说,我希望“遍历”在循环中运行时收到的所有值z,但不涉及帮助变量ijxInd和{ {1}} - 或至少涉及最少数量的计算(最重要的是没有乘法)。我怎样才能做到这一点?关于使循环更有效的可能方法的其他提示将受到欢迎。谢谢!

2 个答案:

答案 0 :(得分:0)

如果我们假设offX和offY为0,并将'&lt;'替换为'&lt; =',我们可以通过这样做摆脱i和j:

for (yInd = 0; yInd <= aX + aY; ++yInd)
    for (xInd = max(-yInd, -aX); xInd <= min(yInd, aY); ++xInd)

答案 1 :(得分:0)

如果我们读到如何最大限度地减少循环迭代次数的问题,我们可以采用以下方法。

约束:

(xInd>=0) && (xInd<X)
(yInd>=0) && (yInd<Y)

允许用来收紧for循环的界限。展开xIndyInd会给出:

0 <= i - j + offX <= X
0 <= i + j + offY <= Y

修复i允许我们将第二个循环边界重写为:

for(int i=0; i<aY; i+=a) {
    int lower = (max(i + offX - X, -i - offY) / a) * a; //factored out for clarity.
    int upper = min(i + offX, Y - i -offY);
    for(int j=lower; j<=upper; j+=a) {

如果您对offXoffYaXY的可能值了解更多信息,则可能会进一步缩减。

请注意,实际上您可能不想盲目地应用此类优化而不首先进行分析(这可能会阻止编译器为您执行此操作,例如gcc graphite)。

用作索引

如果使用值z=yInd*X+xInd来索引内存,则通过确保内存访问是顺序的来确保良好的缓存行为,可以实现更大的胜利。

目前每次迭代都会发生yInd次更改,因此可能会导致缓存性能下降。

此问题的解决方案是首先计算并存储所有指标,然后使用这些指标在第二次通过中执行所有内存操作。

int indicies[Y * X];
int index = 0;
for(...){
    for(...){
        ...
        indicies[index++] = z;
    }
}
// sort indicies
for(int idx = 0; idx < index; idx++){
    z = indicies[idx];
    //do stuff with z
}