VC++ 不再使用基于范围的语法对简单 FOR 循环进行矢量化



在用基于范围的 for 循环替换很多"旧"的 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("%fn", sum);

查看反汇编,标准 for 循环全部矢量化:

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

但基于范围的 for 循环不是:

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++ 编译器"Nov 2013 CTP")

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

编辑

Du 评论,我用原始 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("%fn", sum);

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

最新更新