有人可以解释为什么icc没有在下面的代码1中进行循环不变的代码运动(移动指针的a)。当指针赋值从代码2中的t6循环中移出时,我看到性能提高了40%。我尝试将指针'a'标记为const并限制,让编译器知道指针'a'不会在t6循环内改变。我正在使用icc中的-ansi-alias选项编译代码。
// code 1
for (t4=256*t1; t4<=256*t1+254; t4++) {
lbv=256*t2;
ubv=256*t2+255;
for (t6=lbv; t6<=ubv; t6++) {
double *restrict const a = a_trans[lbv /256]; //loop invariant code
a[t6-lbv]=a[t6-lbv]/a[t6-lbv];
}
}
//代码2
for (t4=256*t1; t4<=256*t1+254; t4++) {
lbv=256*t2;
ubv=256*t2+255;
double *restrict const a = a_trans[lbv /256];
for (t6=lbv; t6<=ubv; t6++) {
a[t6-lbv]=a[t6-lbv]/a[t6-lbv];
}
}
此代码由源到源转换器生成。手动操作非常繁琐 将此转换应用于大量循环。有没有办法让icc自动进行这种转换?
答案 0 :(得分:1)
似乎a_trans
和lbv
都在外部作用域中定义,而不是常量。你不能指望icc足够聪明,理解a
不会改变。对于像a_trans
和lbv
这样的大范围变量,编译器会将它们分配到RAM中。循环期间它们可能会被更改。实际上,如果它们被定义为局部变量(在寄存器中分配),则编译器可能能够对其进行优化。
for (t4=256*t1; t4<=256*t1+254; t4++) {
lbv=256*t2;
ubv=256*t2+255;
const int local_lbv=lbv;
const double** local_a_trans=a_trans;
for (t6=lbv; t6<=ubv; t6++) {
double *restrict const a = local_a_trans[local_lbv /256];
a[t6-lbv]=a[t6-lbv]/a[t6-lbv];
}
}
通常,编译器旨在编译和优化由人类编写的代码,而不是源代码翻译器。
另一方面,您可以尝试使用-O3
和-ipo
进行更积极的代码优化
尝试本地化变量后,仍然没有性能提升。我认为我们可以得出结论,代码生成器不会生成具有足够高性能的代码。自动生成后,建议手动重写。