Domanda

Sto scrivendo una rete di feed in avanti in VC ++ usando AVX Intrinsics. Sto invocando questo codice tramite Pinvoke in C#. La mia prestazione quando chiama una funzione che calcola un grande ciclo inclusa la funzione exp () è ~ 1000 ms per un loopsize di 160 m. Non appena chiamo qualunque Funzione che utilizza AVX Intrinsics e quindi successivamente usa Exp (), le mie prestazioni scendono a circa ~ 8000 ms per la stessa operazione. Si noti che la funzione che calcola Exp () è standard C e la chiamata che utilizza AVX Intrinsics può essere completamente non correlata in termini di elaborazione dei dati. Una specie di bandiera viene inciampato da qualche parte in fase di esecuzione.

In altre parole,

A(); // 1000ms calculates 160M exp() 
B(); // completely unrelated but contains AVX
A(); // 8000ms

o, curiosamente,

C(); // contains 128 bit SSE SIMD expressions
A(); // 1000ms

Mi sono perso su quale possibile meccanismo sta succedendo qui o su come perseguire un sol'n. Sono su una CPU Intel 2500k Win 7. Express Versions of vs.

Grazie.

È stato utile?

Soluzione

Se si utilizzano istruzioni AVX256, lo "stato superiore AVX" diventa "sporco", che si traduce in una grande stalla se si utilizzano successivamente le istruzioni SSE (incluso il punto mobile scalare eseguito nei registri XMM). Questo è documentato nel manuale di ottimizzazione Intel, che puoi scarica gratis (ed è un must-leggi se stai facendo questo tipo di lavoro):

L'istruzione AVX modifica sempre i bit superiori dei registri YMM e le istruzioni SSE non modificano i bit superiori. Dal punto di vista hardware, i bit superiori della raccolta del registro YMM possono essere considerati in uno dei tre stati:

• Clean: tutti i pezzi superiori di ymm sono zero. Questo è lo stato quando il processore inizia dal ripristino.

• Modificato e salvato nella regione XSAVE Il contenuto dei bit superiori dei registri YMM corrisponde ai dati salvati nella regione di XSAVE. Questo accade quando dopo l'esecuzione di XSAVE/XRSTOR.

• Modificato e non salvato: l'esecuzione di un'istruzione AVX (256 bit o 128 bit) modifica i bit superiori della destinazione YMM.

La penalità di transizione AVX/SSE si applica ogni volta che gli stati del processore vengono "modificati e non salvati". L'uso di Vzeroupper sposta gli stati del processore per "pulire" ed evitare la penalità di transizione.

La tua routine B( ) Dirties lo stato YMM, quindi il codice SSE in A( ) bancarelle. Inserire a VZEROUPPER istruzione tra B e A per evitare il problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top