У меня есть некоторый код, который я хотел бы запустить быстро, поэтому я надеялся, что смогу убедить gcc (g ++) векторизовать некоторые из моих внутренних циклов. Флаги моего компилятора включают
-O3 -msse2 -ffast-math -ftree-vectorize -ftree-vectorizer-verbose=5
но gcc не может векторизовать наиболее важные циклы, что дает мне следующие не очень подробные сообщения:
Not vectorized: complicated access pattern.
а также
Not vectorized: unsupported use in stmt.
Мои вопросы: (1) что именно они означают? (Насколько сложным должно быть это, прежде чем оно станет слишком сложным? Неподдерживаемое использование чего именно?), И (2) есть ли способ заставить компилятор дать мне даже чуть-чуть больше информации о том, что я делаю неправильно?
Примером цикла, который дает «сложный шаблон доступа», является
for (int s=0;s<N;++s)
a.grid[s][0][h-1] = D[s] * (b.grid[s][0][h-2] + b.grid[s][1][h-1] - 2*b.grid[s][0][h-1]);
и тот, который дает «неподдерживаемое использование в stmt», является внутренним циклом
for (int s=0;s<N;++s)
for (int i=1;i<w-1;++i)
for (int j=1;j<h-1;++j)
a.grid[s][i][j] = D[s] * (b.grid[s][i][j-1] + b.grid[s][i][j+1] + b.grid[s][i-1][j] + b.grid[s][i+1][j] - 4*b.grid[s][i][j]);
(Это то, что действительно необходимо оптимизировать.) Здесь a.grid и b.grid — трехмерные массивы с плавающей точкой, D — одномерный массив с плавающей точкой, а N, w и h — это константы.
Не векторизовано: сложная схема доступа.
«Неосложненные» шаблоны доступа — это последовательный доступ к элементам или доступ по элементам с определенными ограничениями (один элемент группы, к которому осуществляется доступ в цикле, количество элементов группы равно степени 2, размер группы кратен типу вектора).
b.grid[s][0][h-2] + b.grid[s][1][h-1] - 2*b.grid[s][0][h-1]);
Ни последовательный, ни поэтапный доступ
Не векторизовано: неподдерживаемое использование в stmt.
Здесь «использование» в смысле потока данных, получение значения переменной (регистр, компилятор временный). В этом случае «поддерживаемое использование» — это переменные, определенные в текущей итерации цикла, константы и инварианты цикла.
a.grid[s][i][j] = D[s] * (b.grid[s][i][j-1] + b.grid[s][i][j+1] + b.grid[s][i-1][j] + b.grid[s][i+1][j] - 4*b.grid[s][i][j]);
В этом примере, я думаю, что «неподдерживаемое использование» происходит потому, что b.grid[s][i][j-1]
а также b.grid[s][i][j+1]
присваиваются («определены») предыдущей итерацией цикла.
Других решений пока нет …