矢量化失败了GCC

时间:2014-05-05 20:19:15

标签: c++ c gcc vectorization icc

我正在尝试理解矢量化,但令我惊讶的是这个非常简单的代码没有被矢量化

#define n 1024
int main () {
  int i, a[n], b[n], c[n];

  for(i=0; i<n; i++) { a[i] = i; b[i] = i*i; }
  for(i=0; i<n; i++) c[i] = a[i]+b[i];
}

虽然英特尔编译器因某种原因导致初始化循环,第5行。

> icc -vec-report a.c
a.c(5): (col. 3) remark: LOOP WAS VECTORIZED

GCC,我似乎没有得到任何东西

> gcc -ftree-vectorize -ftree-vectorizer-verbose=2 a.c

我做错了吗?这不应该是一个非常简单的可矢量化循环吗?所有相同的操作,连续存储器等。我的CPU支持SSE1 / 2/3/4。

--- 更新 ---

根据以下答案,此示例适用于我。

#include <stdio.h>
#define n 1024

int main () {
  int i, a[n], b[n], c[n];

  for(i=0; i<n; i++) { a[i] = i; b[i] = i*i; }
  for(i=0; i<n; i++) c[i] = a[i]+b[i];

  printf("%d\n", c[1023]);  
}

使用icc

> icc -vec-report a.c
a.c(7): (col. 3) remark: LOOP WAS VECTORIZED
a.c(8): (col. 3) remark: LOOP WAS VECTORIZED

和gcc

> gcc -ftree-vectorize -fopt-info-vec -O a.c
a.c:8:3: note: loop vectorized
a.c:7:3: note: loop vectorized

2 个答案:

答案 0 :(得分:8)

我稍微修改了您的源代码,以确保GCC无法删除循环:

#include <stdio.h>
#define n 1024

int main () {
  int i, a[n], b[n], c[n];

  for(i=0; i<n; i++) { a[i] = i; b[i] = i*i; }
  for(i=0; i<n; i++) c[i] = a[i]+b[i];

  printf("%d\n", c[1023]);  
}

GCC(v4.8.2)可以对两个循环进行矢量化,但它需要-O标志:

gcc -ftree-vectorize -ftree-vectorizer-verbose=1 -O2 a.c

我得到了:

  

分析a.c:8

的循环      

在a.c:8

处进行矢量化循环      

a.c:8注意:LOOP VECTORIZED。在a.c:7分析循环

     

在a.c:7

处进行矢量化循环      

a.c:7注意:LOOP VECTORIZED。 a.c:注意:矢量化的2个循环   功能

使用-fdump-tree-vect开关GCC会在a.c.##t.vect文件中转储更多信息(这对于了解正在发生的事情&#34;内部&#34;)非常有用。

还要考虑:

答案 1 :(得分:0)

在大多数情况下,如果选项-Ofast -march=native可以在您的处理器上使用,则会对其进行矢量化处理。

$ gcc compute_simple.c -Ofast -march=native -fopt-info-vec -o compute_simple.bin
compute_simple.c:14:5: note: loop vectorized
compute_simple.c:14:5: note: loop versioned for vectorization because of possible aliasing
compute_simple.c:14:5: note: loop vectorized

要了解处理器是否可以执行此操作,请使用lscpu并查看可用的标志。

$ lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              12
...
Vendor ID:           GenuineIntel
...
Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge  
 mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall   
nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl   
xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64   
monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1   
sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand   
lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb   
stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1   
hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt   
xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify   
hwp_act_window hwp_epp md_clear flush_l1d

在Intel上需要sse / avx,在ARM上需要neon,在AMD上需要其他(例如xop)。

您可以通过搜索gcc文档来找到有关向量化的更多信息。

关于此主题,这是一篇不错的文章,其中包含可用于许多平台的标志: https://gcc.gnu.org/projects/tree-ssa/vectorization.html

最后,如上所述,在旧版gcc中使用-ftree-vectorizer-verbose=n,在最新版本中使用-fopt-info-vec,以查看矢量化的内容。