Прежде чем заменить большую часть моих «старых» циклов 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);
Я могу предположить, что основанный на диапазоне цикл for не знает, что объект является вектором, массивом или связанным списком, поэтому компилятор не знает заранее, векторизует цикл. Циклы for на основе диапазона являются эквивалентом цикла foreach в других языках. Там может быть способ подсказать компилятору, чтобы подсказка заранее векторизовал цикл, используя макрос, прагму или настройку компилятора. Чтобы проверить, попробуйте использовать код в других компиляторах и посмотреть, что вы получите. Я не удивлюсь, если вы получите не векторизованный ассемблерный код с другими компиляторами.