<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic clEnqueueMap/UnmapBuffer overheads in OpenCL* for CPU</title>
    <link>https://community.intel.com/t5/OpenCL-for-CPU/clEnqueueMap-UnmapBuffer-overheads/m-p/1043542#M3914</link>
    <description>&lt;P&gt;Can someone please straighten me out on expected clEnqueueMapBuffer overheads under Haswell?&lt;/P&gt;

&lt;P&gt;Environment: Windows 7 sp1, VS2013, i7-4770, driver 10.18.14.4170&lt;/P&gt;

&lt;P&gt;I have my own 768kb buffer which needs to be accessed by the HD 4600 GPU.&lt;BR /&gt;
	I clCreateBuffer with CL_MEM_ALLOC_HOST_PTR, which I believe sets aside some pinned memory for later use. Later on I use clEnqueueMapBuffer (with CL_MAP_READ), and use the resultant pointer to populate the new cl_mem with my data. An event from the clEnqueueMapBuffer call is used to kick off a clEnqueueUnmapMemObject straight afterwards, and similarly, an event from the clEnqueueUnmapMemObject is used in the event_wait_list of the kernel launch straight after that.&lt;BR /&gt;
	Code below, sans error handling.&lt;/P&gt;

&lt;P&gt;All fairly straightforward, but timing is a problem. My VTune trace shows the clEnqueueMapBuffer taking 770us in the queue before a 0.3us compute. Then the clEnqueueUnmapMemObject takes 130us followed by a similarly negligible 0.3us compute time. However since my kernel takes only 400us of compute, clEnqueueMap/UnmapBuffer queuing is taking a disproportionate part of the overall time. Am I just in the noise and overheads with such small function times, or can I improve this at all?&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;PRE class="brush:bash;"&gt;		tile_size_bytes = BITMAP_NON_TEXTURED_SIZE_PER_TILE_OPENCL * sizeof(unsigned char);

		input_buffer_cl_mem = 
		clCreateBuffer(oclInstance-&amp;gt;context,
			CL_MEM_ALLOC_HOST_PTR,
			tile_size_bytes,
			NULL,
			&amp;amp;errcode_ret);
			
			
		// later....
		
        // map the buffer

        mapped_tile_buffer = clEnqueueMapBuffer(
            oclInstance-&amp;gt;queue,
            input_buffer_cl_mem,
            CL_FALSE,
            CL_MAP_READ,
            0,
            tile_size_bytes,
            0,
            NULL,
            &amp;amp;writeTileEvent,
            &amp;amp;errcode_ret);

        // copy strided data into mapped buffer

        thisTileStart = tileStrip + (tileCount * BITMAP_TILE_WIDTH_PIXELS * CHANNEL_COUNT_OPENCL);
        destride_incoming_bitmap_tile_in_strip_into_buffer(thisTileStart, bitmap_step, (char *)mapped_tile_buffer);
")

        // and unmap

        errcode_ret = clEnqueueUnmapMemObject(
            oclInstance-&amp;gt;queue,
            input_buffer_cl_mem,
            mapped_tile_buffer,
            1,
            &amp;amp;writeTileEvent,
            &amp;amp;unmapEvent);
		
		
		// (kernel params already set up...
		
		size_t globalSize[3];
		size_t localSize[] = { THREAD_BLOCK_TILE_WIDTH_IN_PIXELS, THREAD_BLOCK_TILE_HEIGHT_IN_PIXELS, 1 };  // blocks are default 64 x 8
		size_t globalSizeWorkgroups[] = { ARR_IMAGE_TILE_WIDTH / THREAD_BLOCK_TILE_WIDTH_IN_PIXELS,			// 256/64 = 4
			ARR_IMAGE_TILE_HEIGHT / THREAD_BLOCK_TILE_HEIGHT_IN_PIXELS,										// 256/8 = 32
			CHANNEL_COUNT_OPENCL };																			// 3

		globalSize[0] = globalSizeWorkgroups[0] * localSize[0];
		globalSize[1] = globalSizeWorkgroups[1] * localSize[1];
		globalSize[2] = globalSizeWorkgroups[2] * localSize[2];

		errcode_ret = clEnqueueNDRangeKernel(
		oclInstance-&amp;gt;queue,								                            // command queue
		acej_kernel_tile_ifdct_cpuhuffman,											// kernel
		3,														                    // work_dim
		0,														                    // global_work_offset
		globalSize,												                    // global_work_size
		localSize,					                                                // local_work_size :  localSize or NULL
		1,														                    // num_events_in_wait_list
		&amp;amp;unmapEvent,													            // event_wait_list
		(eventList + tileCount));											        // event
 


