La comprensión de CUDA dimensiones de la rejilla, las dimensiones del bloque y la organización hilos (explicación simple) [cerrado]

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

  •  25-09-2019
  •  | 
  •  

Pregunta

¿Cómo están organizadas las discusiones a ser ejecutadas por una GPU?

¿Fue útil?

Solución

Hardware

Si un dispositivo GPU tiene, por ejemplo, 4 unidades de multiprocesamiento, y se puede ejecutar 768 hilos de cada una: a continuación, en un momento dado no más de 4 * 768 hilos se ejecutan verdaderamente en paralelo (si lo planeado más hilos, que estará esperando su turno).

software

hilos están organizados en bloques. Un bloque es ejecutado por una unidad de multiprocesamiento. Los hilos de un bloque pueden indentified (indexado) usando 1Dimension (x), 2Dimensions (x, y) o índices 3DIM (x, y, z), pero en cualquier caso x y z <= 768 para nuestro ejemplo (otras restricciones se aplican a x, y, z, consulte la guía y su capacidad de dispositivo).

Obviamente, si necesita más de los 4 * 768 hilos que necesita más de 4 bloques. Los bloques pueden ser indexados también 1D, 2D o 3D. Hay una fila de bloques de espera para entrar la GPU (porque, en nuestro ejemplo, la GPU tiene 4 multiprocesadores y sólo 4 cuadras son siendo ejecutado simultáneamente).

Ahora un caso sencillo: el procesamiento de una imagen de 512x512

Supongamos que queremos un hilo para procesar un píxel (i, j).

puede utilizar bloques de 64 hilos cada uno. Entonces necesitamos 512 * 512 = 4096/64 bloques (Por así tener 512x512 threads = 4,096 * 64)

Es común para organizar (para hacer la indexación de la imagen más fácil) los hilos en bloques en 2D que tienen blockDim = 8 x 8 (el 64 hilos por bloque). Yo prefiero llamarlo threadsPerBlock.

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

y 2D gridDim = 64 x 64 bloques (los bloques 4096 sea necesario). Yo prefiero llamarlo numBlocks.

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

El núcleo se puso en marcha la siguiente manera:

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

Por último:. No será algo así como "una cola de 4096 bloques", donde un bloque está esperando a ser asignado a uno de los multiprocesadores de la GPU para conseguir sus 64 hilos ejecutados

En el núcleo del píxel (i, j) para ser procesado por un hilo se calcula de esta manera:

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

Otros consejos

suponga una GPU 9800: 14 multiprocesadores, cada uno tiene 8 threadprocessors y warpsize es 32 lo que significa cada uno de los mangos threadprocessor hasta 32 hilos. 14 * 8 * 32 = 3584 es el número máximo de actuallos hilos cuncurrent.

si se ejecuta este núcleo con más de 3584 hilos (hilos decir 4000 y que no es importante cómo se defina el bloque y la rejilla de GPU será tratarlos como iguales.):

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

a continuación, el orden de ejecución de estas dos funciones son las siguientes:

1.func1 se ejecuta para los primeros 3584 hilos

2.func2 se ejecuta para los primeros 3584 hilos

3.func1 se ejecuta para los restantes hilos

4.func2 se ejecuta para los restantes hilos

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top