我有以下嵌套循环计算:
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
}
}
}
我希望尽可能地失去对i
,j
,xInd
和yInd
的依赖。换句话说,我希望“遍历”在循环中运行时收到的所有值z
,但不涉及帮助变量i
,j
,xInd
和{ {1}} - 或至少涉及最少数量的计算(最重要的是没有乘法)。我怎样才能做到这一点?关于使循环更有效的可能方法的其他提示将受到欢迎。谢谢!
答案 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循环的界限。展开xInd
和yInd
会给出:
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) {
如果您对offX
,offY
,a
,X
和Y
的可能值了解更多信息,则可能会进一步缩减。
请注意,实际上您可能不想盲目地应用此类优化而不首先进行分析(这可能会阻止编译器为您执行此操作,例如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
}