2

有人可以解释为什么 icc 在下面的代码 1 中没有执行循环不变代码运动(a 的移动指针分配)的原因。当 a 指针分配移出 t6 循环时,如代码 2 中所做的那样,我看到性能提高了 40%。我尝试将指针“a”标记为 const 和限制,让编译器知道指针“a”不会在 t6 循环内更改。我在 icc 中使用 -ansi-alias 选项编译代码。

//代码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 自动进行这种转换?

4

1 回答 1

1

它似乎两者都在外部范围内定义,a_trans并且lbv不是常量。你不能指望icc足够聪明,明白a不会改变。a_trans对于像and这样的大范围变量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

编辑

尝试本地化变量后,仍然没有性能提升。我想我们可以得出一个结论,代码生成器不会生成性能足够高的代码。自动生成后建议手动重写。

于 2013-10-19T14:17:41.693 回答