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);
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. –
@ 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
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. –