Power8 上的 OpenMP SIMD

OpenMP SIMD on Power8

我想知道 Power8 上是否有任何编译器(gccxlc 等)支持 Power8 上的 OpenMP SIMD 构造?我尝试使用 XL (13.1),但无法成功编译。可能它还不支持simd构造。

我可以使用 gcc 4.9.1 进行编译(使用这些标志 -fopenmp -fopenmp-simd-O1)。我在 2 个 asm 文件之间放置差异。

我能说gcc 4.9可以生成altivec代码吗?为了优化更多,我应该怎么做? (我试过-O3,限制治疗)

我的代码很简单:

int *x, *y, *z;
x = (int*) malloc(n * sizeof(int));
y = (int*) malloc(n * sizeof(int));
z = (int*) malloc(n * sizeof(int));   

#pragma omp simd
for(i = 0; i < N; ++i)
  z[i] = a * x[i] + y[i];

生成的程序集在这里

  .L7:
  lwz 9,124(31)
  extsw 9,9 
  std 9,104(31)
  lfd 0,104(31)
  stfd 0,104(31)
  ld 8,104(31)
  sldi 9,8,2
  ld 10,152(31)
  add 9,10,9
  lwz 10,124(31)
  extsw 10,10
  std 10,104(31)
  lfd 0,104(31)
  stfd 0,104(31)
  ld 7,104(31)
  sldi 10,7,2
  ld 8,136(31)
  add 10,8,10
  lwz 10,0(10)
  extsw 10,10
  lwz 8,132(31)
  mullw 10,8,10
  extsw 8,10
  lwz 10,124(31)
  extsw 10,10
  std 10,104(31)
  lfd 0,104(31)
  stfd 0,104(31)
  ld 7,104(31)
  sldi 10,7,2
  ld 7,144(31)
  add 10,7,10
  lwz 10,0(10)
  extsw 10,10
  add 10,8,10
  extsw 10,10
  stw 10,0(9)
  lwz 9,124(31)
  addi 9,9,1
  stw 9,124(31)

GCC 与 -O1 -fopenmp-simd

.L7:
lwz 9,108(31)
mtvsrwa 0,9
mfvsrd 8,0
sldi 9,8,2
ld 10,136(31)
add 9,10,9
lwz 10,108(31)
mtvsrwa 0,10
mfvsrd 7,0
sldi 10,7,2
ld 8,120(31)
add 10,8,10
lwz 10,0(10)
extsw 10,10
lwz 8,116(31)
mullw 10,8,10
extsw 8,10
lwz 10,108(31)
mtvsrwa 0,10
mfvsrd 7,0
sldi 10,7,2
ld 7,128(31)
add 10,7,10
lwz 10,0(10)
extsw 10,10
add 10,8,10
extsw 10,10
stw 10,0(9)
lwz 9,108(31)
addi 9,9,1
stw 9,108(31)

为了澄清和理解细节,我还有一个应用程序是n^2 nbody应用程序。这次我的问题与这些编译器(gcc 4.9 和 XL 13.1)和架构(Intel 和 Power)有关。

我把所有的代码都写进了gist https://gist.github.com/grypp/8b9f0f0f98af78f4223e#file-input-c (完整版输入代码input.c)

  1. Power8 & XLC - 它说 "was not SIMD vectorized because it contains function calls. (there is sqrtf)"。这是合理的。但是在 asm 代码中我可以看到 xsnmsubmdp 是否正常? (汇编:https://gist.github.com/grypp/8b9f0f0f98af78f4223e#file-power8-xlc-noinnersimd-asm)
  2. Power8 & gcc 我尝试以两种方式编译它(使用 omp simd 构造和不使用)。它改变了我的asm代码,这正常吗? (根据 OpenMP,代码不应包含函数调用)(程序集:https://gist.github.com/grypp/8b9f0f0f98af78f4223e#file-power8-gcc-noinnersimd-asm & https://gist.github.com/grypp/8b9f0f0f98af78f4223e#file-power8-gcc-innersimd-asm
  3. i74820K & gcc 我用 omp simd 和没有它做了同样的测试。输出代码也不同。 FMA 会影响此代码块吗? (集合:https://gist.github.com/grypp/8b9f0f0f98af78f4223e#file-i74820k-gcc-noinnersimd-asm & https://gist.github.com/grypp/8b9f0f0f98af78f4223e#file-i74820k-gcc-innersimd-asm

提前致谢

我现在无法访问基于 Power 的机器,但在 x86 上使用 AST 转储程序进行的一些实验表明,只有在优化级别达到 [=11= 时,GCC 4.9.2 才开始生成 SIMD 代码],即以下选项应该可以解决问题:

-fopenmp-simd -O1

GCC 5.1.0 也是如此

另请注意,矢量化器应用的成本模型可能会阻止它在某些情况下实际生成矢量化代码。有关如何覆盖该行为的信息,请参阅 -fsimd-cost-model 和类似选项 here

POWER Linux 上的 XL 编译器目前仅支持 OpenMP 4.0 功能的一个子集。目前不支持 SIMD 构造功能,因此编译器将无法识别源代码中的构造。

但是,如果您正在寻找矢量化,那么好消息是 XL 编译器应该已经自动矢量化您的代码,只要您至少使用以下优化选项

-O3 -qhot -qarch=pwr8 -qtune=pwr8

这些选项将启用 high-order loop transformations 以及 POWER8 特定的优化,包括循环的循环自动矢量化。

之后,您应该会在生成的汇编代码中看到一些 VMX 和 VSX 指令,类似于以下内容:

 188:   19 2e 80 7c     lxvw4x  vs36,0,r5
 18c:   84 09 a6 10     vslw    v5,v6,v1
 190:   10 00 e7 38     addi    r7,r7,16
 194:   10 00 a5 38     addi    r5,r5,16
 198:   40 28 63 10     vadduhm v3,v3,v5
 19c:   80 20 63 10     vadduwm v3,v3,v4
 1a0:   19 4f 66 7c     stxvw4x vs35,r6,r9
 1a4:   14 02 86 41     beq     cr1,3b8 <foo+0x3b8>
 1a8:   10 00 20 39     li      r9,16
 1ac:   19 4e 27 7d     lxvw4x  vs41,r7,r9
 1b0:   19 3e a0 7c     lxvw4x  vs37,0,r7

顺便说一下,您还可以使用 -qreport 选项从 XL 编译器获取优化报告。这将解释哪些循环是矢量化的,哪些循环不是矢量化的,以及原因是什么。例如

1586-542 (I) Loop (loop index 1 with nest-level 0 and iteration count 100) at test.c was SIMD vectorized.

1586-549 (I) Loop (loop index 2) at test.c was not SIMD vectorized because a data dependence prevents SIMD vectorization.

希望对您有所帮助!