ventajas ultima son que nucleos funciones cuda gpgpu nvidia warp-scheduler

ultima - nvidia cuda wiki



¿Cómo se CUDA bloquea/distorsiona/subraya el mapa en núcleos CUDA? (2)

"E. Si una urdimbre contiene 20 hilos, pero actualmente solo hay 16 núcleos disponibles, la urdimbre no se ejecutará".

Es incorrecto. Está confundiendo núcleos en su sentido habitual (también utilizado en CPU): la cantidad de "multiprocesadores" en una GPU, con núcleos en nVIDIA marketing ("nuestra tarjeta tiene miles de núcleos CUDA").

Una urdimbre en sí misma solo se puede programar en un único núcleo (= multiprocesador), y puede ejecutar hasta 32 subprocesos al mismo tiempo; no puede usar más de un solo núcleo.

El número "48 warps" es el número máximo de warps activos (warps que pueden elegirse para programarse para el trabajo en el ciclo siguiente, en cualquier ciclo dado) por multiprocesador, en nVIDIA GPU con Compute Capability 2.x; y este número corresponde a 1536 = 48 x 32 hilos.

Respuesta basada en este seminario web

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 de la universidad), por lo que no es mi preocupación alcanzar el máximo rendimiento.

Antes que nada, me gustaría entender si entendí bien estos hechos:

  1. El programador escribe un kernel y organiza su ejecución en una grilla de bloques de hilos.

  2. Cada bloque está asignado a un multiprocesador de transmisión (SM). Una vez asignado, no puede migrar a otro SM.

  3. Cada SM divide sus propios bloques en Warps (actualmente con un tamaño máximo de 32 hilos). Todos los hilos en una urdimbre se ejecutan simultáneamente en los recursos de la SM.

  4. La ejecución real de un hilo es realizada por los núcleos CUDA contenidos en el SM. No hay una asignación específica entre hilos y núcleos.

  5. Si una urdimbre contiene 20 hilos, pero actualmente solo hay 16 núcleos disponibles, la urdimbre no se ejecutará.

  6. Por otro lado, si un bloque contiene 48 hilos, se dividirá en 2 warps y se ejecutarán en paralelo siempre que haya suficiente memoria disponible.

  7. Si un subproceso comienza en un núcleo, luego se detiene para acceder 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 por lo que 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 requiera más registros que los disponibles en cada SM, imaginé diferentes enfoques:

  1. Creo 8 bloques de 48 hilos cada uno, de modo que cada SM tenga 1 bloque para ejecutar. En este caso, ¿los 48 hilos se ejecutarán en paralelo en el SM (explotando los 48 núcleos disponibles para ellos)?

  2. ¿Hay alguna diferencia si lanzo 64 bloques de 6 hilos? (Suponiendo que se mapearán de manera uniforme entre los SM)

  3. Si "sumerjo" la GPU en el trabajo programado (creando 1024 bloques de 1024 subprocesos cada uno, por ejemplo) es razonable suponer que todos los núcleos se usarán en un cierto punto, y se realizarán los mismos cálculos (suponiendo que los subprocesos nunca te detengas)?

  4. ¿Hay alguna manera de verificar estas situaciones usando el generador de perfiles?

  5. ¿Hay alguna referencia para esto? Leí la guía de programación de CUDA y los capítulos dedicados a la arquitectura de hardware en "Programación de procesadores masivamente paralelos" y "Diseño y desarrollo de aplicaciones CUDA"; pero no pude obtener una respuesta precisa.


Dos de las mejores referencias son

  1. Informe técnico de NVIDIA Fermi Compute Architecture
  2. GF104 Comentarios

Trataré de responder cada una de tus preguntas.

El programador divide trabajo en hilos, hilos en bloques de hilos y bloques de hilo en cuadrículas. El distribuidor de trabajo de cómputo asigna bloques de hilos a los multiprocesadores de transmisión (SM). Una vez que se distribuye un bloque de subprocesos a un SM, se asignan los recursos para el bloque de subprocesos (warps y memoria compartida) y los subprocesos se dividen en grupos de 32 subprocesos llamados warps. Una vez que se asigna un warp, se llama warp activo. Los dos planificadores de warp eligen dos warps activos por ciclo y envían warps a las unidades de ejecución. Para obtener más detalles sobre las unidades de ejecución y el despacho de instrucciones, consulte 1 p.7-10 y 2 .

