OpenCL fine-grained SVM buffer mapping coherence boundary
0 reputation · 08 Jun 2020, 10:50 UTC
0 reputation · 08 Jun 2020, 10:50 UTC
Goal is to configure fine-grained Shared Virtual Memory so a host pointer and device kernels can access the same buffer with a defined visibility boundary and without assuming implementation-specific coherence.
OpenCL 2.0 introduces SVM with explicit mapping via clEnqueueSVMMap and clEnqueueSVMUnmap, and OpenCL 3.0 makes SVM optional. The memory consistency model for fine-grained SVM is implementation-defined, and there is no standardized mechanism to detect device write completion without events or barriers. Permission boundaries between host writes and device reads are not uniformly specified across vendors, and behavior with out-of-order command queues is undefined.
What coherence guarantees can be assumed for fine-grained SVM to be portable across CPU and discrete GPU devices? Is explicit mapping and unmapping sufficient to define a permission boundary for host-device access? Which synchronization primitives are needed to make visibility deterministic when SVM is optional in OpenCL 3.0?
OpenCL 2.0 defines fine‑grained SVM as memory that can be accessed by both host and device without explicit copies. The specification states:
In practice this means that:
Map/unmap are *permission boundaries*, but they do not guarantee that data has propagated through device caches. The spec does not require the implementation to flush or invalidate caches automatically. Therefore:
OpenCL 3.0 makes fine‑grained SVM optional. Portable code should:
CL_DEVICE_SVM_FINE_GRAIN_BUFFER with clGetDeviceInfo.clEnqueueCopyBuffer path.Regardless of the path, you need to enforce ordering with the same primitives: clEnqueueBarrierWithWaitList, clEnqueueMarkerWithWaitList, or event dependencies. Using clFinish after each kernel is the simplest, though it can be expensive.
cl_event map_evt, kernel_evt, unmap_evt;
// 1. Host writes to SVM
clEnqueueSVMMap(queue, svm_ptr, 0, size, CL_MAP_WRITE, 0, NULL, &map_evt);
// ... host writes data here ...
clEnqueueSVMUnmap(queue, svm_ptr, 0, NULL, &unmap_evt);
// 2. Kernel that reads and writes the same SVM buffer
clSetKernelArgSVMPointer(kernel, 0, svm_ptr);
clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global, NULL, 1, &unmap_evt, &kernel_evt);
// 3. Device‑to‑host visibility
clEnqueueBarrierWithWaitList(queue, 1, &kernel_evt, NULL);
// 4. Host reads back
clEnqueueSVMMap(queue, svm_ptr, 0, size, CL_MAP_READ, 0, NULL, &map_evt);
// ... host reads data ...
clEnqueueSVMUnmap(queue, svm_ptr, 0, NULL, NULL);
clFinish(queue);
Key points:
clEnqueueSVMMap or clEnqueueSVMUnmap is paired with an event that you can use to build a dependency chain.If you are still seeing stale data, confirm whether you are using an out‑of‑order command queue. In that case you must explicitly chain the events shown above; otherwise the implicit ordering of an in‑order queue is sufficient.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.