programar - opencl vs opengl
Barreras en OpenCL (2)
En OpenCL, entiendo que puede usar la función barrier()
para sincronizar hilos en un grupo de trabajo. Yo (generalmente) entiendo para qué sirven y cuándo usarlos. También soy consciente de que todos los hilos en un grupo de trabajo deben golpear la barrera, de lo contrario hay problemas. Sin embargo, cada vez que he intentado usar barreras hasta ahora, parece que mi controlador de video falla o un mensaje de error sobre el acceso a memoria no válida de algún tipo. He visto esto en 2 tarjetas de video diferentes hasta ahora (1 ATI, 1 NVIDIA).
Entonces, mis preguntas son:
- Alguna idea de por qué esto pasaría?
- ¿Cuál es la diferencia entre
barrier(CLK_LOCAL_MEM_FENCE)
ybarrier(CLK_GLOBAL_MEM_FENCE)
? Leí la documentación, pero no estaba claro para mí. - ¿Hay una regla general sobre cuándo usar la
barrier(CLK_LOCAL_MEM_FENCE)
frente a labarrier(CLK_GLOBAL_MEM_FENCE)
? - ¿Hay alguna vez que llamar a la
barrier()
con el tipo de parámetro incorrecto pueda causar un error?
Como ha indicado, las barreras solo pueden sincronizar hilos en el mismo grupo de trabajo . No hay manera de sincronizar diferentes grupos de trabajo en un kernel.
Ahora, para responder a su pregunta, la especificación tampoco me quedó clara, pero me parece que la sección 6.11.9 contiene la respuesta:
CLK_LOCAL_MEM_FENCE: la función de barrera eliminará todas las variables almacenadas en la memoria local o pondrá en cola una cerca de memoria para garantizar el orden correcto de las operaciones de la memoria en la memoria local.
CLK_GLOBAL_MEM_FENCE: la función de barrera pondrá en cola una cerca de memoria para garantizar el orden correcto de las operaciones de memoria en la memoria global. Esto puede ser útil cuando los elementos de trabajo, por ejemplo, escriben en un búfer o en objetos de memoria de imagen y luego desean leer los datos actualizados.
Entonces, a mi entender, debes usar CLK_LOCAL_MEM_FENCE al escribir y leer en el espacio de la memoria __local
, y CLK_GLOBAL_MEM_FENCE al escribir y leer en el espacio de la memoria __global
.
No he probado si esto es más lento, pero la mayoría de las veces, cuando necesito una barrera y tengo dudas sobre qué espacio de memoria se ve afectado, simplemente uso una combinación de los dos, es decir:
barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);
De esta manera, no debería tener ningún problema de orden de escritura / lectura de memoria (siempre que esté seguro de que todos los hilos del grupo atraviesan la barrera, pero es consciente de ello).
Espero eso ayude.
Reviviendo un hilo viejo-ish aquí. He tenido un poco de problemas con la barrera () yo mismo.
Con respecto a su problema de choque, una posible causa podría ser si su barrera está dentro de una condición. Leí que cuando usa la barrera, TODOS los elementos de trabajo en el grupo deben poder llegar a esa instrucción, o de lo contrario, colgará su núcleo, lo que generalmente resulta en una falla.
if(someCondition){
//do stuff
barrier(CLK_LOCAL_MEM_FENCE);
//more stuff
}else{
//other stuff
}
Entiendo que si uno o más elementos de trabajo satisfacen alguna condición, TODOS los elementos de trabajo deben cumplir esa condición, o habrá algunos que saltarán la barrera. Las barreras esperan hasta que TODOS los elementos de trabajo alcancen ese punto. Para arreglar el código anterior, necesito reestructurarlo un poco:
if(someCondition){
//do stuff
}
barrier(CLK_LOCAL_MEM_FENCE);
if(someCondition){
//more stuff
}else{
//other stuff
}
Ahora todos los elementos de trabajo llegarán a la barrera.
No sé hasta qué punto esto se aplica a los bucles; si un elemento de trabajo se rompe de un bucle for, ¿golpea las barreras? No estoy seguro
ACTUALIZACIÓN: He bloqueado con éxito algunos programas ocl con una barrera en un bucle for. Asegúrese de que todos los elementos de trabajo salgan del bucle for al mismo tiempo, o mejor aún, coloque la barrera fuera del bucle.
(fuente: computación heterogénea con OpenCL Capítulo 5, p90-91)