cuda - equiv - ¿Qué desenrolla#pragma exactamente? ¿Afecta el número de hilos?
http equiv expires (1)
No. Significa que ha llamado a un kernel CUDA con un bloque y que un bloque tiene 100 hilos activos. Estás pasando tamaño como el segundo parámetro de función a tu kernel. En su kernel, cada uno de esos 100 hilos ejecuta el ciclo for 100 veces.
#pragma unroll
es una optimización del compilador que puede, por ejemplo, reemplazar un fragmento de código como
for ( int i = 0; i < 5; i++ )
b[i] = i;
con
b[0] = 0;
b[1] = 1;
b[2] = 2;
b[3] = 3;
b[4] = 4;
poniendo la directiva #pragma unroll
justo antes del ciclo. Lo bueno de la versión desenrollada es que implica menos carga de procesamiento para el procesador. En el caso de la versión for
loop, el procesamiento, además de asignar cada i
a b[i]
, implica i
inicialización, evaluando i<5
por 6 veces e incrementando i
por 5 veces. Mientras que en el segundo caso, solo implica la recopilación de contenido de matriz b
(quizás más int i=5;
si se usa más adelante). Otro beneficio del desenrollado de bucles es la mejora del Paralelismo de Nivel de Instrucción (ILP). En la versión desenrollada, posiblemente habría más operaciones para que el procesador ingrese a la tubería de procesamiento sin preocuparse por la condición de bucle for
en cada iteración.
Publicaciones como esta explican que el desenrollado del bucle en tiempo de ejecución no puede suceder para CUDA. En su caso, el compilador CUDA no tiene ninguna pista de que el size
va a ser 100, por lo que no se producirá el desenrollado del bucle en tiempo de compilación, por lo que si fuerza el desenrollado, puede terminar perjudicando el rendimiento.
Si está seguro de que el size
es 100 para todas las ejecuciones, puede desenrollar su ciclo de la siguiente manera:
#pragma unroll
for(int i=0;i<SIZE;i++) //or simply for(int i=0;i<100;i++)
b[i]=i;
en el que se conoce SIZE
en tiempo de compilación con #define SIZE 100
.
También sugiero que tengas una comprobación correcta de errores CUDA en tu código (se explica aquí ).
Soy nuevo en CUDA, y no puedo entender cómo se desenrolla el bucle. He escrito un fragmento de código para entender la técnica
__global__ void kernel(float *b, int size)
{
int tid = blockDim.x * blockIdx.x + threadIdx.x;
#pragma unroll
for(int i=0;i<size;i++)
b[i]=i;
}
Arriba está mi función kernel. En main
lo llamo abajo
int main()
{
float * a; //host array
float * b; //device array
int size=100;
a=(float*)malloc(size*sizeof(float));
cudaMalloc((float**)&b,size);
cudaMemcpy(b, a, size, cudaMemcpyHostToDevice);
kernel<<<1,size>>>(b,size); //size=100
cudaMemcpy(a, b, size, cudaMemcpyDeviceToHost);
for(int i=0;i<size;i++)
cout<<a[i]<<"/t";
_getch();
return 0;
}
¿Significa que tengo size
* size
= 10000 hilos ejecutándose para ejecutar el programa? ¿Se crean 100 de ellos cuando se desenrolla el bucle?