Me pongo lo que blockDim es, pero tengo un problema con gridDim. Blockdim da el tamaño del bloque, pero lo que es gridDim? En Internet se dice gridDim.x da el número de bloques en la coordenada x.

¿Cómo puedo saber qué blockDim.x * gridDim.x da?

¿Cómo puedo saber cuántos gridDim.x valores hay en la x de la línea?

Por ejemplo, considere el siguiente código:

int tid = threadIdx.x + blockIdx.x * blockDim.x;
double temp = a[tid];
tid += blockDim.x * gridDim.x;

while (tid < count)
{
    if (a[tid] > temp)
    {
       temp = a[tid];
    }
    tid += blockDim.x * gridDim.x;
}

Sé que tid comienza con 0. A continuación, el código ha tid+=blockDim.x * gridDim.x. ¿Qué es tid ahora, después de esta operación?

InformationsquelleAutor ehah | 2013-05-17

3 Comentarios

  1. 81
    • blockDim.x,y,z da el número de hilos en un bloque, en el
      dirección particular
    • gridDim.x,y,z da el número de bloques en una cuadrícula, en la
      dirección particular
    • blockDim.x * gridDim.x da el número de hilos en una cuadrícula (en la dirección x, en este caso)

    bloque de cuadrícula y de las variables pueden ser de 1, 2 o 3 dimensiones. Es una práctica común que cuando manejo 1-D datos para crear sólo 1-D bloques y cuadrículas.

    En el CUDA documentación, estas variables se definen aquí

    En particular, cuando el total de los hilos en el x-dimensión (gridDim.x*blockDim.x) es menos de el tamaño de la matriz deseo proceso, entonces es una práctica común para crear un bucle y tienen la cuadrícula de hilos que mueven a través de toda la matriz. En este caso, tras la tramitación de un bucle de iteración, cada hilo debe, a continuación, pasar a la siguiente sin procesar ubicación, que está dada por tid+=blockDim.x*gridDim.x; En efecto, la totalidad de la red de hilos está saltando a través de la 1-D de la matriz de datos, una red de ancho en un momento. En este tema, a veces llamado un «grid-anda loop», se analiza con más profundidad en este artículo de blog.

    Usted puede ser que desee considerar tomar un par de introducción CUDA webinars disponibles en el NVIDIA página webinar. Por ejemplo, estos 2:

    • La GPU usando CUDA C – Una Introducción (2010), introducción
      a los fundamentos de la GPU usando CUDA C. Conceptos serán
      ilustrado con tutoriales de ejemplos de código. No antes de la GPU
      se requiere experiencia
    • La GPU usando CUDA C – Avanzado 1 (2010) Primer nivel
      las técnicas de optimización global de optimización de memoria, y
      la utilización del procesador. Los conceptos se ilustran con código real
      ejemplos

    Serían 2 horas bien gastado, si usted quiere entender estos conceptos que mejor.

    El tema general de la red a grandes zancadas de bucles está cubierto en detalle aquí.

    • Yo diría que su respuesta es la mejor, +1
    • Yo estaba en el proceso de simplemente añadir un par de comentarios a su respuesta cuando se ha eliminado. (Después se re-publicado, supongo.) Se fueron en primer lugar, y su respuesta es buena.
    • Sí accidentalmente había publicado en la mitad del camino a través de la escritura (ups)
  2. 46

    Parafraseado de la Guía de Programación de CUDA:

    gridDim: Esta variable contiene las dimensiones de la cuadrícula.

    blockIdx: Esta variable contiene el índice del bloque dentro de la cuadrícula.

    blockDim: Esta variable y contiene las dimensiones del bloque.

    threadIdx: Esta variable contiene el hilo índice dentro del bloque.

    Usted parece ser un poco confundido acerca de la rosca jerarquía que CUDA ha; en pocas palabras, para un kernel habrá 1 cuadrícula (que yo siempre visualizar como un 3-dimensional del cubo). Cada uno de sus elementos es un bloque, de tal manera que una cuadrícula declarado como dim3 grid(10, 10, 2); habría 10*10*2 total de bloques. A su vez, cada bloque es de un 3-dimensional del cubo de hilos.

    Con la que, dijo, es común utilizar solo el x-dimensión de los bloques y las redes, que es lo que se ve el código en tu pregunta está haciendo. Esto es especialmente revlevant si estás trabajando con 1D matrices. En ese caso, su tid+=blockDim.x * gridDim.x línea, sería en efecto el único índice de cada hilo dentro de su red. Esto es debido a que su blockDim.x sería el tamaño de cada bloque, y su gridDim.x sería el número total de bloques.

    Así que si usted lanza un kernel con los parámetros de

    dim3 block_dim(128,1,1);
    dim3 grid_dim(10,1,1);
    kernel<<<grid_dim,block_dim>>>(...);

    a continuación, en su núcleo había threadIdx.x + blockIdx.x*blockDim.x que efectivamente tiene:

    threadIdx.x range from [0 ~ 128)

    blockIdx.x range from [0 ~ 10)

    blockDim.x equal to 128

    gridDim.x equal to 10

    Por lo tanto, en el cálculo de threadIdx.x + blockIdx.x*blockDim.x, tendría valores dentro del rango definido por: [0, 128) + 128 * [1, 10), lo que significaría su tid valores que van desde {0, 1, 2, …, 1279}.
    Esto es útil para cuando se desea asignar hilos de tareas, ya que esto proporciona un identificador único para todos los hilos en su núcleo.

    Sin embargo, si usted tiene

    int tid = threadIdx.x + blockIdx.x * blockDim.x;
    tid += blockDim.x * gridDim.x;

    entonces usted va a tener fundamentalmente: tid = [0, 128) + 128 * [1, 10) + (128 * 10), y su tid valores de rango de {1280, 1281, …, 2559}
    No estoy seguro de que eso sería relevante, pero todo depende de su aplicación y cómo asignar los hilos a sus datos. Esta asignación es bastante central para cualquier núcleo de lanzamiento, y tú eres el que determina cómo debe hacerse. Cuando se inicia el kernel especificar la cuadrícula y el bloque de dimensiones, y tú eres el que tiene que hacer cumplir la asignación a sus datos dentro de su núcleo. Siempre y cuando no excedan de sus límites de hardware (para las modernas tarjetas, usted puede tener un máximo de 2^10 hilos por bloque y 2^16 – 1 bloques por cuadrícula)

    • El ejemplo concreto fue muy útil, muchas gracias. Muchas personas simplemente repetir las definiciones de gridDim, blockIdx, etc., pero el ejemplo es de vital importancia.
    • Disculpe señor, pero, al final de la frase que usted dijo usted puede tener un máximo de 2^10 hilos por bloque y 2^16 – 1 bloques por hilo, pero no debería ser: usted puede tener un máximo de 2^10 hilos por bloque y 2^16 – 1 bloques por cuadrícula
  3. 1

    En este código fuente, incluso tenemos 4 threds, el núcleo de la función puede acceder a todos los de 10 matrices. Cómo?

    #define N 10 //(33*1024)
    
    __global__ void add(int *c){
        int tid = threadIdx.x + blockIdx.x * gridDim.x;
    
        if(tid < N)
            c[tid] = 1;
    
        while( tid < N)
        {
            c[tid] = 1;
            tid += blockDim.x * gridDim.x;
        }
    }
    
    int main(void)
    {
        int c[N];
        int *dev_c;
        cudaMalloc( (void**)&dev_c, N*sizeof(int) );
    
        for(int i=0; i<N; ++i)
        {
            c[i] = -1;
        }
    
        cudaMemcpy(dev_c, c, N*sizeof(int), cudaMemcpyHostToDevice);
    
        add<<< 2, 2>>>(dev_c);
        cudaMemcpy(c, dev_c, N*sizeof(int), cudaMemcpyDeviceToHost );
    
        for(int i=0; i< N; ++i)
        {
            printf("c[%d] = %d \n" ,i, c[i] );
        }
    
        cudaFree( dev_c );
    }

    ¿Por qué no creamos 10 hilos ex) add<<<2,5>>> or add<5,2>>>
    Porque tenemos que crear razonablemente pequeño número de hilos, si N es mayor que 10 para ex) 33*1024.

    Este código fuente es un ejemplo de este caso.
    las matrices son de 10, cuda hilos son 4.
    Cómo acceder a todos los 10 matrices de sólo 4 hilos.

    véase la página sobre el significado de threadIdx, blockIdx, blockDim, gridDim en el cuda detalle.

    En este código fuente,

    gridDim.x : 2    this means number of block of x
    
    gridDim.y : 1    this means number of block of y
    
    blockDim.x : 2   this means number of thread of x in a block
    
    blockDim.y : 1   this means number of thread of y in a block

    Nuestro número de hilo son 4, porque 2*2(bloques * hilo).

    En agregar núcleo de la función, podemos acceder a 0, 1, 2, 3 índice de hilo

    ->tid = threadIdx.x + blockIdx.x * blockDim.x

    ①0+0*2=0

    ②1+0*2=1

    ③0+1*2=2

    ④1+1*2=3

    Cómo acceder resto de índice 4, 5, 6, 7, 8, 9.
    Hay un cálculo en bucle while

    tid += blockDim.x + gridDim.x in while

    * * * la primera llamada de kernel **

    -1 bucle: 0+2*2=4

    -2 bucle: 4+2*2=8

    -3 bucle: 8+2*2=12 ( pero este valor es false, mientras que los de fuera!)

    ** segunda llamada de kernel **

    -1 bucle: 1+2*2=5

    -2 bucle: 5+2*2=9

    -3 bucle: 9+2*2=13 ( pero este valor es false, mientras que los de fuera!)

    ** tercera convocatoria de kernel **

    -1 bucle: 2+2*2=6

    -2 bucle: 6+2*2=10 ( pero este valor es false, mientras que los de fuera!)

    ** cuarta convocatoria de kernel **

    -1 bucle: 3+2*2=7

    -2 bucle: 7+2*2=11 ( pero este valor es false, mientras que los de fuera!)

    Así, todos los índices de 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 se puede acceder por el valor tid.

    consulte esta página.
    http://study.marearts.com/2015/03/to-process-all-arrays-by-reasonably.html
    No puedo subir la imagen, debido a la baja reputación.

Dejar respuesta

Please enter your comment!
Please enter your name here