Странное поведение автоковекторизации Gcc в матрице умножения, когда массивы являются параметрами функции - PullRequest
0 голосов
/ 20 июня 2019

Я тестирую разные формы умножения матриц с разными уровнями оптимизации (в учебных целях), и я обнаружил странное поведение в gve autovectorization. Он не может векторизовать, когда массивы являются параметрами (см. 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 требует примерно в 10 раз больше времени выполнения mxmg. Изучая код ассемблера, просто случается, что gcc способен автоматически векторизовать mxmg (когда массивы являются глобальными переменными), но не может векторизовать mxmp (где массивы являются параметрами).

Пробовал то же самое с формой kij, и он может векторизовать обе функции.

Мне нужна помощь, чтобы выяснить, почему у gcc такое поведение. И как помочь gcc (прагмы, параметры компиляции, атрибуты, ...) правильно векторизовать функцию mxmp. Спасибо

1 Ответ

0 голосов
/ 20 июня 2019

Когда массивы являются глобальными, компилятор может легко увидеть, что они являются непересекающимися областями памяти. Когда они являются параметрами функции, вы можете вызвать 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]) {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...