在C ++中展开嵌套for循环

时间:2010-05-01 18:37:46

标签: c++ optimization loops

我如何展开以下嵌套循环?

for(k = begin; k != end; ++k) {
 for(j = 0; j < Emax; ++j) {
  for(i = 0; i < N; ++i) { 
   if (j >= E[i]) continue; 
   array[k] += foo(i, tr[k][i], ex[j][i]);
  }
 }
}

我尝试了以下内容,但我的输出不一样,应该是:

for(k = begin; k != end; ++k) {
 for(j = 0; j < Emax; ++j) {
  for(i = 0; i+4 < N; i+=4) { 
   if (j >= E[i]) continue; 
   array[k] += foo(i, tr[k][i], ex[j][i]);
   array[k] += foo(i+1, tr[k][i+1], ex[j][i+1]);
   array[k] += foo(i+2, tr[k][i+2], ex[j][i+2]);
   array[k] += foo(i+3, tr[k][i+3], ex[j][i+3]);
  }
  if (i < N) {
   for (; i < N; ++i) {
    if (j >= E[i]) continue; 
    array[k] += foo(i, tr[k][i], ex[j][i]);
   }
  }
 }
}

我将使用英特尔的TBB并行运行此代码,以便利用多个内核。完成运行后,另一个函数打印出array []中的内容,现在,在展开时,输出不一样。任何帮助表示赞赏。

更新:我修好了。我使用这个问题的答案进行展开...输出不匹配,因为我在第一个for循环后没有进行array[k] = 0;

谢谢, 赫里斯托斯

2 个答案:

答案 0 :(得分:2)

   if (j >= E[i]) continue; 
   array[k] += foo(i, tr[k][i], ex[j][i]);
   array[k] += foo(i+1, tr[k][i+1], ex[j][i+1]);
   array[k] += foo(i+2, tr[k][i+2], ex[j][i+2]);
   array[k] += foo(i+3, tr[k][i+3], ex[j][i+3]);

if (j >= E[i]) continue; 
array[k] += foo(i, tr[k][i], ex[j][i]);

筛选条件不相同

更好的筛选方法(消除分支):

array[k] += (j < E[i])*foo(i, tr[k][i], ex[j][i]);

另外,你需要保证N可被4整除,否则你可能会超调。或者,截断N可被4整除(N - N%4)

答案 1 :(得分:1)

我认为if (j >= E[i]) continue;是你的问题。在原始版本中,将针对每个索引i运行此测试。在展开的版本中,它仅针对每四个索引进行测试。请尝试以下方法:

for (i = 0; i < N; /*advanced in loop*/) {
    if (j >= E[i]) continue;
    array[k] += foo(i, tr[k][i], ex[j][i]); ++i;
    if (j >= E[i]) continue;
    array[k] += foo(i, tr[k][i], ex[j][i]); ++i;
    if (j >= E[i]) continue;
    array[k] += foo(i, tr[k][i], ex[j][i]); ++i;
    if (j >= E[i]) continue;
    array[k] += foo(i, tr[k][i], ex[j][i]); ++i;
}
while (i < N) {
    if (j >= E[i]) {
        ++i; // missing in original version
        continue;
    }
    array[k] += foo(i, tr[k][i], ex[j][i]);
    ++i;
}

编辑:我忘记在原始版本中增加一个导致j >= E[i]时无限循环的索引。