2017-04-05 158 views
0

我对SIMD相当新颖,想试试看能否让GCC为我引导一个简单的动作。矩阵乘法的自动矢量化

所以我看着this post,想要做更多或更少的相同的事情。 (但在Linux 64位GCC 5.4.0,对于KabyLake处理器)

我基本上是有这个功能:

/* m1 = N x M matrix, m2 = M x P matrix, m3 = N x P matrix & output */ 
void mmul(double **m1, double **m2, double **m3, int N, int M, int P) 
{ 
    for (i = 0; i < N; i++) 
     for (j = 0; j < P; j++) 
     { 
      double tmp = 0.0; 

      for (k = 0; k < M; k++) 
       tmp += m1[i][k] * m2[k][j]; 

      tmp = m3[i][j]; 
     } 
    return m3; 
} 

其中我编译-O2 -ftree-vectorize -msse2 -ftree-vectorizer-verbose=5,但我没有看到任何消息矢量已完成。

如果有人能帮助我,那将非常感激。

+2

'-fopt-info-all-vec'(详见doc文档)给出了更多信息。 '-fopt-info-missed-vec'输出中的一个关键要素是“减少:不安全的fp数学优化:tmp_40 = _16 + tmp_49;”这实质上意味着你需要-ffast-math(或稍微弱一点)来进行矢量化。 –

回答

2

在你的命令中没有向量化信息!您可以使用-fopt-info-vec来打开矢量化报告。但是,不要依赖它。编译器有时会存在(他们矢量化和报告它,但不使用它!),你可以改进这些改进!为此,你可以测量加速。首先,禁用矢量化并测量时间t1。然后启用并测量时间t2。如果它大于1,那么加速将会是t1/t2,它说编译器改进了,如果1没有改进,如果小于一个,它说编译器自动矢量化器毁了你!另一种方法是您可以将-S添加到您的命令中,并在分开的.s文件中查看汇编代码。

注:,如果你想看到的自动向量化功率增加-march=native和删除-msse2

UPDATE:当你使用一个变量,一个NM等作为循环计数器,你可能看不到量化。因此,您应该使用constants代替。根据我的经验,矩阵 - 矩阵乘法可以使用gcc 4.8, 5.4 and 6.2进行矢量化。其他编译器如clang-LLVMICCMSVC也将其向量化。正如在评论中提到的,如果您使用doublefloat数据类型,则可能需要使用-ffast-math这是-Ofast优化级别中的启用标志,说您不需要高精确度的结果(大多数情况都是如此)。这是因为复制者更擅长于浮点操作。

+0

谢谢一堆:) –

+0

@WorkofArtiz和Martin:'gcc -O3'启用'-ftree-vectorize'和其他一些东西。请注意,“-Ofast”是“-O3 -ffast-math”,而不是“-O2”。无论如何,我建议比较'-O3 -ffast-math -march = native'与'O3 -ffast-math -march = native -fno-tree-vectorize'。 –

+1

关于常量与可变循环计数的好处。只要循环迭代计数在第一次迭代之前已知,gcc和clang通常可以进行矢量化。 (但他们永远不能像'while(a [i ++]!= 2){}')那样矢量化搜索循环。尽管如此,他们通常在编译时常量循环计数方面做得更好。 –