在用基于范围的循环替换我的许多“旧”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)
有没有理由为什么编译器无法对这些循环进行矢量化?
我真的很想使用新的语法,但是失去矢量化太糟糕了。
我刚看到this question,所以我尝试了/Qvec-report:2
标志,给出了另一个原因:
loop not vectorized due to reason '1200'
即:
循环包含阻止矢量化的循环携带数据依赖性。不同的迭代 循环相互干扰,使得循环矢量化会产生错误的答案,并且 自动矢量化器无法证明自己没有这种数据依赖性。
这是同一个错误吗? (我也尝试过最后一个vc ++编译器“2013年11月CTP”)
我是否应该在MS连接上报告?
Du to comments,我使用原始int数组而不是vector执行相同的测试,因此不涉及迭代器类,只是原始指针。
现在除了两个“模拟的基于范围的”循环外,所有循环都被矢量化。
编译说这是由于'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);
答案 0 :(得分:1)
我的猜测可能是基于范围的for循环不会随意知道对象是向量或数组或链表,因此编译器事先不知道向量化循环。基于范围的for循环相当于其他语言中的foreach循环。可能有一种方法可以提示编译器使用宏或编译指示或编译器设置预先对循环进行矢量化。要检查一下,请尝试使用其他编译器中的代码,看看你得到了什么,如果你得到其他编译器的非矢量化汇编代码,我不会感到惊讶。