2010-10-01 11 views
16

Una cosa que no he descubierto y Google no me está ayudando, ¿por qué es posible tener conflictos bancarios con la memoria compartida, pero no en la memoria global? ¿Puede haber conflictos bancarios con los registros?¿Por qué no hay conflictos bancarios en la memoria global para Cuda/OpenCL?

ACTUALIZACIÓN Wow Realmente aprecio las dos respuestas de Tibbit y Grizzly. Sin embargo, parece que solo puedo dar una marca verde a una respuesta. Soy nuevo en el desbordamiento de la pila. Supongo que tengo que elegir una respuesta como la mejor. ¿Puedo hacer algo para agradecerle la respuesta a la que no doy un cheque verde?

+0

Siempre se puede votar por cualquier pregunta o respuesta que desee – Grizzly

+0

Los conflictos bancarios pueden ocurrir en otros niveles de la jerarquía de la memoria, así como en el archivo de registro. Los conflictos de los bancos de memoria compartida pueden afectar significativamente el rendimiento del kernel y son completamente controlables por el desarrollador. Otros tipos de conflictos bancarios tienen un menor impacto en el rendimiento y el desarrollador no puede resolverlos, por lo que no se comunican al desarrollador. –

Respuesta

32

Respuesta corta: No hay conflictos bancarios ni en la memoria global ni en los registros.

Explicación:

La clave para entender por qué es captar la granularidad de las operaciones. Un solo hilo no accede a la memoria global. Los accesos a la memoria global están "fusionados". Como la memoria global es muy lenta, cualquier acceso de los hilos dentro de un bloque se agrupan para hacer la menor cantidad posible de solicitudes a la memoria global.

Se puede acceder a la memoria compartida por subprocesos simultáneamente. Cuando dos hilos intentan acceder a una dirección dentro del mismo banco, esto provoca un conflicto bancario.

No se puede acceder a los registros con ningún hilo, excepto el asignado. Como no puede leer o escribir en mis registros, no puede impedir que acceda a ellos; por lo tanto, no hay conflictos bancarios.

¿Quién puede leer & escribir en la memoria global?

Only blocks. Un solo hilo puede hacer un acceso, pero la transacción se procesará a nivel de bloque (en realidad, el nivel de warp/half warp, pero no estoy tratando de complicarme). Si dos bloques acceden a la misma memoria, no creo que lleve más tiempo y puede acelerarse con la caché L1 en los dispositivos más nuevos, aunque esto no es evidente.

¿Quién puede leer & escribir en la memoria compartida?

Any thread within a given block. Si solo tiene 1 hilo por bloque, no puede haber un conflicto bancario, pero no tendrá un rendimiento razonable. Los conflictos bancarios ocurren porque un bloque se asigna con varios, digamos 512 hilos, y todos compiten por direcciones diferentes dentro del mismo banco (no exactamente la misma dirección). Hay algunas excelentes imágenes de estos conflictos al final de la Guía de programación CUDA C - Figura G2, en la página 167 (en realidad, la página 177 del pdf). Link to version 3.2

¿Quién puede leer & escribir a registros?

Only the specific thread to which it is allocated. Por lo tanto, solo un hilo está accediendo a la vez.

+0

Tenga en cuenta que mi comentario sobre la memoria caché L1 es en realidad una cuestión mía: ¿se producen conflictos bancarios en la memoria caché L1? Como esto se maneja completamente en el hardware, no creo que nos hayan dicho en la documentación más reciente. (Pero la L1 solo está en el hardware 2. * más nuevo, por lo que si no tiene una GPU de Fermi, apúntela). –

22

La existencia o no de conflictos bancarios en un tipo dado de memoria depende obviamente de la estructura de la memoria y, por lo tanto, de su finalidad.

¿Por qué la memoria compartida está diseñada de manera que permite conflictos bancarios?

Eso es relativamente simple, no es fácil diseñar un controlador de memoria que pueda manejar accesos independientes a la misma memoria simultáneamente (demostrado por el hecho de que la mayoría no puede). Entonces, para permitir que cada subproceso de una semirredida acceda a una palabra individualmente dirigida, la memoria se almacena en un banco, con un controlador independiente para cada banco (al menos así es como uno puede pensar en ello, no está seguro del hardware real). Estos bancos están intercalados para hacer que los hilos secuenciales accedan rápidamente a la memoria secuencial. Por lo tanto, cada uno de estos bancos puede manejar una solicitud a la vez idealmente permitiendo ejecuciones concurrentes de todas las solicitudes en la semirred (obviamente este modelo puede sostener mayor ancho de banda debido a la independencia de esos bancos, lo que también es un plus).

