矩阵乘法的自动向量化

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.

更新: 当您使用 NM 等变量作为循环计数器时,您可能看不到向量化。因此,您应该改用 constants。根据我的经验,矩阵-矩阵乘法可以使用 gcc 4.8, 5.4 and 6.2 向量化。 clang-LLVMICCMSVC 等其他编译器也将其矢量化。如评论中所述,如果您使用 doublefloat 数据类型,您可能需要使用 -ffast-math 这是 -Ofast 优化级别中的启用标志,表示您不需要一个高精度的结果(大多数时候没问题)。这是因为编译器对浮点运算更加谨慎。