Как преодолеть "существование векторной зависимости" в icc
Я хочу векторизовать следующий цикл в C:
for(k = 0; k < SysData->numOfClaGen; k++)
A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]);
где нет псевдонима между переменными и ind0
постоянная Ни один из других указателей (A
или же B
) указать на ind0 и, следовательно, ind0
остается постоянным на протяжении всего цикла.
Когда я компилирую код с помощью icc, он говорит, что этот цикл не может быть векторизован из-за возможной векторной зависимости. Вот сообщение:
loop was not vectorized: existence of vector dependence.
Я сузил проблему и обнаружил, что замена ind0 на постоянное число решает проблему. Итак, я предполагаю, что ICC думает A
может указывать на ind0
и поэтому, ind0
может поменяться.
Я хотел бы знать, как я могу помочь компилятору узнать, что безопасно векторизовать такой цикл.
Заранее спасибо за помощь.
3 ответа
Добавлять #pragma ivdep
перед циклом for он указывает компилятору игнорировать предполагаемые векторные зависимости.
#pragma ivdep
for(k = 0; k < SysData->numOfClaGen; k++)
A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]);
для получения дополнительной информации о ivdep, см. документ ICC
Использование restrict
Модификатор для указателей утверждает компилятору, что нет псевдонимов. Это ключевое слово было введено в C99. C++ не поддерживает его, но многие компиляторы C++ поддерживают __restrict
в качестве эквивалентного проприетарного расширения. При использовании компилятора Intel необходимо включить использование restrict
добавив флаг командной строки -restrict
(Linux) или /Qrestrict
(Windows). В следующей версии вашего кода цикл используется по желанию при использовании компилятора Intel версии 13.1.3.198:
#include <math.h>
struct bar {
int numOfClaGen;
};
void foo (double * restrict A,
const double * restrict B,
const double * restrict x1,
const struct bar * restrict SysData,
const int ind0)
{
int k;
for (k = 0; k < SysData->numOfClaGen; k++) {
A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]);
}
}
Вызов компилятора следующим образом (в 64-битной системе Windows)
icl /c /Ox /QxHost /Qrestrict /Qvec-report2 vectorize.c
компилятор сообщил
vectorize.c(14): (col. 5) remark: LOOP WAS VECTORIZED.
Год назад icc был изменен на set -ansi-alias по умолчанию для Linux и Mac. Для Windows на это значение по умолчанию нельзя рассчитывать, так как оно конфликтует с использованием Microsoft. Эта опция эквивалентна gcc -fstrict-aliasing, которая используется по умолчанию с gcc 3.0. Я думаю, что гораздо лучше установить эту опцию, чем устанавливать ivdep restrict или simd для такой ограниченной проблемы. Хотя это не очень хорошо задокументировано, icc обрабатывает __restrict так же, как gcc, и не требует, чтобы параметр restrict или C99 принимал его. В принципе, он должен вступать в игру только для изменяемых объектов (A[] в приведенном выше примере). Как ни странно, __restrict имеет немного другое значение для MSVC++. Он допускает невекторную оптимизацию, которая в противном случае могла бы быть предотвращена возможными зависимостями, но не разрешает векторизацию (но это может относиться к настоящему случаю).