&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Thu, 18 Jun 2015 05:56:33 GMT</pubDate>
    <dc:creator>PCox</dc:creator>
    <dc:date>2015-06-18T05:56:33Z</dc:date>
    <item>
      <title>clEnqueueMap/UnmapBuffer overheads</title>
      <link>https://community.intel.com/t5/OpenCL-for-CPU/clEnqueueMap-UnmapBuffer-overheads/m-p/1043542#M3914</link>
      <description>&lt;P&gt;Can someone please straighten me out on expected clEnqueueMapBuffer overheads under Haswell?&lt;/P&gt;

&lt;P&gt;Environment: Windows 7 sp1, VS2013, i7-4770, driver 10.18.14.4170&lt;/P&gt;

&lt;P&gt;I have my own 768kb buffer which needs to be accessed by the HD 4600 GPU.&lt;BR /&gt;
	I clCreateBuffer with CL_MEM_ALLOC_HOST_PTR, which I believe sets aside some pinned memory for later use. Later on I use clEnqueueMapBuffer (with CL_MAP_READ), and use the resultant pointer to populate the new cl_mem with my data. An event from the clEnqueueMapBuffer call is used to kick off a clEnqueueUnmapMemObject straight afterwards, and similarly, an event from the clEnqueueUnmapMemObject is used in the event_wait_list of the kernel launch straight after that.&lt;BR /&gt;
	Code below, sans error handling.&lt;/P&gt;

&lt;P&gt;All fairly straightforward, but timing is a problem. My VTune trace shows the clEnqueueMapBuffer taking 770us in the queue before a 0.3us compute. Then the clEnqueueUnmapMemObject takes 130us followed by a similarly negligible 0.3us compute time. However since my kernel takes only 400us of compute, clEnqueueMap/UnmapBuffer queuing is taking a disproportionate part of the overall time. Am I just in the noise and overheads with such small function times, or can I improve this at all?&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;PRE class="brush:bash;"&gt;		tile_size_bytes = BITMAP_NON_TEXTURED_SIZE_PER_TILE_OPENCL * sizeof(unsigned char);

		input_buffer_cl_mem = 
		clCreateBuffer(oclInstance-&amp;gt;context,
			CL_MEM_ALLOC_HOST_PTR,
			tile_size_bytes,
			NULL,
			&amp;amp;errcode_ret);
			
			
		// later....
		
        // map the buffer

        mapped_tile_buffer = clEnqueueMapBuffer(
            oclInstance-&amp;gt;queue,
            input_buffer_cl_mem,
            CL_FALSE,
            CL_MAP_READ,
            0,
            tile_size_bytes,
            0,
            NULL,
            &amp;amp;writeTileEvent,
            &amp;amp;errcode_ret);

        // copy strided data into mapped buffer

        thisTileStart = tileStrip + (tileCount * BITMAP_TILE_WIDTH_PIXELS * CHANNEL_COUNT_OPENCL);
        destride_incoming_bitmap_tile_in_strip_into_buffer(thisTileStart, bitmap_step, (char *)mapped_tile_buffer);
")

        // and unmap

        errcode_ret = clEnqueueUnmapMemObject(
            oclInstance-&amp;gt;queue,
            input_buffer_cl_mem,
            mapped_tile_buffer,
            1,
            &amp;amp;writeTileEvent,
            &amp;amp;unmapEvent);
		
		
		// (kernel params already set up...
		
		size_t globalSize[3];
		size_t localSize[] = { THREAD_BLOCK_TILE_WIDTH_IN_PIXELS, THREAD_BLOCK_TILE_HEIGHT_IN_PIXELS, 1 };  // blocks are default 64 x 8
		size_t globalSizeWorkgroups[] = { ARR_IMAGE_TILE_WIDTH / THREAD_BLOCK_TILE_WIDTH_IN_PIXELS,			// 256/64 = 4
			ARR_IMAGE_TILE_HEIGHT / THREAD_BLOCK_TILE_HEIGHT_IN_PIXELS,										// 256/8 = 32
			CHANNEL_COUNT_OPENCL };																			// 3

		globalSize[0] = globalSizeWorkgroups[0] * localSize[0];
		globalSize[1] = globalSizeWorkgroups[1] * localSize[1];
		globalSize[2] = globalSizeWorkgroups[2] * localSize[2];

		errcode_ret = clEnqueueNDRangeKernel(
		oclInstance-&amp;gt;queue,								                            // command queue
		acej_kernel_tile_ifdct_cpuhuffman,											// kernel
		3,														                    // work_dim
		0,														                    // global_work_offset
		globalSize,												                    // global_work_size
		localSize,					                                                // local_work_size :  localSize or NULL
		1,														                    // num_events_in_wait_list
		&amp;amp;unmapEvent,													            // event_wait_list
		(eventList + tileCount));											        // event
 


