Как заставить Visual C ++ векторизовать этот цикл (код ошибки 1200)?

Я пытаюсь сделать так, чтобы VC ++ 2012 автоматически векторизовал цикл, который выглядит примерно так (на самом деле происходят интересные вычисления, но они сделаны с целью сделать вопрос как можно более точным).

parameters:
int period;
unsigned char* out_array;
unsigned char* in_array1;
unsigned char* in_array2;
unsigned char* in_array3;

for (int x = 0; x < width; ++x)
{
int index = period * (x / 2);

out_array[0] = in_array1[x];
out_array[1] = in_array2[index];
out_array[2] = in_array3[index];
out_array += 4;
}

Я думал, что единственное, что стоит на пути векторизации, это out_array += 4Я сделал внутренний развернутый цикл, надеясь, что хотя бы один из них может быть векторизован:

for (int x = 0; x < width; ++x)
{
for (int xx = 0; xx < 4; ++xx)
{
int index = period * ((xx + x) / 2);

unsigned char* pout_array = out_array + (4 * xx);
pout_array[0] = in_array1[xx + x];
pout_array[1] = in_array2[index];
pout_array[2] = in_array3[index];
}
out_array += 16;
}

Но как я запускаю компилятор с /Qvect-report:2, это говорит мне, что внутренний цикл не может быть векторизован из-за кода ошибки 1200. Код ошибки 1200 гласит:

Цикл содержит переносимые в петлю зависимости данных, которые предотвращают
векторизации. Различные итерации цикла мешают каждому
другой такой, что векторизация цикла будет давать неправильные ответы, и
авто-векторизатор не может доказать себе, что таких данных нет
зависимости.

Я не понимаю этого. Очевидно, что каждая итерация этого цикла независима. Как я могу заставить Visual Studio его векторизовать?

3

Решение

Основная причина, по которой он не может векторизовать это, заключается в том, что, как написано, компилятор не может исключить возможность того, что out_array [n] не является in_arrayX [m], поэтому он должен придерживаться вашего последовательного порядка.

Вы можете разрешить это для компилятора с помощью ключевого слова «__restrict» или «restrict», которое обещает компилятору, что вы будете вызывать его только таким образом, чтобы гарантировать, что out_array не совпадает с любым из трех других указателей. Вы также можете захотеть использовать модификатор «const», чтобы помочь компилятору:

void func(const int period,
unsigned char* __restrict out_array,
const unsigned char* in_array1,
const unsigned char* in_array2,
const unsigned char* in_array3)
{
...
//mark 'width' as 'const' if possible:
const int width = ...;
for (int x = 0; x < width; ++x)
{
const int index = period * (x / 2);

out_array[(x* 4) + 0] = in_array1[x];
out_array[(x* 4) + 1] = in_array2[index];
out_array[(x* 4) + 2] = in_array3[index];
}
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]