2011-01-14 4 views
7

Sto cercando di capire se un determinato problema è un buon candidato per l'utilizzo di CUDA per mettere il problema su una GPU.Le GPU sono buone per il filtro delle immagini basato sul caso?

Sto essenzialmente facendo un filtro a riquadri che cambia in base a qualche rilevamento dei bordi. Quindi ci sono fondamentalmente 8 casi che sono testati per ogni pixel, e poi il resto delle operazioni si verificano - calcoli medi tipici e così via. La presenza di queste istruzioni switch nel mio ciclo causerà il problema di essere un cattivo candidato per accedere alla GPU?

Non sono davvero sicuro di come evitare le istruzioni switch, perché questo rilevamento dei bordi deve avvenire ad ogni pixel. Suppongo che l'intera immagine possa separare la parte di rilevamento dei bordi dall'algoritmo di elaborazione e che sia possibile memorizzare un buffer corrispondente al filtro da utilizzare per ciascun pixel, ma sembra che aggiungerebbe molto pre-elaborazione all'algoritmo .

Edit: solo per dare un po 'di contesto - questo algoritmo è già stato scritto, e OpenMP è stato usato per fare un buon effetto a velocizzarlo. Tuttavia, gli 8 core della mia scatola di sviluppo sono impalliditi rispetto ai 512 della GPU.

+0

se con "pales" si intende nei numeri grezzi, questo non è necessariamente vero, poiché molti dei commentatori in questo thread hanno spiegato che la programmazione per la GPU richiede un diverso tipo di pensiero. questo perché, anche se è un cavallo di battaglia, è adatto solo per determinati compiti. :) –

+0

se si ha accesso a una scheda basata su Fermi da nVidia, provatelo e portate la parte del codice in cui vi sono hotspot. potresti anche voler esaminare il tuo codice se non lo hai già fatto, per vedere qual è il vero collo di bottiglia. altrimenti la soluzione migliore è riscriverla in modo che non si ramifichi. –

risposta

0

L'utilizzo di una GPU per l'elaborazione può spesso essere contro-intuitivo; le cose che sono ovviamente inefficienti se fatte nel normale codice seriale, sono in realtà il modo migliore per farlo in parallelo usando la GPU.

Lo pseudo-codice qui sotto sembra inefficiente (in quanto calcola 8 valori filtrati per ogni pixel), ma verrà eseguito in modo efficiente su una GPU:


# Compute the 8 possible filtered values for each pixel 
for i = 1...8 
    # filter[i] is the box filter that you want to apply 
    # to pixels of the i'th edge-type 
    result[i] = GPU_RunBoxFilter(filter[i], Image) 

# Compute the edge type of each pixel 
# This is the value you would normally use to 'switch' with 
edge_type = GPU_ComputeEdgeType(Image) 

# Setup an empty result image 
final_result = zeros(sizeof(Image)) 
# For each possible switch value, replace all pixels of that edge-type 
# with its corresponding filtered value 
for i = 1..8 
    final_result = GPU_ReplacePixelIfTrue(final_result, result[i], edge_type==i) 

Speriamo che aiuta!

+0

sto leggendo questo diritto - che stai dicendo di calcolare fondamentalmente tutti questi filtri prima del tempo per l'intera immagine, lo stesso con il tipo di bordo? – Derek

+0

si. Sembra uno spreco di calcolo, poiché normalmente si dovrebbe calcolare solo un "valore filtrato" per pixel e qui si calcolano 8 valori, ma si evita la ramificazione. – Ciaran

1

Il rilevamento dei bordi, i calcoli medi e la correlazione incrociata possono essere implementati come curve 2D. Convoluzioni possono essere implementate su GPU in modo molto efficace (speed-up > 10, up to 100 rispetto alla CPU), in particolare per i grossi kernel. Quindi sì, potrebbe avere senso riscrivere il filtro delle immagini sulla GPU.

Anche se non utilizzerei GPU come piattaforma di sviluppo per tale metodo.

+0

ho aggiunto il contesto di soem: ne abbiamo già eseguito e parallelizzato in qualche modo con OpenMP – Derek

1

in genere, a meno che non si sia sulla nuova architettura CUDA, si vorrà evitare la ramificazione. Poiché le GPU sono fondamentalmente macchine SIMD, la pipeline è estremamente permeabile e soffre tremendamente di stallo di gasdotti a causa di una errata previsione dei rami.

se si pensa che ci siano vantaggi significativi da ottenere utilizzando una GPU, fare alcuni parametri preliminari per avere un'idea approssimativa.

se vuoi imparare un po 'su come scrivere codice senza branching, vai su http://cellperformance.beyond3d.com/ e dai uno sguardo.

ulteriormente, indagando in esecuzione di questo problema su più core della CPU potrebbe anche essere la pena, nel qual caso probabilmente si vuole prendere in considerazione sia OpenCL o le librerie di prestazioni Intel (come TBB)

un'altra Go alla sorgente per problemi destinate alla GPU che si tratti di grafica, geometria computazionale o in altro modo, è IDAV, l'Istituto di analisi dei dati e la visualizzazione: http://idav.ucdavis.edu

0

Yep, flusso di controllo di solito ha penalizzazione delle prestazioni su GPU, sia esso se di/switch' es/ternary operator, perché con le operazioni del flusso di controllo la GPU non può eseguire i thread in modo ottimale.Quindi le solite tattiche sono evitare la ramificazione possibile. In alcuni casi, gli IF possono essere sostituiti da una formula, in cui le condizioni IF vengono mappate ai coefficienti della formula. Ma la soluzione/ottimizzazione concreta dipende dal concreto kernel della GPU ... Forse puoi mostrare il codice esatto, da analizzare ulteriormente dalla community di StackOverflow.

EDIT: Solo nel caso siate interessati qui è convolution pixel shader che ho scritto.

+0

esaminerò il codice che mostra. A questo punto potrebbe essere troppo proprietario per rilasciare il codice interessante – Derek

+0

. :) –

1

La ramificazione non è poi così male, se c'è una coerenza spaziale nella ramificazione. In altre parole, se si prevedono blocchi di pixel l'uno accanto all'altro nell'immagine per passare attraverso lo stesso ramo, l'impatto sulle prestazioni è ridotto al minimo.

+0

questo è vero per i nuovi processori Nvidia; Non sei sicuro di AMD/ATi? –

+0

inoltre, dato che il problema è il rilevamento dei bordi, i percorsi di esecuzione divergenti si verificherebbero ovviamente attorno ai bordi, sebbene questo impatto sulle prestazioni possa essere insignificante a seconda della geometria dell'immagine –