2014-11-15 4 views
10

Prima di sostituire un sacco del mio "vecchio" per i cicli con la gamma a base di cicli for, mi sono imbattuto qualche test con Visual Studio 2013:VC++ non è più vectorize semplice per i cicli con la sintassi gamma basata

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

guardando lo smontaggio, standard per i cicli erano tutti vettorizzati:

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

ma gamma base per i cicli non erano:

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

C'è qualche ragione per cui il compilatore non ha potuto vettorializzare questi loop?

Mi piacerebbe davvero usare la nuova sintassi, ma perdere la vettorizzazione è troppo brutto.

ho appena visto this question, così ho provato la bandiera /Qvec-report:2, dando un altro motivo:

loop not vectorized due to reason '1200' 

che è:

loop contiene dipendenze di dati di loop-effettuata che impediscono vettorializzazione. Diverse iterazioni di il loop interferiscono tra loro in modo tale che la vettorizzazione del loop produce risposte sbagliate, e l'auto-vettore non può dimostrare a se stesso che non ci sono tali dipendenze dei dati.

È lo stesso bug? (Ho anche provato con l'ultimo compilatore vC++ "Nov 2013 CTP")

Devo segnalarlo anche su MS connect?

modificare

Du ai commenti, ho fatto lo stesso test con un int serie cruda, invece di un vettore, in modo da nessuna classe iteratore è coinvolto, a soli puntatori prime.

Ora tutti i loop sono vettorizzati tranne i due cicli "simulati in base alla gamma".

compilatore dice che questo è dovuto al motivo '501':

variabile induzione non è locale; o il limite superiore non è invariante del ciclo.

Non capisco cosa sta succedendo ...

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

Sembra che il compilatore non riesca a visualizzare il tipo di iteratore. Prova a usare l'emulazione 'for' basata su intervallo usando' & v [0] 'e' & v [0] + v.size() 'per confermare questo sospetto. –

+0

@ DietmarKühl Se ho capito bene, ho provato: \t \t per (auto __begin = e numeri [0], \t \t __end = & numeri [0] + numbers.size(); \t \t __begin = __end; +! + __ inizio) { \t \t auto && ref = * __ inizio; \t \t somma + = rif; \t} Ma questo anche vettorializzare. – ThreeStarProgrammer57

+3

Se la versione che utilizza i puntatori vettorializza il ciclo, chiaramente l'iteratore che avvolge il puntatore sconvolge il compilatore: il tipo restituito da 'std :: vector :: begin()' non deve essere 'T *' (o 'T const * '). Sembra che il compilatore non possa rilevare che questo iteratore non è altro che un involucro sottile sopra un puntatore. –

risposta

1

mia ipotesi potrebbe essere che la gamma-based per i cicli non estemporaneo sanno che l'oggetto è un vettore o di una matrice o di un lista collegata quindi il compilatore non sa in anticipo vettorizza il ciclo. I loop basati su range sono l'equivalente del ciclo foreach in altre lingue. Potrebbe esserci un modo per suggerire al compilatore di suggerire prima di vettorizzare il ciclo usando una macro o un pragma o un'impostazione del compilatore. Per controllare, prova ad usare il codice in altri compilatori e guarda cosa ottieni Non sarei sorpreso se ricevessi codice di assemblaggio non-vettorizzato con gli altri comporter.

+0

hai testato il codice su altri costruttori e controllato i risultati? –

Problemi correlati