vc ++不再使用基于范围的语法对for循环进行简单的向量化

Thr*_*r57 10 c++ vectorization visual-c++ c++11 ranged-loops

在用基于范围的循环替换我的许多"旧"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);
Run Code Online (Sandbox Code Playgroud)

看看反汇编,循环的标准都是矢量化的:

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

但基于循环的范围不是:

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

有没有理由为什么编译器无法对这些循环进行矢量化?

我真的很想使用新的语法,但是失去矢量化太糟糕了.

我刚看到这个问题,所以我尝试了/Qvec-report:2旗帜,给出了另一个原因:

loop not vectorized due to reason '1200'
Run Code Online (Sandbox Code Playgroud)

那是:

循环包含阻止矢量化的循环携带数据依赖性.循环的不同迭代相互干扰,使得对循环进行矢量化将产生错误的答案,并且自动矢量化器不能向自身证明不存在这样的数据依赖性.

这是同一个bug吗?(我也试过最后一个vc ++编译器"2013年11月CTP")

我应该在MS连接上报告吗?

编辑

对于评论,我使用原始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);
Run Code Online (Sandbox Code Playgroud)

小智 1

我的猜测可能是,基于范围的 for 循环不会立即知道该对象是向量、数组或链表,因此编译器不知道事先向量化循环。基于范围的 for 循环相当于其他语言中的 foreach 循环。可能有一种方法可以提示编译器使用宏或编译指示或编译器设置来提示预先对循环进行矢量化。要检查,请尝试使用其他编译器中的代码,看看您得到什么,如果您使用其他编译器获得非矢量化汇编代码,我不会感到惊讶。