2011-07-13 14 views
7

Tengo alguna pregunta sobre cómo las GPU realizan sincronizaciones. Como sé, cuando una urdimbre encuentra una barrera (suponiendo que esté en OpenCL), y sabe que las otras urdimbres del mismo grupo todavía no han llegado. Entonces tiene que esperar. ¿Pero qué hace exactamente ese warp durante el tiempo de espera? ¿Sigue siendo un warp activo? ¿O hará algún tipo de operaciones nulas?Sincronizaciones en GPU

Como noté, cuando tenemos una sincronización en el kernel, el número de instrucciones aumenta. Me pregunto cuál es la fuente de este incremento. ¿La sincronización está desglosada en muchas instrucciones más pequeñas de la GPU? O porque las urdimbres ociosas realizan algunas instrucciones adicionales?

Y finalmente, me pregunto si el costo agregado por una sincronización, comparado con uno sin sincronización, (digamos barrera (CLK_LOCAL_MEM_FENCE)) se ve afectado por el número de warp en un grupo de trabajo (o threadblock)? Gracias

Respuesta

7

Un warp activo es uno que reside en el SM, es decir, todos los recursos (registros, etc.) han sido asignados y el Warp está disponible para su ejecución siempre que sea programable. Si una urdimbre alcanza una barrera antes de otras distorsiones en el mismo subproceso/grupo de trabajo, seguirá activa (todavía es residente en el SM y todos sus registros siguen siendo válidos), pero no ejecutará ninguna instrucción ya que es no está listo para ser programado.

Insertar una barrera no solo bloquea la ejecución sino que también actúa como una barrera para el compilador: el compilador no puede realizar la mayoría de las optimizaciones a través de la barrera ya que esto puede invalidar el propósito de la barrera. Esta es la razón más probable por la que está viendo más instrucciones: sin la barrera, el compilador puede realizar más optimizaciones.

El costo de una barrera depende mucho de lo que esté haciendo su código, pero cada barrera presenta una burbuja donde todas las urdimbres deben permanecer inactivas antes de que comiencen a funcionar nuevamente, de modo que si tiene un bloque de hilos muy grande/work-group entonces, por supuesto, existe una burbuja potencialmente más grande que con un bloque pequeño. El impacto de la burbuja depende de su código: si su código está muy ligado a la memoria, la barrera expondrá las latencias de memoria donde antes podrían haberse ocultado, pero si está más equilibrado, puede tener un efecto menos notorio.

Esto significa que en un kernel con mucha memoria puede ser mejor lanzar un mayor número de bloques más pequeños para que otros bloques se puedan ejecutar cuando un bloque está burbujeando en una barrera. Debería asegurarse de que su ocupación aumente como resultado, y si está compartiendo datos entre subprocesos utilizando la memoria compartida en bloque, entonces se tendrá una compensación.

+0

Gracias por la respuesta detallada. Sería bueno si pudieras compartir algunos documentos de los que obtuvieras el conocimiento. Me gustaría citar en mi investigación. ¿Podría explicarnos más por qué los núcleos vinculados a la memoria exponen latencias de memoria? Según entiendo ahora, una solicitud de memoria cerca de una sincronización (aparece antes de la sincronización) que se supone que está oculta por algún cálculo se detendrá hasta que lleguen los datos. ¿Es correcto? Por otro lado, si kernel no está vinculado a la memoria, ¿qué expone una sincronización? ¿Latencia de la tubería de instrucción? (Se supone que no hay divergencias, y sí, ¿qué hace todo esto con las divergencias?) – Zk1001