¿Qué ocurre con los registros?

Los registros están diseñados para ser accedidos como operandos para instrucciones ALU, lo que significa que deben accederse con muy baja latencia. Por lo tanto, obtienen más transistores/bit para hacer eso posible. No estoy seguro de cómo se accede exactamente a los registros en los procesadores modernos (no es el tipo de información que necesita a menudo y que no es tan fácil de descubrir). Sin embargo, obviamente sería muy poco práctico organizar registros en los bancos (para las arquitecturas más simples, normalmente se ven todos los registros colgados en un gran multiplexor). Entonces no, no habrá conflictos bancarios por registros.

memoria global

En primer lugar la memoria global funciona en una granularidad diferente de memoria compartida a continuación. Se accede a la memoria en bloques de 32, 64 o 128 bytes (para GT200 al menos, para fermi es 128B siempre, pero en caché, AMD es un poco diferente), donde cada vez que quieres algo de un bloque se accede/transfiere todo el bloque. Es por eso que necesita accesos combinados, ya que si cada hilo accede a la memoria de un bloque diferente, debe transferir todos los bloques.

¿Pero quién dice que no hay conflictos bancarios? No estoy completamente seguro de esto, porque no he encontrado ninguna fuente real para soportar esto para el hardware NVIDIA, pero parece lógico: La memoria global se distribuye típicamente a varios chips ram (que se puede verificar fácilmente al mirar una tarjeta gráfica). Tendría sentido, si cada uno de estos chips es como un banco de memoria local, por lo que tendría conflictos bancarios si hay varias solicitudes simultáneas en el mismo banco. Sin embargo, los efectos serían mucho menos pronunciados por una cosa (ya que la mayor parte del tiempo consumido por los accesos de memoria es la latencia para obtener los datos de A a B de todos modos), y no será un efecto noticible "dentro" de un grupo de trabajo (dado que solo se ejecuta una semirred a la vez y si esa semifalta emite más de una solicitud, tiene un acceso de memoria no asociado, por lo que ya está recibiendo un acierto, por lo que es difícil medir los efectos de este conflicto. varios grupos de trabajo intentan acceder al mismo banco. En su situación típica para gpgpu, tiene un gran conjunto de datos en memoria secuencial, por lo que los efectos no deberían ser notorios ya que hay otros grupos de trabajo accediendo a los otros bancos al mismo tiempo, pero Debería ser posible construir situaciones en las que el conjunto de datos se centre solo en unos pocos bancos, lo que generaría un impacto en el ancho de banda (ya que el ancho de banda máximo provendría de la igualdad de distribución del acceso en todos los bancos, por lo que cada banco nly tienen una fracción de ese ancho de banda). Una vez más, no he leído nada para probar esta teoría para el hardware nvidia (principalmente todo se centra en la fusión, que por supuesto es más importante, ya que hace que esto no sea un problema para los conjuntos de datos naturales). Sin embargo, de acuerdo con la guía informática ATI Stream, esta es la situación de las tarjetas Radeon (para 5xxx: los bancos están separados 2kb y usted quiere asegurarse de distribuir sus accesos (es decir, de todos los worgroups simuladamente activos) iguales en todos los bancos), entonces imaginaría que las tarjetas NVidia se comportan de manera similar.

Por supuesto, para la mayoría scenarious la posibilidad de conflictos de banco en la memoria global es un tema que no, por lo que en la práctica se puede decir:

  • reloj de coalescencia cuando se accede a la memoria global
  • reloj de conflictos banco cuando para acceder a la memoria local
  • no hay problemas con los registros de acceso
+0

¡Cuidado también con la partición de camping en la memoria global! – mch

+1

Buscando información sobre la partición de camping, me encontré con esta respuesta. Tiene razón, la memoria global está físicamente dividida en particiones, y algunos patrones de acceso pueden generar conflictos incluso cuando los accesos están fusionados (consulte la documentación sobre el ejemplo de transposición de Matrix en el SDK de CUDA). Sin embargo, en arquitecturas Fermi y, en general, para dispositivos con capacidad de cálculo 2.x, los accesos a la memoria global están almacenados en caché, con un ancho de 32 bytes, y las direcciones son hash, por lo que teóricamente la partición no debería ser un problema. – Auron

+0

¿Estas mejoras en la arquitectura de memoria en la capacidad de cómputo> = 2.0 también reducen el impacto de la partición de campamento para la memoria global * escribe *? –

3

múltiples hilos que accedan al mismo banco no significa necesariamente que hay un banco co nflict. Hay un conflicto si los hilos quieren leer al mismo tiempo desde UNA FILA DIFERENTE dentro del mismo banco.

Cuestiones relacionadas