He estado usando CUDA durante algunas semanas, pero tengo algunas dudas sobre la asignación de bloques / warps / thread. Estoy estudiando la arquitectura desde un punto de vista didáctico (proyecto universitario), por lo que alcanzar mi máximo rendimiento no es mi preocupación.
En primer lugar, me gustaría entender si entendí bien estos hechos:
El programador escribe un núcleo y organiza su ejecución en una cuadrícula de bloques de hilos.
Cada bloque se asigna a un Multiprocesador de transmisión (SM). Una vez asignado, no puede migrar a otro SM.
Cada SM divide sus propios bloques en Warps (actualmente con un tamaño máximo de 32 hilos). Todos los hilos de una urdimbre se ejecutan simultáneamente en los recursos del SM.
La ejecución real de un hilo es realizada por los núcleos CUDA contenidos en el SM. No existe un mapeo específico entre hilos y núcleos.
Si un warp contiene 20 hilos, pero actualmente solo hay 16 núcleos disponibles, el warp no se ejecutará.
Por otro lado, si un bloque contiene 48 hilos, se dividirá en 2 urdimbres y se ejecutarán en paralelo siempre que haya suficiente memoria disponible.
Si un subproceso se inicia en un núcleo, se detiene para el acceso a la memoria o para una operación de coma flotante larga, su ejecución podría reanudarse en un núcleo diferente.
¿Son correctas?
Ahora, tengo una GeForce 560 Ti, de acuerdo con las especificaciones, está equipada con 8 SM, cada una con 48 núcleos CUDA (384 núcleos en total).
Mi objetivo es asegurarme de que cada núcleo de la arquitectura ejecute las MISMAS instrucciones. Suponiendo que mi código no requerirá más registros que los disponibles en cada SM, imaginé diferentes enfoques:
Creo 8 bloques de 48 hilos cada uno, para que cada SM tenga 1 bloque para ejecutar. En este caso, ¿se ejecutarán los 48 hilos en paralelo en el SM (explotando todos los 48 núcleos disponibles para ellos)?
¿Hay alguna diferencia si ejecuto 64 bloques de 6 hilos? (Suponiendo que se asignarán de manera uniforme entre los SM)
Si "sumerjo" la GPU en el trabajo programado (creando 1024 bloques de 1024 hilos cada uno, por ejemplo), es razonable suponer que todos los núcleos se usarán en un cierto punto y realizarán los mismos cálculos (suponiendo que los hilos nunca pararse)?
¿Hay alguna forma de verificar estas situaciones con el generador de perfiles?
¿Hay alguna referencia para estas cosas? Leí la guía de programación CUDA y los capítulos dedicados a la arquitectura de hardware en "Programación de procesadores paralelos masivos" y "Diseño y desarrollo de aplicaciones CUDA"; pero no pude obtener una respuesta precisa.