簡體   English   中英

vc ++不再使用基於范圍的語法對for循環進行簡單的向量化

[英]vc++ no longer vectorize simple for loops with range-based syntax

在用基於范圍的循環替換我的許多“舊”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'

那是:

循環包含阻止矢量化的循環攜帶數據依賴性。 循環的不同迭代相互干擾,使得對循環進行矢量化將產生錯誤的答案,並且自動矢量化器不能向自身證明不存在這樣的數據依賴性。

這是同一個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);

我的猜測可能是基於范圍的for循環不會隨意知道對象是向量或數組或鏈表,因此編譯器事先不知道向量化循環。 基於范圍的for循環相當於其他語言中的foreach循環。 可能有一種方法可以提示編譯器使用宏或編譯指示或編譯器設置預先對循環進行矢量化。 要檢查請嘗試使用其他編譯器中的代碼,看看你得到了什么,如果你得到其他編譯器的非矢量化匯編代碼,我不會感到驚訝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM