Domanda

Qualcuno ha approfittato della vettorializzazione automatica che gcc può fare? Nel mondo reale (al contrario del codice di esempio)? Ci vuole una ristrutturazione del codice esistente per trarne vantaggio? Esiste un numero significativo di casi in qualsiasi codice di produzione che può essere vettorizzato in questo modo?

È stato utile?

Soluzione

Devo ancora vedere GCC o Intel C ++ vettorializzare automaticamente qualsiasi cosa tranne i loop molto semplici, anche quando mi viene dato il codice degli algoritmi che possono (e sono stati, dopo averli riscritti manualmente usando i intrinseci SSE) essere vettorizzati.

Parte di questo è essere conservativa - specialmente di fronte a un possibile aliasing del puntatore, può essere molto difficile per un compilatore C / C ++ "dimostrare" a se stesso che una vettorializzazione sarebbe sicura, anche se tu come programmatore sai che è. La maggior parte dei compilatori (ragionevolmente) preferisce non ottimizzare il codice piuttosto che rischiare di non compilarlo. Questa è un'area in cui i linguaggi di livello superiore hanno un reale vantaggio rispetto a C, almeno in teoria (dico in teoria poiché non sono effettivamente a conoscenza di alcun compilatore ML o Haskell che vettorializza automaticamente).

Un'altra parte sono semplicemente i limiti analitici - la maggior parte delle ricerche nel campo della vettorializzazione, ho capito, è legata all'ottimizzazione dei problemi numerici classici (fluidodinamica, diciamo) che era il pane e il burro della maggior parte delle macchine vettoriali prima di qualche anno fa (quando , tra CUDA / OpenCL, Altivec / SSE e STI Cell, la programmazione vettoriale in varie forme è diventata ampiamente disponibile nei sistemi commerciali).

È abbastanza improbabile che il codice scritto per un processore scalare in mente sia facile da vettorializzare per un compilatore. Fortunatamente, molte cose che puoi fare per rendere più facile a un compilatore capire come vettorializzarlo, come il loop tiling e lo srotolamento parziale del loop, anche (tendono a) aiutare le prestazioni sui processori moderni anche se il compilatore non riesce a capire come vettorializzarlo.

Altri suggerimenti

È difficile da usare in qualsiasi logica aziendale, ma aumenta la velocità quando si elaborano volumi di dati allo stesso modo.

Un buon esempio è l'elaborazione audio / video in cui si applica la stessa operazione a ogni campione / pixel. Ho usato VisualDSP per questo, e hai dovuto controllare i risultati dopo la compilazione - se è davvero usato dove dovrebbe.

La vettorializzazione sarà utile principalmente per i programmi numerici. I programmi vettorializzati possono essere eseguiti più rapidamente su processori vettoriali come il processore di celle STI utilizzato nelle console di gioco PS3. Lì, i calcoli numerici utilizzati, ad esempio, nel rendering della grafica del gioco possono essere accelerati molto mediante la vettorializzazione. Tali processori sono chiamati processori SIMD (Single Instruction Multiple Data).

Su altri processori la vettorializzazione non verrà utilizzata. I programmi vettorializzati vengono eseguiti su un set di istruzioni vettorializzato che non sarà applicabile a un processore non SIMD.

La serie di processori Intel Nehalem (rilasciata alla fine del 2008) implementa le istruzioni SSE 4.2, che sono istruzioni SIMD. Fonte: wikipedia .

Le istruzioni vettorializzate non si limitano ai processori Cell - la maggior parte delle CPU moderne come le workstation le hanno (PPC, x86 dal pentium 3, Sparc, ecc ...). Se usato bene per operazioni in virgola mobile, può essere di grande aiuto per attività molto complesse (filtri, ecc ...). Nella mia esperienza, la vettorializzazione automatica non funziona così bene.

Forse avrai notato che quasi nessuno in realtà sa come fare buon uso della vettorializzazione automatica di GCC. Se cerchi nel Web per vedere i commenti delle persone, ti viene sempre l'idea che GCC ti consente di abilitare la vettorializzazione automatica, ma molto raramente ne fa un uso effettivo, quindi se desideri utilizzare l'accelerazione SIMD (ad es. MMX, SSE, AVX, NEON, AltiVec), quindi devi praticamente capire come scriverlo usando i valori intrinseci del compilatore o il codice del linguaggio Assembly.

Ma il problema con gli intrinseci è che devi effettivamente comprendere il lato del linguaggio Assembly e quindi anche imparare il metodo Intrinsics per descrivere ciò che vuoi, il che probabilmente risulterà in un codice molto meno efficiente rispetto a se lo scrivessi in Codice assembly (come ad esempio un fattore 10x), perché il compilatore avrà ancora problemi a fare buon uso delle istruzioni intrinseche!

Ad esempio, potresti utilizzare SIMD Intrinsics in modo che molte operazioni possano essere eseguite contemporaneamente in parallelo, ma il tuo compilatore probabilmente genererà il codice Assembly che trasferisce i dati tra i registri SIMD e i normali registri della CPU e viceversa, rendere efficace il tuo codice SIMD a una velocità simile (o anche più lenta) del normale codice!

Quindi sostanzialmente:

  • Se vuoi accelerazioni fino al 100% (2x velocità), quindi acquistare il compilatori ufficiali Intel / ARM o convertire parte del codice in modo da utilizzare SIMD C / C ++ Intrinsics.
  • Se tu vuoi accelerazioni del 1000% (velocità 10x), quindi scriverlo nel codice assembly usando le istruzioni SIMD a mano. Oppure, se disponibile sul tuo hardware, utilizza invece l'accelerazione GPU come OpenCL o CUDA SDK di Nvidia, poiché possono fornire accelerazioni simili nella GPU come SIMD fa nella CPU.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top