Why is writing to shared variables of compute shader incoherent memory access?

Viewed 94

I have searched and read some wiki about incoherent memory access, such as https://en.wikipedia.org/wiki/Memory_coherence , https://www.khronos.org/opengl/wiki/Memory_Model

To my knowledge, the main cause of incoherent memory access is multiple local caches of same memory address. In cache memory architecture, the processor usually does not directly access memory but instead cache. For multi-processor system, each processor has its own cache but shares one memory, which may result multiple copies of same memory address. Therefore, one processor may read the old data of a memory address even after another process writes to this address.

However, shared variable should be located in cache and can only be accessed by the invocation within same workgroup which is executed on same processor. Thus there should not exist multiple versions of shared variable. Even when the size of shared variable exceeds the maximal size of cache, part of data would be in memory, the shared variable only exists in one cache. Why access to shared variable is incoherent?

Also, is accessing to coherent image/buffer variable by invocations within a workgroup incoherent?

supplement

To my understanding, there are two kinds of barriers in compute shader.

  • barrier function of glsl, which is used to control the execution of shader codes and makes sure that the preceding write operation is truely happened before the posterior read operation.
  • memory barriers are used to ensure the data of write operation visible to furture read operation. These types of memory barrier are set up for incoherent memory access. Also, in my understanding, incoherent memory access means the values written by a shader invocation not are necessarily visible to other invocation even when the read operation happens after write operation. The memory barriers are used to handle to this situation.

What I really want to ask is that regarding to invocations of one workgroup, could incoherent memory access I just described happens for shared, buffer or image variables? In other words, regarding to invocations of one workgroup, if I use barrier to make sure the read operation happens after the write operation, is the written value visible to read operation?

To my way of thinking, the written value is always visible to posterior read operation in the case above. Because, one workgroup only executes on one compute unit, thus no multiple caches exist for same memory address. But I am not sure about that.

1 Answers

Workgroup size limits are often many times larger than the wavefront/warp size of an actual execution unit. The point of collecting invocations into work groups is to be able to have them share information and have execution barriers between them.

If a workgroup is larger than an invocation subgroup (or if there is execution divergence due to divergent conditional execution), shared memory still needs to work. If the wavefront size is 32, but you have a workgroup size of 128, how can invocation number 97 read data written by invocation 2 when they're in different wavefronts?

An implementation could execute them sequentially on the same compute unit. Execute the first 32 invocations, then the next, etc. This would keep all shared memory in local storage, but how do you read data written by another invocation? You need an execution barrier so that the implementation knows to stop executing the current 32 and move to the next wavefront within the workgroup. Memory accesses are incoherent because you cannot know which invocations have even executed writes without an explicit barrier.

Any means of serial execution of such work groups would mean that shared memory has to be shared between different compute units. And that means caches.

Related