矩阵乘法的自动向量化
Automatic vectorization of matrix multiplication
我对 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。加速将是 t1/t2 如果它大于 1 它说编译器改进如果 1 没有改进如果小于 1 它说编译器自动向量化器为你毁了它!另一种方法是将 -S
添加到命令中,然后在单独的 .s
文件中查看汇编代码。
注意: 如果您想查看自动矢量化能力,请添加 -march=native
并删除 -msse2
.
更新: 当您使用 N
、M
等变量作为循环计数器时,您可能看不到向量化。因此,您应该改用 constants
。根据我的经验,矩阵-矩阵乘法可以使用 gcc 4.8, 5.4 and 6.2
向量化。 clang-LLVM
、ICC
和 MSVC
等其他编译器也将其矢量化。如评论中所述,如果您使用 double
或 float
数据类型,您可能需要使用 -ffast-math
这是 -Ofast
优化级别中的启用标志,表示您不需要一个高精度的结果(大多数时候没问题)。这是因为编译器对浮点运算更加谨慎。
我对 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。加速将是 t1/t2 如果它大于 1 它说编译器改进如果 1 没有改进如果小于 1 它说编译器自动向量化器为你毁了它!另一种方法是将 -S
添加到命令中,然后在单独的 .s
文件中查看汇编代码。
注意: 如果您想查看自动矢量化能力,请添加 -march=native
并删除 -msse2
.
更新: 当您使用 N
、M
等变量作为循环计数器时,您可能看不到向量化。因此,您应该改用 constants
。根据我的经验,矩阵-矩阵乘法可以使用 gcc 4.8, 5.4 and 6.2
向量化。 clang-LLVM
、ICC
和 MSVC
等其他编译器也将其矢量化。如评论中所述,如果您使用 double
或 float
数据类型,您可能需要使用 -ffast-math
这是 -Ofast
优化级别中的启用标志,表示您不需要一个高精度的结果(大多数时候没问题)。这是因为编译器对浮点运算更加谨慎。