One of the most powerful aspects of parallel programming on integrated GPUs is that you may avoid the O(N) copy operation associated with moving data from host to device memory. This feature can be particularly useful for applications that deal with real-time data streams, like video processing.
<h4 id="method-1-let-opencl-allocate-memory-and-use-map-unmap-buffers">Method 1: Let OpenCL allocate memory and use map/unmap buffers</h4>
The first method of allocating zero-copy buffers is quite simple: let OpenCL do it for you. To create a buffer in this fashion simply specify the<code>CL_MEM_ALLOC_HOST_PTR</code> argument to the <code>cl::Buffer</code> constructor (or<code>clCreateBuffer</code> if you are using the C API):
<pre><code class="lang-c++">// Instruct OpenCL to allocate host memory
::size_t size = N * sizeof(float)
Buffer d_results(context, CL_MEM_ALLOC_HOST_PTR, size);

... launch kernels, etc
</code></pre>
<h4 id="method-2-allocate-aligned-memory-and-use-map-unmap-buffers">Method 2: Allocate aligned memory and use map/unmap buffers</h4>
In situations where you are streaming data or doing DMA between devices, it may be necessary to use aligned memory. In this situation, Intel OpenCL devices require that data be allocated with 4k alignment and be a multiple of 64 bytes (a cache line) as follows:
<pre><code class="lang-c++">::size_t size = N * sizeof(float); // size must be a multiple of 64
::size_t alignment = 4096;
// Allocate aligned memory on the host. The particular function is OS-dependent.
//  memalign(size_t alignment, size_t size) on Linux, release memory with free(...)
//  _aligned_malloc(size_t size, size_t alignment) on Windows, release with _aligned_free(...)
//  posix_memalign(void ** ptr, size_t alignment, size_t size) on OSX, release with free(...)
float * h_results = (float*) memalign(alignment, size);

// Create an OpenCL buffer using the host pointer
Buffer d_results = cl::Buffer(context, CL_MEM_USE_HOST_PTR, size, t_results);
</code></pre>
<h4 id="accessing-memory">Accessing memory</h4>
Perhaps the most misunderstood aspect of zero-copy buffers in OpenCL relates to the state of the buffer after being used in a kernel invocation. It is often thought that the memory in the buffers will be updated immediately after the kernel completes; however, the OpenCL specification does not guarantee this behavior. To ensure that a zero-copy buffer is properly updated prior to use, a developer must map (and unmap!) a buffer prior to use in host code. This is actually a quite simple process:
<pre><code class="lang-c++">// Get exclusive access to the buffer
float * temp = (float*) queue.enqueueMapBuffer(d_results, CL_TRUE, CL_MAP_READ, 0, size);

... use the mapped buffer

// release the buffer back to OpenCL’s control
queue.enqueueUnmapMemObject(d_results, temp);
</code></pre>
<h4 id="further-reading">Further reading</h4>
<a href="https://software.intel.com/en-us/articles/getting-the-most-from-opencl-12-how-to-increase-performance-by-minimizing-buffer-copies-on-intel-processor-graphics">Getting the Most from OpenCL™ 1.2: How to Increase Performance by Minimizing Buffer Copies on Intel® Processor Graphics</a>