vc ++ больше не векторизуется просто для циклов с синтаксисом на основе диапазона

Прежде чем заменить большую часть моих «старых» циклов for на диапазоны, основанные на циклах, я провел несколько тестов в Visual Studio 2013:

std::vector<int> numbers;

for (int i = 0; i < 50; ++i) numbers.push_back(i);

int sum = 0;

//vectorization
for (auto number = numbers.begin(); number != numbers.end(); ++number) sum += *number;

//vectorization
for (auto number = numbers.begin(); number != numbers.end(); ++number) {
auto && ref = *number;
sum += ref;
}

//definition of range based for loops from http://en.cppreference.com/w/cpp/language/range-for
//vectorization
for (auto __begin = numbers.begin(),
__end = numbers.end();
__begin != __end; ++__begin) {
auto && ref = *__begin;
sum += ref;
}

//no vectorization :(
for (auto number : numbers) sum += number;

//no vectorization :(
for (auto& number : numbers) sum += number;

//no vectorization :(
for (const auto& number : numbers) sum += number;

//no vectorization :(
for (auto&& number : numbers) sum += number;

printf("%f\n", sum);

Глядя на разборку, все стандартные циклы были векторизованы:

00BFE9B0  vpaddd      xmm1,xmm1,xmmword ptr [eax]
00BFE9B4  add         ecx,4
00BFE9B7  add         eax,10h
00BFE9BA  cmp         ecx,edx
00BFE9BC  jne         main+140h (0BFE9B0h)

но диапазон для петель не был:

00BFEAC6  add         esi,dword ptr [eax]
00BFEAC8  lea         eax,[eax+4]
00BFEACB  inc         ecx
00BFEACC  cmp         ecx,edi
00BFEACE  jne         main+256h (0BFEAC6h)

Есть ли причина, по которой компилятор не может векторизовать эти циклы?

Я действительно хотел бы использовать новый синтаксис, но потерять векторизацию очень плохо.

Я просто увидел этот вопрос, поэтому я попробовал /Qvec-report:2 флаг, давая другую причину:

loop not vectorized due to reason '1200'

то есть:

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

Это та же ошибка? (Я также пытался с последним компилятором vc ++ «ноябрь 2013 CTP»)

Должен ли я сообщить об этом на MS Connect тоже?

Что касается комментариев, я проделал тот же тест с необработанным массивом int вместо вектора, поэтому класс итераторов не задействован, только необработанные указатели.

Теперь все циклы векторизованы, кроме двух «имитированных диапазонов».

Компилятор говорит, что это связано с причиной ‘501’:

Индукционная переменная не является локальной; или верхняя граница не является инвариантной к петле.

Я не понимаю, что происходит …

const size_t size = 50;
int numbers[size];

for (size_t i = 0; i < size; ++i) numbers[i] = i;

int sum = 0;

//vectorization
for (auto number = &numbers[0]; number != &numbers[0] + size; ++number) sum += *number;

//vectorization
for (auto number = &numbers[0]; number != &numbers[0] + size; ++number) {
auto && ref = *number;
sum += ref;
}

//definition of range based for loops from http://en.cppreference.com/w/cpp/language/range-for
//NO vectorization ?!
for (auto __begin = &numbers[0],
__end = &numbers[0] + size;
__begin != __end; ++__begin) {
auto && ref = *__begin;
sum += ref;
}

//NO vectorization ?!
for (auto __begin = &numbers[0],
__end = &numbers[0] + size;
__begin != __end; ++__begin) {
auto && ref = *__begin;
sum += ref;
}

//vectorization ?!
for (auto number : numbers) sum += number;

//vectorization ?!
for (auto& number : numbers) sum += number;

//vectorization ?!
for (const auto& number : numbers) sum += number;

//vectorization ?!
for (auto&& number : numbers) sum += number;

printf("%f\n", sum);

10

Решение

Я могу предположить, что основанный на диапазоне цикл for не знает, что объект является вектором, массивом или связанным списком, поэтому компилятор не знает заранее, векторизует цикл. Циклы for на основе диапазона являются эквивалентом цикла foreach в других языках. Там может быть способ подсказать компилятору, чтобы подсказка заранее векторизовал цикл, используя макрос, прагму или настройку компилятора. Чтобы проверить, попробуйте использовать код в других компиляторах и посмотреть, что вы получите. Я не удивлюсь, если вы получите не векторизованный ассемблерный код с другими компиляторами.

1

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


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