当数组是函数参数时,矩阵中的Gcc自动矢量化怪异行为

时间:2019-06-20 09:14:19

标签: gcc auto-vectorization

我正在对具有不同优化级别(出于教学目的)的不同矩阵乘法形式进行基准测试,并且在gcc自动矢量化过程中发现了奇怪的行为。当数组是参数时,它无法向量化(请参阅mxmp),但是当数组是全局变量时,它可以向量化(请参见mxmg)

gcc版本7.4.0(Ubuntu 7.4.0-1ubuntu1〜18.04.1) 但是行为与旧版gcc相同

编译选项: gcc -O3 -mavx2 -mfma

#define N 1024
float A[N][N], B[N][N], C[N][N];

void mxmp(float A[N][N], float B[N][N], float C[N][N]) {
  int i,j,k;
  for (i=0; i<N; i++)
    for (j=0; j<N; j++)
      for (k=0; k<N; k++)
        C[i][j] = C[i][j] + A[i][k] * B[k][j];
}

void mxmg() {
  int i,j,k;
  for (i=0; i<N; i++)
    for (j=0; j<N; j++)
      for (k=0; k<N; k++)
        C[i][j] = C[i][j] + A[i][k] * B[k][j];
}

main(){
  mxmg();
  mxmp(A, B, C);
}

我希望编译器在两个函数中都执行相同的操作,但是mxmp的执行时间约为mxmg的10倍。在研究汇编代码时,碰巧gcc能够自动向量化mxmg(当数组是全局变量时),但是无法向量化mxmp(其中数组是参数)。

使用kij形式进行了相同的尝试,并且可以向量化这两个函数。

我需要帮助来发现为什么gcc会出现这种行为。以及如何帮助gcc(编译指示,编译选项,属性等)正确地向量化mxmp函数。 谢谢

1 个答案:

答案 0 :(得分:0)

当数组是全局数组时,编译器可以轻松地看到它们是不相交的内存区域。当它们是函数参数时,您可以调用mxmp(A,A,A),因此必须假定写入C可能会修改A或B,这可能会影响以后的迭代并使向量化复杂化。当然,在您的特定情况下,编译器可以内联或执行其他操作来了解它...

您可以使用restrict明确指定缺少别名:

void mxmp(float A[restrict N][N], float B[restrict N][N], float C[restrict N][N]) {