我对SIMD很新,想要试着看看我是否可以让GCC为我做一个简单的动作。
所以我看了this post,想做或多或少做同样的事情。 (但在Linux 64bit上使用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
编译,但是我没有看到任何关于矢量化完成的消息。
如果有人能帮助我,那将非常感激。
答案 0 :(得分:2)
您的命令中没有完成矢量化的消息!您可以使用-fopt-info-vec
打开矢量化报告。但是,不要依赖它。编译器有时会说谎(它们会对它进行矢量化和报告但不使用它!)你可以改进它们!为此,你可以测量加速。首先,禁用矢量化并测量时间t1。然后启用并测量时间t2。加速度将是t1 / t2,如果它大于1,它说编译器改进了如果1没有改善,如果小于1它说编译器自动矢量化器毁了你!另一种方法是将-S
添加到命令中,并在单独的.s
文件中查看汇编代码。
注意:如果您想查看自动向量化功能添加-march=native
并删除-msse2
。
UPDATE:当您使用N
,M
等变量作为循环计数器时,您可能看不到矢量化。因此,您应该使用constants
代替。根据我的经验,矩阵 - 矩阵乘法可以使用gcc 4.8, 5.4 and 6.2
进行矢量化。其他编译器(例如clang-LLVM
,ICC
和MSVC
也会对其进行矢量化。如评论中所述,如果您使用double
或float
数据类型,则可能需要使用-ffast-math
这是-Ofast
优化级别中的已启用标记,表示您不需要高精度的结果(大部分时间都可以)。这是因为ompilers对于浮选点操作更加关注。