Does CL_MAP_WRITE_INVALIDATE_REGION permit overlapping kernel execution on the same buffer?
0 reputation · 16 May 2025, 21:17 UTC
0 reputation · 16 May 2025, 21:17 UTC
I am designing a host-side pipeline that maps an OpenCL buffer for writing while previously enqueued kernels may still be running. The specification describes CL_MAP_WRITE_INVALIDATE_REGION as a hint that the entire mapped region will be overwritten, so the implementation may discard prior contents instead of fetching them.
What I cannot pin down is the interaction with concurrent device-side access. The flag seems aimed at avoiding a read-back of stale data, but I cannot find explicit language stating whether a kernel reading or writing an overlapping region during the map is legal, forbidden, or simply undefined. If some vendors treat the flag as a promise of exclusive access and skip coherence work while others preserve consistency, the same code could silently corrupt data on one platform and work on another.
Assume OpenCL 1.2 or later, where this flag exists, and a standard in-order command queue.
My questions:
clEnqueueMapBuffer with CL_MAP_WRITE_INVALIDATE_REGION and concurrently executing kernels that touch the same buffer?CL_TRUE) sufficient to make this safe, or must kernel completion be enforced with events or clFinish regardless?31275 reputation · 17 May 2025, 04:09 UTC
No. CL_MAP_WRITE_INVALIDATE_REGION is a performance hint about host-side intent ("I will overwrite the whole region, so don't bother fetching old contents"), not a synchronization or exclusivity primitive. The OpenCL specification (1.2 onward, where the flag exists) does not grant the host exclusive access to the buffer during a map, and it does not define an ordering between the mapped region and kernels that touch the same buffer. If a kernel reads or writes an overlapping region while the buffer is mapped, the behavior is undefined: one implementation may quietly preserve coherence, another may use the hint to skip coherence work entirely, and your pipeline corrupts data only on the second one.
None beyond the normal command-queue rules. What the spec does guarantee is the usual mapping semantics: the map operation is ordered with respect to previously enqueued commands that use the same memory object, so a map will not observe a buffer state from before prior work on that object. What it does not do is lock the buffer against kernels enqueued later, or make concurrent overlap well-defined. The "invalidate" wording only licenses the implementation to skip reading stale contents into the host mapping; it says nothing about device-side access during the map window.
A blocking map (blocking_map = CL_TRUE) is sufficient only for work already enqueued: it will not return until prior commands affecting the buffer have completed, so previously submitted kernels cannot overlap your host writes. It gives you no protection against kernels submitted after the map call. Those must not be enqueued until after clEnqueueUnmapMemObject — on an in-order queue, unmapping before enqueueing the next kernel is enough; on an out-of-order queue you would need event dependencies. So the safe pattern is:
// prior kernels already enqueued
void *p = clEnqueueMapBuffer(queue, buf, CL_TRUE,
CL_MAP_WRITE_INVALIDATE_REGION, 0, size, 0, NULL, NULL, &err);
// host writes the full region
clEnqueueUnmapMemObject(queue, buf, p, 0, NULL, NULL);
// only now enqueue kernels that touch bufWith a non-blocking map (CL_FALSE) you must wait on the returned event (or call clFinish) before touching the pointer, otherwise the host may write while device work is still in flight — the most hazardous variant of this bug.
There is no portable query for this. No device info flag exposes "we honor invalidate as a coherence skip," and empirical corruption testing is unreliable precisely because the behavior is undefined — a passing test only proves your current driver/hardware combo happened to stay coherent. The only portable stance is to treat any overlap as a bug regardless of observed behavior.
To confirm the blocking-map ordering on your platform, enqueue a long-running kernel writing the buffer, then issue a blocking map and time it (or use event profiling on the kernel and map). The map's start should follow the kernel's end. This verifies ordering of prior work — it does not, and cannot, verify safety of overlap, because no such safety exists to verify.
Structure the pipeline so the buffer is never mapped while kernels referencing it can execute: use the hint for what it is (avoiding read-back of dead data when you fully overwrite a region), and get your concurrency from double-buffering or sub-buffers with disjoint regions instead of overlapping access to one buffer.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.