Кто-нибудь видит что-нибудь очевидное в коде цикла ниже, чего я не вижу, почему это не может быть автоматически векторизовано компилятором С++ VS2012?
Все, что компилятор дает мне, это info C5002: loop not vectorized due to reason '1200', когда я использую переключатель командной строки /Qvec-report:2.
Причина 1200 задокументирована в MSDN как:
Цикл содержит переносимые циклом зависимости данных, которые предотвращают векторизацию. Разные итерации цикла мешают друг другу, так что векторизация цикла будет давать неверные ответы, а автовекторизатор не может доказать себе, что таких зависимостей по данным нет.
Я знаю (или я почти уверен, что) нет никаких зависимостей данных, переносимых циклом, но я не уверен, что мешает компилятору понять это.
Эти указатели source и dest никогда не перекрываются и не создают псевдонимы одной и той же памяти, и я пытаюсь предоставить компилятору эту подсказку через __restrict.
pitch всегда является положительным целым числом, что-то вроде 4096, в зависимости от разрешения экрана, поскольку это функция рендеринга/преобразования 8bpp->32bpp, работающая по столбцам.
byte * __restrict source;
DWORD * __restrict dest;
int pitch;
for (int i = 0; i < count; ++i) {
dest[(i*2*pitch)+0] = (source[(i*8)+0]);
dest[(i*2*pitch)+1] = (source[(i*8)+1]);
dest[(i*2*pitch)+2] = (source[(i*8)+2]);
dest[(i*2*pitch)+3] = (source[(i*8)+3]);
dest[((i*2+1)*pitch)+0] = (source[(i*8)+4]);
dest[((i*2+1)*pitch)+1] = (source[(i*8)+5]);
dest[((i*2+1)*pitch)+2] = (source[(i*8)+6]);
dest[((i*2+1)*pitch)+3] = (source[(i*8)+7]);
}
Круглые скобки вокруг каждого source[] являются остатками вызова функции, который я здесь опустил, потому что цикл по-прежнему не будет автоматически векторизован без вызова функции в его самой простой форме.
ИЗМЕНИТЬ:
Я упростил цикл до его самой тривиальной формы:
for (int i = 0; i < 200; ++i) {
dest[(i*2*4096)+0] = (source[(i*8)+0]);
}
Это по-прежнему производит тот же код причины 1200.
ИЗМЕНИТЬ (2):
Этот минимальный тестовый пример с локальными выделениями и идентичными типами указателей по-прежнему не может автоматически векторизоваться. Я просто сбит с толку в этот момент.
const byte * __restrict source;
byte * __restrict dest;
source = (const byte * __restrict ) new byte[1600];
dest = (byte * __restrict ) new byte[1600];
for (int i = 0; i < 200; ++i) {
dest[(i*2*4096)+0] = (source[(i*8)+0]);
}
pitchвсегда является положительным целым числом. Но знает ли об этом компилятор? - person Mysticial   schedule 23.12.2012restrictна уровне функций. Таким образом, объявление указателей как ограниченных внутри функции ничего не делает. Попробуйте заменить их выделениями. Может быть, будет достаточно ума, чтобы признать, что они не могут быть псевдонимами, если они поступают из разных распределений. - person Mysticial   schedule 23.12.2012__restrictна глобальных переменных, и если это не удастся, я попробую просто с фиктивными выделениями в функции. - person James Dunne   schedule 23.12.2012dest[i] = source[i];, это дало мне причину 1300: тело цикла не содержит или содержит очень мало вычислений. Я думаю, ему не нравятся сложные индексаторы. - person James Dunne   schedule 23.12.2012