2011-04-13 19 views
15

Soy nuevo en CUDA y necesito ayuda para entender algunas cosas. Necesito ayuda para paralelizar estos dos bucles. Específicamente, cómo configurar el dimBlock y dimGrid para hacer que esta ejecución sea más rápida. Sé que esto parece el ejemplo de agregar vectores en el SDK, pero ese ejemplo es solo para matrices cuadradas y cuando intento modificar ese código para mi matriz de 128 x 1024, no funciona correctamente.CUDA cómo obtener cuadrícula, bloque, tamaño de hilo y paralizar cálculo de matriz no cuadrada

__global__ void mAdd(float* A, float* B, float* C) 
{ 
    for(int i = 0; i < 128; i++) 
    { 
     for(int i = 0; i < 1024; i++) 
     { 
      C[i * 1024 + j] = A[i * 1024 + j] + B[i * 1024 + j]; 
     } 
    } 
} 

Este código es parte de un circuito más grande y es la parte más sencilla del código, así que decidí tratar de paralleize tia y aprender CUDA al mismo tiempo. He leído las guías pero todavía no entiendo cómo obtener el no apropiado. de grids/block/threads en marcha y usarlos de manera efectiva.

+5

En [pycuda] (http://mathema.tician.de/software/pycuda) es simplemente 'C [i] = A [i] + B [i]' [demo.py] (https://gist.github.com/916835) – jfs

+2

(fuera del tema) Actualmente tiene i como índice para ambos bucles (olvidó la j). –

Respuesta

31

Como lo ha escrito, ese kernel es completamente serial. Cada hilo lanzado para ejecutarlo va a realizar el mismo trabajo.

La idea principal detrás de CUDA (y OpenCL y otros modelos similares de programación de "datos únicos, múltiples programas") es que realiza una operación "paralela a datos", por lo que debe realizarse la misma operación, en gran parte independiente. muchas veces, y escriba un núcleo que realice esa operación. A continuación, se inicia una gran cantidad de subprocesos (semi) autónomos para realizar esa operación en el conjunto de datos de entrada.

En su ejemplo Además matriz, la operación de datos en paralelo es

C[k] = A[k] + B[k]; 

para todo k entre 0 y 128 * 1024. Cada operación de suma es completamente independiente y no tiene los requisitos del pedido, y por lo tanto puede ser realizada por un hilo diferente Para expresar esto en CUDA, uno podría escribir el núcleo de esta manera:

__global__ void mAdd(float* A, float* B, float* C, int n) 
{ 
    int k = threadIdx.x + blockIdx.x * blockDim.x; 

    if (k < n) 
     C[k] = A[k] + B[k]; 
} 

[exención de responsabilidad: código escrito en el navegador, no han sido evaluados, utilice el riesgo propio]

Aquí, el bucle interior y exterior de la el código de serie se reemplaza por un hilo CUDA por operación, y he agregado una verificación de límite en el código para que, en los casos en que se inicien más hilos que las operaciones requeridas, no se produzca un desbordamiento del búfer. Si el núcleo se lanzó entonces así:

const int n = 128 * 1024; 
int blocksize = 512; // value usually chosen by tuning and hardware constraints 
int nblocks = n/nthreads; // value determine by block size and total work 

madd<<<nblocks,blocksize>>>mAdd(A,B,C,n); 

Entonces 256 bloques, conteniendo cada uno 512 hilos se pondrá en marcha en el hardware GPU para realizar la operación de adición de matriz en paralelo. Tenga en cuenta que si el tamaño de los datos de entrada no se podía expresar como un bonito redondeo múltiple del tamaño del bloque, la cantidad de bloques debería redondearse hacia arriba para cubrir el conjunto completo de datos de entrada.

Todo lo anterior es una visión general muy simplificada del paradigma CUDA para una operación muy trivial, pero tal vez le da suficiente información para que usted pueda continuar. CUDA es bastante maduro en estos días y hay una gran cantidad de material educativo bueno y gratuito flotando en la web que probablemente pueda utilizar para iluminar aún más muchos de los aspectos del modelo de programación que he pasado por alto en esta respuesta.

+0

Gracias talonmies. Esto realmente me ayudó a entender el tamaño del bloque y la cuadrícula. Toda esa lectura que he estado haciendo de repente tiene sentido. – user656210

+0

int k = threadIdx.x + gridDim.x * blockDim.x; Esto seguramente es incorrecto? gridDim.x * blockDim.x en tu ejemplo siempre será 256 * 512. Debería ser int k = threadIdx.x + blockIdx.x * blockDim.x; Traté de editarlo pero fue rechazado. – Ozone

+0

@Ozone: Sí, eso fue un error tipográfico, gracias por señalarlo. – talonmies

Cuestiones relacionadas