4 '' . Existe un mapeo entre laneid (índice de hilos en una urdimbre) y un núcleo.

5 '' . Si un warp contiene menos de 32 hilos, en la mayoría de los casos se ejecutará de la misma manera que si tuviera 32 hilos. Warps puede tener menos de 32 subprocesos activos por varias razones: el número de subprocesos por bloque no es divisible por 32, el programa ejecuta un bloque divergente para que los subprocesos que no tomaron la ruta actual se marquen como inactivos o se salga un subproceso de la distorsión.

6 '' . Un bloque de hilos se dividirá en WarpsPerBlock = (ThreadsPerBlock + WarpSize - 1) / WarpSize. No es necesario que los planificadores de warp seleccionen dos warps del mismo bloque de hilos.

7 '' . Una unidad de ejecución no se parará en una operación de memoria. Si un recurso no está disponible cuando una instrucción está lista para ser despachada, la instrucción se enviará de nuevo en el futuro cuando el recurso esté disponible. Los Warps pueden estancarse en barreras, en operaciones de memoria, operaciones de textura, dependencias de datos, ... Un warp estancado no es elegible para ser seleccionado por el planificador warp. En Fermi es útil tener al menos 2 urdimbres elegibles por ciclo para que el planificador de warp pueda emitir una instrucción.

Ver referencia 2 para las diferencias entre un GTX480 y GTX560.

Si lees el material de referencia (unos minutos), creo que encontrarás que tu objetivo no tiene sentido. Intentaré responder a tus puntos.

1 '' . Si ejecuta kernel <<< 8, 48 >>> obtendrá 8 bloques cada uno con 2 warps de 32 y 16 hilos. No hay garantía de que estos 8 bloques se asignarán a SM diferentes. Si se asignan 2 bloques a un SM, es posible que cada planificador de warp pueda seleccionar un warp y ejecutar el warp. Solo usarás 32 de los 48 núcleos.

2 '' . Hay una gran diferencia entre 8 bloques de 48 hilos y 64 bloques de 6 hilos. Supongamos que su núcleo no tiene divergencia y cada hilo ejecuta 10 instrucciones.

  • 8 bloques con 48 hilos = 16 urdimbres * 10 instrucciones = 160 instrucciones
  • 64 bloques con 6 hilos = 64 urdimbres * 10 instrucciones = 640 instrucciones

Para obtener una eficiencia óptima, la división del trabajo debe ser en múltiplos de 32 subprocesos. El hardware no fusionará los hilos de diferentes urdimbres.

3 '' . Un GTX560 puede tener 8 bloques SM * 8 = 64 bloques a la vez u 8 SM * 48 warps = 512 warps si el núcleo no alcanza el máximo de registros o memoria compartida. En cualquier momento dado, una parte del trabajo estará activo en SM. Cada SM tiene múltiples unidades de ejecución (más que núcleos CUDA). Qué recursos están en uso en un momento dado depende de los programadores warp y la combinación de instrucciones de la aplicación. Si no realiza operaciones TEX, las unidades TEX estarán inactivas. Si no realiza una operación especial de punto flotante, las unidades SUFU estarán inactivas.

4 '' . Parallel Nsight y el programa Visual Profiler

a. ejecutado IPC

segundo. emitido IPC

do. urdimbres activas por ciclo activo

re. urdimbres elegibles por ciclo activo (solo Nsight)

mi. razones de warp stall (solo Nsight)

F. hilos activos por instrucción ejecutada

El generador de perfiles no muestra el porcentaje de utilización de ninguna de las unidades de ejecución. Para GTX560, una estimación aproximada sería IssuedIPC / MaxIPC. Para MaxIPC suponga que GF100 (GTX480) es 2 GF10x (GTX560) es 4 pero el objetivo es 3 es un objetivo mejor.