我正在对具有不同优化级别(出于教学目的)的不同矩阵乘法形式进行基准测试,并且在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函数。 谢谢
答案 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]) {