Para tratar de poner más claramente (con suerte),
mem_fence()
espera hasta que todas las lecturas/escrituras a la memoria local y/o global hecha por el elemento de trabajo llamando antes de mem_fence() son visibles para todos los hilos en el grupo de trabajo.
que proviene de: http://developer.download.nvidia.com/presentations/2009/SIGGRAPH/asia/3_OpenCL_Programming.pdf
operaciones de memoria se pueden reordenar para que se adapte al dispositivo que se están ejecutando en. La especificación establece (básicamente) que cualquier reordenación de las operaciones de memoria debe garantizar que la memoria esté en un estado constante dentro de un único elemento de trabajo. Sin embargo, ¿qué sucede si (por ejemplo) realiza una operación de tienda y el valor decide vivir en un caché específico de un elemento de trabajo por ahora hasta que se presente un tiempo mejor para escribir en la memoria local/global? Si intenta cargar desde esa memoria, el elemento de trabajo que escribió el valor lo tiene en su caché, por lo que no hay problema. Pero otros elementos de trabajo dentro del grupo de trabajo no lo hacen, por lo que pueden leer el valor incorrecto. Colocar una valla de memoria garantiza que, en el momento de la llamada a la valla de memoria, la memoria local/global (según los parámetros) se hará coherente (cualquier caché se vacíe, y cualquier reordenamiento tendrá en cuenta que usted espera que otros hilos puedan necesidad de acceder a estos datos después de este punto).
Admito que todavía es confuso, y no juraré que mi comprensión es 100% correcta, pero creo que es al menos la idea general.
Seguimiento:
me encontré con este enlace que habla sobre las cercas de memoria CUDA, pero la misma idea general se aplica a OpenCL:
http://developer.download.nvidia.com/compute/cuda/2_3/toolkit/docs/NVIDIA_CUDA_Programming_Guide_2.3.pdf
Comprobar la sección de memoria B.5 Funciones de valla.
Tienen un ejemplo de código que calcula la suma de una matriz de números en una llamada. El código está configurado para calcular una suma parcial en cada grupo de trabajo. Luego, si hay más suma que hacer, el código tiene el último grupo de trabajo que hace el trabajo.
Por lo tanto, básicamente se hacen 2 cosas en cada grupo de trabajo: Una suma parcial, que actualiza una variable global, luego el incremento atómico de una variable global de contador.
Después de eso, si queda trabajo por hacer, el grupo de trabajo que incrementó el contador al valor de ("tamaño de grupo de trabajo" - 1) se considera el último grupo de trabajo. Ese grupo de trabajo continúa para terminar.
Ahora, el problema (como lo explican) es que, debido a la reordenación de la memoria y/o el almacenamiento en caché, el contador puede aumentar y el último grupo de trabajo puede comenzar a hacer su trabajo antes de esa suma parcial global variable ha tenido su valor más reciente escrito en la memoria global.
Una valla de memoria asegurará que el valor de esa variable de suma parcial sea consistente para todos los hilos antes de pasar la valla.
Espero que esto tenga algún sentido. Es confuso.
Esta presentación proporciona un ejemplo para vallas de memoria: previene e. gramo. un reordenamiento de '' '' shared_var = value; lock = false; '' '' (https://people.maths.ox.ac.uk/gilesm/cuda/new_lectures/lec3.pdf) Para un solo elemento de trabajo aislado, este reordenamiento no importaría, porque para el trabajo individual parece que no hay ninguna dependencia entre estas variables => la consistencia requerida se da dentro del elemento de trabajo. Además, este artículo demostró ser útil: https://en.wikipedia.org/wiki/Memory_barrier. –