矩阵乘法的自动矢量化
我对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
,但我没有看到任何消息矢量已完成。
如果有人能帮助我,那将非常感激。
在你的命令中没有向量化信息!您可以使用-fopt-info-vec
来打开矢量化报告。但是,不要依赖它。编译器有时会存在(他们矢量化和报告它,但不使用它!),你可以改进这些改进!为此,你可以测量加速。首先,禁用矢量化并测量时间t1。然后启用并测量时间t2。如果它大于1,那么加速将会是t1/t2,它说编译器改进了,如果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
优化级别中的启用标志,说您不需要高精确度的结果(大多数情况都是如此)。这是因为复制者更擅长于浮点操作。
谢谢一堆:) –
@WorkofArtiz和Martin:'gcc -O3'启用'-ftree-vectorize'和其他一些东西。请注意,“-Ofast”是“-O3 -ffast-math”,而不是“-O2”。无论如何,我建议比较'-O3 -ffast-math -march = native'与'O3 -ffast-math -march = native -fno-tree-vectorize'。 –
关于常量与可变循环计数的好处。只要循环迭代计数在第一次迭代之前已知,gcc和clang通常可以进行矢量化。 (但他们永远不能像'while(a [i ++]!= 2){}')那样矢量化搜索循环。尽管如此,他们通常在编译时常量循环计数方面做得更好。 –
'-fopt-info-all-vec'(详见doc文档)给出了更多信息。 '-fopt-info-missed-vec'输出中的一个关键要素是“减少:不安全的fp数学优化:tmp_40 = _16 + tmp_49;”这实质上意味着你需要-ffast-math(或稍微弱一点)来进行矢量化。 –