我如何展开以下嵌套循环?
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;
。
谢谢, 赫里斯托斯
答案 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]
时无限循环的索引。