CUDA determinar hilos por bloque, bloques por cuadrícula


Soy nuevo en el paradigma CUDA. Mi pregunta es determinar el número de hilos por bloque y bloques por cuadrícula. ¿Un poco de arte y juicio juegan en esto? Lo que he encontrado es que muchos ejemplos tienen un número aparentemente arbitrario elegido para estas cosas.

Estoy considerando un problema en el que sería capaz de pasar matrices - de cualquier tamaño - a un método de multiplicación. De modo que, cada elemento de C (como en C = A * B) sería calculado por un solo hilo. ¿Cómo se determinaría la hilos / bloque, bloques / cuadrícula en este caso?

Author: dnbwise, 2010-12-08

4 answers

En general, desea dimensionar sus bloques/cuadrícula para que coincidan con sus datos y maximizar simultáneamente la ocupación, es decir, cuántos hilos están activos a la vez. Los principales factores que influyen en la ocupación son el uso de memoria compartida, el uso de registros y el tamaño del bloque de subprocesos.

Una GPU habilitada para CUDA tiene su capacidad de procesamiento dividida en SMs (multiprocesadores de streaming), y el número de SMs depende de la tarjeta real, pero aquí nos centraremos en un solo SM para simplificar (todos se comportan same). Cada SM tiene un número finito de registros de 32 bits, memoria compartida, un número máximo de bloques activos Y un número máximo de subprocesos activos. Estos números dependen de la CC (capacidad de cómputo) de su GPU y se pueden encontrar en el centro del artículo de Wikipedia http://en.wikipedia.org/wiki/CUDA .

En primer lugar, el tamaño del bloque de subprocesos siempre debe ser un múltiplo de 32, porque los núcleos emiten instrucciones en urdimbres (32 subprocesos). Por ejemplo, si tiene un tamaño de bloque de 50 subprocesos, la GPU todavía emitirá comandos a 64 subprocesos y solo los estaría desperdiciando.

En segundo lugar, antes de preocuparse por la memoria compartida y los registros, intente dimensionar sus bloques en función del número máximo de subprocesos y bloques que correspondan a la capacidad de cálculo de su tarjeta. A veces hay varias maneras de hacer esto... por ejemplo, una tarjeta CC 3.0 cada SM puede tener 16 bloques activos y 2048 hilos activos. Esto significa que si tiene 128 hilos por bloque, podría caber 16 bloques en tu SM antes de alcanzar el límite de 2048 hilos. Si utiliza 256 hilos, solo puede caber 8, pero todavía está utilizando todos los hilos disponibles y todavía tendrá ocupación completa. Sin embargo, el uso de 64 hilos por bloque solo utilizará 1024 hilos cuando se alcance el límite de 16 bloques, por lo que solo el 50% de ocupación. Si la memoria compartida y el uso de registros no son un cuello de botella, esta debería ser su principal preocupación (aparte de sus dimensiones de datos).

Sobre el tema de su cuadrícula... los bloques en su cuadrícula se extienden hacia fuera sobre el SMs para comenzar, y entonces los bloques restantes se colocan en una tubería. Los bloques se mueven al SMs para procesarlos tan pronto como haya suficientes recursos en ese SM para tomar el bloque. En otras palabras, a medida que los bloques se completan en un SM, se mueven otros nuevos. Podría argumentar que tener bloques más pequeños (128 en lugar de 256 en el ejemplo anterior) puede completarse más rápido ya que un bloque particularmente lento acaparará menos recursos, pero esto depende en gran medida de la codificar.

Con respecto a los registros y la memoria compartida, fíjese en eso a continuación, ya que puede estar limitando su ocupación. La memoria compartida es finita para un SM completo, así que intente usarla en una cantidad que permita que quepan tantos bloques como sea posible en un SM. Lo mismo ocurre con el uso del registro. Una vez más, estos números dependen de la capacidad de cálculo y se pueden encontrar tabulados en la página de wikipedia. ¡Buena suerte!

 72
Author: underpickled,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-16 19:11:13

Http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls

La Calculadora de ocupación CUDA le permite calcular el multiprocesador ocupación de una GPU por un núcleo CUDA dado. La ocupación multiprocesador es la relación entre las deformaciones activas y el número máximo de deformaciones soportadas en un multiprocesador de la GPU. Cada multiprocesador en el dispositivo tiene un conjunto de N registros disponibles para su uso por subprocesos de programa CUDA. Estos registros son un recursos compartidos que se asignan entre los bloques de subprocesos que se ejecutan en un multiprocesador. El compilador CUDA intenta minimizar el uso de registros para maximizar el número de bloques de subprocesos que pueden estar activos en la máquina simultáneamente. Si un programa intenta lanzar un núcleo para el cual los registros usados por hilo multiplican el tamaño del bloque de hilo es mayor que N, el lanzamiento fallará...

 18
Author: jmilloy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-06 11:32:29

Con raras excepciones, debe usar un número constante de subprocesos por bloque. El número de bloques por cuadrícula se determina por el tamaño del problema, como las dimensiones de la matriz en el caso de la multiplicación de matrices.

Elegir el número de hilos por bloque es muy complicado. La mayoría de los algoritmos CUDA admiten una amplia gama de posibilidades, y la elección se basa en lo que hace que el núcleo se ejecute de manera más eficiente. Casi siempre es un múltiplo de 32, y al menos 64, debido a cómo el hardware de programación de subprocesos funciona. Una buena opción para un primer intento es 128 o 256.

 15
Author: Heatsink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-08 19:20:54

También debe considerar la memoria compartida porque los subprocesos en el mismo bloque pueden acceder a la misma memoria compartida. Si estás diseñando algo que requiere mucha memoria compartida, entonces más hilos por bloque podrían ser ventajosos.

Por ejemplo, en términos de cambio de contexto, cualquier múltiplo de 32 funciona igual. Así que para el caso 1D, lanzar 1 bloque con 64 hilos o 2 bloques con 32 hilos cada uno no hace ninguna diferencia para los accesos a la memoria global. Sin embargo, si el problema en cuestión naturalmente se descompone en 1 longitud-64 vector, entonces la primera opción será mejor (menos sobrecarga de memoria, cada hilo puede acceder a la misma memoria compartida) que la segunda.

 3
Author: ely,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-08 20:03:28