expires equiv control cache cuda nvidia pragma loop-unrolling

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?