caching - simétrico - sistemas de multiples procesadores
CUDA-Multiprocesadores, tamaño de deformación e hilos máximos por bloque: ¿Cuál es la relación exacta? (1)
Sé que hay multiprocesadores en una GPU CUDA que contienen núcleos CUDA en ellos. En mi lugar de trabajo, estoy trabajando con una GTX 590, que contiene 512 núcleos CUDA, 16 multiprocesadores y que tiene un tamaño de deformación de 32. Así que esto significa que hay 32 núcleos CUDA en cada multiprocesador que funciona exactamente en el mismo código en la misma deformación . Y, finalmente, el máximo de hilos por tamaño de bloque es 1024.
Mi pregunta es cómo se relacionan exactamente el tamaño de bloque y el recuento de multiprocesador - tamaño de deformación. Permítame decirle que entiendo la situación: por ejemplo, asigno N bloques con el tamaño máximo de threadPerBlock de 1024 en la GTX 590. Por lo que entiendo de la guía de programación de CUDA y de otras fuentes, los bloques primero son enumerados por el hardware . En este caso 16 de los N bloques están asignados a diferentes multiprocesadores. Cada bloque contiene 1024 subprocesos y el programador de hardware asigna 32 de estos subprocesos a los 32 núcleos en un solo multiprocesador. Los hilos en el mismo multiprocesador (warp) procesan la misma línea del código y utilizan la memoria compartida del multiprocesador actual. Si los 32 subprocesos actuales encuentran una operación fuera del chip como las lecturas y escrituras en la memoria, se reemplazan con otro grupo de 32 subprocesos del bloque actual. Por lo tanto, en realidad hay 32 subprocesos en un solo bloque que se ejecutan exactamente en paralelo en un multiprocesador en un momento dado, no en la totalidad del 1024. Finalmente, si un multiprocesador procesa un bloque completamente, un nuevo bloque de subprocesos del La lista de N bloques de subprocesos está conectada al multiprocesador actual. Y, finalmente, hay un total de 512 subprocesos que se ejecutan en paralelo en la GPU durante la ejecución del kernel CUDA. (Sé que si un bloque usa más registros que los disponibles en un solo multiprocesador, entonces se divide para funcionar en dos multiprocesadores, pero supongamos que cada bloque puede caber en un solo multiprocesador en nuestro caso).
Entonces, ¿es correcto mi modelo de ejecución paralela de CUDA? Si no, ¿qué está mal o falta? Quiero ajustar el proyecto actual en el que estoy trabajando, por lo que necesito el modelo de trabajo más correcto de todo.
En mi lugar de trabajo, estoy trabajando con una GTX 590, que contiene 512 núcleos CUDA, 16 multiprocesadores y que tiene un tamaño de deformación de 32. Así que esto significa que hay 32 núcleos CUDA en cada multiprocesador que funciona exactamente en el mismo código en la misma deformación . Y, finalmente, el máximo de hilos por tamaño de bloque es 1024.
Un GTX590 contiene 2 veces los números que mencionó, ya que hay 2 GPU en la tarjeta. A continuación, me enfoco en un solo chip.
Permítame decirle que entiendo la situación: por ejemplo, asigno N bloques con el tamaño máximo de threadPerBlock de 1024 en la GTX 590. Por lo que entiendo de la guía de programación de CUDA y de otras fuentes, los bloques primero son enumerados por el hardware . En este caso 16 de los N bloques están asignados a diferentes multiprocesadores.
Los bloques no están necesariamente distribuidos uniformemente entre los multiprocesadores (SM). Si programa exactamente 16 bloques, algunos de los SM pueden obtener 2 o 3 bloques, mientras que algunos de ellos quedan inactivos. No se por que
Cada bloque contiene 1024 subprocesos y el programador de hardware asigna 32 de estos subprocesos a los 32 núcleos en un solo multiprocesador.
La relación entre hilos y núcleos no es tan directa. Hay 32 ALU "básicas" en cada SM. Los que manejan cosas como el punto flotante de precisión simple y la mayoría de las instrucciones lógicas y de enteros de 32 bits. Pero solo hay 16 unidades de carga / almacenamiento, por lo que si la instrucción de deformación que se está procesando actualmente es una carga / almacén, debe programarse dos veces. Y solo hay 4 unidades de funciones especiales, que hacen cosas como la trigonometría. Así que estas instrucciones deben ser programadas 32/4 = 8 veces.
Los hilos en el mismo multiprocesador (warp) procesan la misma línea del código y utilizan la memoria compartida del multiprocesador actual.
No, puede haber muchos más de 32 subprocesos "en vuelo" al mismo tiempo en un solo SM.
Si los 32 subprocesos actuales encuentran una operación fuera del chip como las lecturas y escrituras en la memoria, se reemplazan con otro grupo de 32 subprocesos del bloque actual. Por lo tanto, en realidad hay 32 subprocesos en un solo bloque que se ejecutan exactamente en paralelo en un multiprocesador en un momento dado, no la totalidad de los 1024.
No, no son solo las operaciones de memoria las que hacen que se reemplacen las deformaciones. Las ALU también están profundamente canalizadas, por lo que se intercambiarán nuevas deformaciones a medida que se produzcan dependencias de datos para los valores que aún se encuentran en la tubería. Entonces, si el código contiene dos instrucciones donde la segunda usa la salida de la primera, la deformación se pondrá en espera mientras que el valor de la primera instrucción se abrirá paso a través de la tubería.
Finalmente, si un multiprocesador procesa completamente un bloque, un nuevo bloque de subprocesos de la lista de N bloques de subprocesos se conecta al multiprocesador actual.
Un multiprocesador puede procesar más de un bloque a la vez, pero un bloque no puede moverse a otro MP una vez que se haya iniciado el procesamiento. El número de subprocesos en un bloque que están actualmente en vuelo depende de cuántos recursos utiliza el bloque. La Calculadora de ocupación de CUDA le indicará cuántos bloques estarán en vuelo al mismo tiempo, en función del uso de recursos de su núcleo específico.
Y, finalmente, hay un total de 512 subprocesos que se ejecutan en paralelo en la GPU durante la ejecución del kernel CUDA. (Sé que si un bloque usa más registros que los disponibles en un solo multiprocesador, entonces se divide para funcionar en dos multiprocesadores, pero supongamos que cada bloque puede caber en un solo multiprocesador en nuestro caso).
No, un bloque no se puede dividir para trabajar en dos multiprocesadores. Un bloque completo siempre es procesado por un único multiprocesador. Si el multiprocesador dado no tiene suficientes recursos para procesar al menos un bloque con su kernel, obtendrá un error de inicio del kernel y su programa no se ejecutará en absoluto.
Depende de cómo se define un subproceso como "en ejecución". La GPU normalmente tendrá muchos más de 512 subprocesos que consumen varios recursos en el chip al mismo tiempo.
Vea la respuesta de @ harrism en esta pregunta: CUDA: ¿Cuántos hilos concurrentes en total?