Does clFinish guarantee host-pointer coherence for CL_MEM_USE_HOST_PTR buffers on out-of-order queues?
0 reputation · 27 Jul 2022, 18:32 UTC
0 reputation · 27 Jul 2022, 18:32 UTC
OpenCL 1.2 specifies that a buffer created with CL_MEM_USE_HOST_PTR requires explicit synchronization—such as clEnqueueMapBuffer/clEnqueueUnmapMemObject or a read/write command—before the host can safely access the memory after kernel execution. The specification does not state that clFinish alone establishes coherence for the host pointer, even when CL_DEVICE_HOST_UNIFIED_MEMORY reports CL_TRUE.
In practice, some integrated or unified-memory drivers appear to make the host pointer visible immediately after clFinish on an out-of-order queue, while discrete GPUs typically do not. This implementation variance creates a portability hazard: code that works on one device may silently corrupt data on another or after a driver update.
What synchronization sequence does the OpenCL 1.2 memory model require before a host thread reads a CL_MEM_USE_HOST_PTR buffer that a kernel has just written on an out-of-order command queue? Does the answer change when CL_DEVICE_HOST_UNIFIED_MEMORY is CL_TRUE versus CL_FALSE?
35275 reputation · 28 Jul 2022, 02:07 UTC
No. clFinish alone does not establish host-pointer coherence for a CL_MEM_USE_HOST_PTR buffer after a kernel write on an out-of-order queue, regardless of the CL_DEVICE_HOST_UNIFIED_MEMORY value. The OpenCL 1.2 memory model requires an explicit device-to-host synchronization command—clEnqueueMapBuffer, clEnqueueReadBuffer, or clEnqueueReadBufferRect—ordered after the kernel via an event wait list or barrier. clFinish only guarantees that previously enqueued commands have completed on the device; it does not by itself perform the buffer synchronization that makes the host pointer safe to read.
K returned by the kernel enqueue (clEnqueueNDRangeKernel) on the out-of-order queue.K in its event_wait_list:
cl_event map_evt;
clEnqueueMapBuffer(queue, buffer, CL_FALSE, CL_MAP_READ, 0, size, 1, &K, &map_evt, &err);clWaitForEvent(map_evt) or clFinish(queue) after the map/read enqueue.clEnqueueMapBuffer).clEnqueueUnmapMemObject (if mapped) or ensure the read command has completed.Step 2 is essential: on an out-of-order queue, program order does not order the host-facing command after the kernel. The event wait list (or a clEnqueueBarrierWithWaitList) creates the required happens-before edge.
CL_DEVICE_HOST_UNIFIED_MEMORYThe required sequence does not change. When CL_DEVICE_HOST_UNIFIED_MEMORY == CL_TRUE, the device and host share physical memory, so some drivers appear to make the host pointer visible immediately after clFinish. This is implementation-specific behavior, not a portable guarantee. A driver update, a different device on the same platform, or a discrete GPU (CL_FALSE) will break code that relies on clFinish alone. Treat CL_DEVICE_HOST_UNIFIED_MEMORY as a performance hint only.
Code that reads host_ptr after only clFinish works on some integrated GPUs and CPUs today but will silently corrupt data on discrete GPUs or after driver changes. The OpenCL 1.2 specification (section 5.2.1, 5.3) is explicit: the host must not access the memory region while a command using the buffer is in flight, and coherence is established only by the map/read/write commands themselves.
CL_DEVICE_HOST_UNIFIED_MEMORY once at startup; log it but do not branch synchronization logic on it.clFinish-only host read against the event-ordered map/read sequence using a known kernel write pattern.clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS, ...) returning CL_COMPLETE before dereferencing the host pointer.Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 28 Jul 2022, 00:11 UTC
The OpenCL 1.2 specification requires explicit synchronization before host access to a buffer after kernel execution, irrespective of status.
While guarantees command completion on an out-of-order queue, it does not force device cache flushing to the host pointer.
A portable pattern involves enqueuing the kernel, calling , and then using with to explicitly bring the data into the host's view for safe reading.