2014-11-15 6 views
10

Bevor eine Menge meiner „alten“ for-Schleifen mit Bereich auf Basis for-Schleifen ersetzen, lief ich einige Test mit Visual Studio 2013:vC++ nicht mehr vectorize einfach für Schleifen mit bereichsbasierte Syntax

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); 

betrachten die Demontage, Standard für Schleifen waren alle vektorisiert:

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

aber Bereich auf Basis for-Schleifen waren nicht:

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

Gibt es einen Grund, warum der Compiler diese Schleifen nicht vektorisieren konnte?

Ich würde wirklich gerne die neue Syntax verwenden, aber die Vektorisierung zu verlieren ist zu schlecht.

ich sah nur this question, so habe ich versucht, die /Qvec-report:2 Flagge, einen anderen Grund gibt:

loop not vectorized due to reason '1200' 

, die:

Schleife enthält schleifengeführte Datenabhängigkeiten, die Vektorisierung verhindern. Verschiedene Iterationen von die Schleife interferieren miteinander, so dass die Vektorisierung der Schleife falsche Antworten produzieren würde, und der Auto-Vektorizer kann sich nicht beweisen, dass es solche Datenabhängigkeiten nicht gibt.

Ist das der gleiche Fehler? (Ich habe auch mit dem letzten vC++ Compiler "Nov 2013 CTP") versucht

Sollte ich es auf MS melden verbinden auch?

bearbeiten

Du Kommentaren, habe ich den gleichen Test mit einem rohen int Array anstelle eines Vektors, so ist kein Iterator-Klasse beteiligt, nur rohe Zeiger.

Nun werden alle Schleifen vektorisiert, mit Ausnahme der zwei "simulierten bereichsbasierten" Schleifen.

Compiler sagt dieser Grund zurückzuführen ist '501':

Induktionsvariable ist nicht lokal; oder die obere Grenze ist nicht schleifeninvariant.

ich nicht bekommen, was los ist ...

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); 
+1

Es scheint, dass der Compiler den Iteratortyp nicht durchsehen kann. Versuchen Sie, Ihre bereichsbasierte 'for'-Emulation mit' & v [0] 'und' & v [0] + v.size() 'zu verwenden, um diesen Verdacht zu bestätigen. –

+0

@ DietmarKühl Wenn ich es richtig verstanden habe, habe ich versucht: \t \t für (auto __begin = & Zahlen [0], \t \t __end = & Zahlen [0] + numbers.size(); \t \t __begin = __end; +! + __ beginnen) { \t \t auto && ref = * __ beginnen; \t \t summe + = ref; \t} Aber dies auch vektorisieren. – ThreeStarProgrammer57

+3

Wenn die Version, die Zeiger verwendet, die Schleife vektorisiert, verwirrte eindeutig der Iterator, der den Zeiger wickelt, den Compiler: der Typ, der von 'std :: vector :: begin()' zurückgegeben wird, muss nicht 'T *' (oder 'T sein const * '). Es scheint, dass der Compiler nicht erkennen kann, dass dieser Iterator nichts weiter als ein dünner Wrapper über einen Zeiger ist. –

Antwort

1

Meine Vermutung könnte sein, dass die bereichsbasierte for-Schleifen weiß nicht ohne Weiteres, dass das Objekt ein Vektor oder ein Array oder ein verknüpfte Liste, daher weiß der Compiler vorher nicht, dass er die Schleife vektorisiert. Bereichsbasierte for-Schleifen sind äquivalent zur foreach-Schleife in anderen Sprachen. Es könnte eine Möglichkeit geben, den Compiler anzudeuten, dass die Schleife zuvor mit einem Makro oder einer Pragma- oder einer Compiler-Einstellung vektorisiert wird. Um das zu überprüfen, versuchen Sie bitte, den Code in anderen compliers zu benutzen und zu sehen, was Sie erhalten, würde ich nicht überrascht sein, wenn Sie nicht-vektorisierten Zusammenstellungscode mit den anderen compliers bekommen.

+0

Hast du den Code auf anderen Compliern getestet und die Ergebnisse überprüft? –