Comprensione CUDA dimensioni griglia, dimensioni del blocco e organizzazione fili (semplice spiegazione) [chiuso]

StackOverflow https://stackoverflow.com/questions/2392250

  •  25-09-2019
  •  | 
  •  

Domanda

Come sono le discussioni organizzate per essere eseguiti da una GPU?

È stato utile?

Soluzione

Hardware

Se un dispositivo GPU ha, per esempio, 4 unità multiprocessing, e possono funzionare 768 thread ciascuno: quindi in un dato momento non più di 4 * 768 discussioni saranno davvero in esecuzione in parallelo (se avete programmato più thread, che sarà attesa del loro turno).

Software

le discussioni sono organizzati in blocchi. Un blocco viene eseguito da un'unità di elaborazione multipla. I fili di un blocco può essere identificato (indicizzato) utilizzando 1Dimension (x), 2Dimensions (x, y) o indici 3DIM (x, y, z), ma in ogni caso x y z <= 768 per il nostro esempio (altre restrizioni ad x, y, z, consultare la guida e la vostra capacità del dispositivo).

Ovviamente, se avete bisogno di più di quelli di 4 * 768 discussioni è necessario più di 4 blocchi. I blocchi possono essere indicizzati 1D, 2D o 3D. C'è una fila di blocchi in attesa di entrare GPU (perché, nel nostro esempio, la GPU ha 4 multiprocessori e solo 4 blocchi sono in esecuzione simultaneamente).

Ora un semplice caso: l'elaborazione di un immagine 512x512

Supponiamo di voler un thread per elaborare un pixel (i, j).

Possiamo usare blocchi di 64 fili ciascuno. Poi abbiamo bisogno di 512 * 512/64 = 4096 blocchi (In modo da avere 512x512 thread = 4096 * 64)

E 'comune per organizzare (per rendere indicizzare l'immagine più facile) i fili di blocchi 2D aventi blockDim = 8 x 8 (64 fili per blocco). Io preferisco chiamarla threadsPerBlock.

dim3 threadsPerBlock(8, 8);  // 64 threads

e 2D gridDim = 64 x 64 blocchi (i 4096 blocchi necessari). Io preferisco chiamarla numBlocks.

dim3 numBlocks(imageWidth/threadsPerBlock.x,  /* for instance 512/8 = 64*/
              imageHeight/threadsPerBlock.y); 

Il kernel è lanciato in questo modo:

myKernel <<<numBlocks,threadsPerBlock>>>( /* params for the kernel function */ );       

Infine:. Ci sarà qualcosa come "una coda di 4096 blocchi", in cui un blocco è in attesa di essere assegnato uno dei multiprocessori della GPU per ottenere il suo 64 thread eseguiti

Nel kernel pixel (i, j) per essere trasformati con un filo viene calcolato in questo modo:

uint i = (blockIdx.x * blockDim.x) + threadIdx.x;
uint j = (blockIdx.y * blockDim.y) + threadIdx.y;

Altri suggerimenti

supporre una GPU 9800GT: 14 multiprocessori, ognuno ha 8 threadprocessors e warpsize è 32 che significa ogni maniglie threadprocessor fino a 32 thread. 14 * 8 * 32 = 3584 è il numero massimo di actuall fili cuncurrent.

se si esegue questo kernel con più di 3584 le discussioni (diciamo 4000 discussioni e non è importante come si definisce il blocco e la griglia GPU li tratterà come lo stesso.):

func1();
__syncthreads();
func2();
__syncthreads();

quindi l'ordine di esecuzione di queste due funzioni sono le seguenti:

1.func1 viene eseguita per i primi 3584 fili

2.func2 viene eseguita per i primi 3584 fili

3.func1 viene eseguito per la fili

restante

4.func2 viene eseguito per la fili

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