&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 18 Jun 2015 05:56:33 GMT</pubDate>
      <guid>https://community.intel.com/t5/OpenCL-for-CPU/clEnqueueMap-UnmapBuffer-overheads/m-p/1043542#M3914</guid>
      <dc:creator>PCox</dc:creator>
      <dc:date>2015-06-18T05:56:33Z</dc:date>
    </item>
    <item>
      <title>Hi Philip,</title>
      <link>https://community.intel.com/t5/OpenCL-for-CPU/clEnqueueMap-UnmapBuffer-overheads/m-p/1043543#M3915</link>
      <description>&lt;P&gt;Hi Philip,&lt;/P&gt;

&lt;P&gt;I am traveling today, so won't be able to try what you are doing until tomorrow.&lt;/P&gt;

&lt;P&gt;Meanwhile, you can try the following things to see if the behavior changes in any way:&lt;/P&gt;

&lt;P&gt;1. Try to get rid of events.&lt;/P&gt;

&lt;P&gt;2. Instead of CL_MEM_ALLOC_HOST_PTR, even though it is a valid use, try allocating memory with _aligned_malloc with 4096 byte alignment and then create a buffer with CL_MEM_USE_HOST_PTR. Make sure that the length of your buffer is a multiple of 64 bytes.&lt;/P&gt;

&lt;P&gt;3. There is a newer 15.36.21.64.4222 driver out there (see &lt;A href="https://downloadcenter.intel.com/search?keyword=4th+Generation"&gt;https://downloadcenter.intel.com/search?keyword=4th+Generation&lt;/A&gt;&amp;nbsp;) - try it to see if it changes behavior in any way.&lt;/P&gt;

&lt;P&gt;Let me know how it goes.&lt;/P&gt;

&lt;P&gt;Thanks!&lt;/P&gt;</description>
      <pubDate>Thu, 18 Jun 2015 14:12:48 GMT</pubDate>
      <guid>https://community.intel.com/t5/OpenCL-for-CPU/clEnqueueMap-UnmapBuffer-overheads/m-p/1043543#M3915</guid>
      <dc:creator>Robert_I_Intel</dc:creator>
      <dc:date>2015-06-18T14:12:48Z</dc:date>
    </item>
    <item>
      <title>Hi Philip,</title>
      <link>https://community.intel.com/t5/OpenCL-for-CPU/clEnqueueMap-UnmapBuffer-overheads/m-p/1043544#M3916</link>
      <description>&lt;P&gt;Hi Philip,&lt;/P&gt;

&lt;P&gt;I am back in office. Couple of questions:&lt;/P&gt;

&lt;P&gt;1. Could you please provide a complete reproducer that I can run on my system? You have several constants that are undefined in the snippet you provided as well as the kernel itself.&amp;nbsp;&lt;/P&gt;

&lt;P&gt;2. You use &amp;nbsp;&lt;SPAN style="color: rgb(0, 0, 0); font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; font-size: 13.0080003738403px; line-height: 14.3087997436523px;"&gt;CL_MAP_READ&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="font-size: 13.0080003738403px; line-height: 15.609601020813px;"&gt;in the example above where I would expect CL_MAP_WRITE - aren't you writing that mapped buffer?&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 13.0080003738403px; line-height: 15.609601020813px;"&gt;3. Were you able to try things I suggested?&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 13.0080003738403px; line-height: 15.609601020813px;"&gt;Thanks!&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;Robert&lt;/P&gt;</description>
      <pubDate>Fri, 19 Jun 2015 17:58:14 GMT</pubDate>
      <guid>https://community.intel.com/t5/OpenCL-for-CPU/clEnqueueMap-UnmapBuffer-overheads/m-p/1043544#M3916</guid>
      <dc:creator>Robert_I_Intel</dc:creator>
      <dc:date>2015-06-19T17:58:14Z</dc:date>
    </item>
  </channel>
</rss>

