title: async_work_group_copy is copying data slower than manual copying in opencl kernel
body: <p>In my opencl kernel, I am trying to copy part of the data which is accessed more than other parts to the local memory. To do that, at the beginning I was just assigining the values manually. The copying was as follows:</p>
  
  <pre><code>    __global LinearBVHInteriorNode* subtree_globalptr           =  &amp;(((__global BVHTree*)accelstruct)-&gt;interior_nodes[subtree_interior_idx]);
      __global LinearBVHInteriorNodeInfo* subtree_info_globalptr  =  &amp;(((__global BVHTree*)accelstruct)-&gt;interior_nodes_info[subtree_interior_idx]);
  
      int last_subtree_interior_idx  = subtree_info_globalptr-&gt;last_interior;
  
      int n_subtree_interior_nodes = last_subtree_interior_idx - subtree_interior_idx + 1;
  
      int interior_nodes_beg_idx = thread_local_idx * ((n_subtree_interior_nodes / local_dim) + 1);
      int interior_nodes_end_idx = min((thread_local_idx + 1) * ((n_subtree_interior_nodes / local_dim) + 1), last_subtree_interior_idx);
  
      if(thread_local_idx == 0){
        subtree.interior_base_idx = subtree_info_globalptr[1].parent;
        subtree.leaf_base_idx     = subtree_info_globalptr[0].leaf_lowidx;
        subtree.tree              = accelstruct;
      }
  
      // Copy the data for interior nodes from the global memory to local memory
      for(int i = interior_nodes_beg_idx; i &lt;= interior_nodes_end_idx; i++){
  
        subtree.interior_nodes[ i ].left_bound.min  = subtree_globalptr[ i ].left_bound.min;
        subtree.interior_nodes[ i ].left_bound.max  = subtree_globalptr[ i ].left_bound.max;
        subtree.interior_nodes[ i ].right_bound.min = subtree_globalptr[ i ].right_bound.min;
        subtree.interior_nodes[ i ].right_bound.max = subtree_globalptr[ i ].right_bound.max;
        subtree.interior_nodes[ i ].children[0]     = subtree_globalptr[ i ].children[0];
        subtree.interior_nodes[ i ].children[1]     = subtree_globalptr[ i ].children[1];
        subtree.interior_nodes[ i ].splitAxis       = subtree_globalptr[ i ].splitAxis;
      }
  
      int leafnodes_lowidx                                = subtree_info_globalptr-&gt;leaf_lowidx;
      int leafnodes_highidx                               = subtree_info_globalptr-&gt;leaf_highidx;
      int n_subtree_leaf_nodes                            = leafnodes_highidx - leafnodes_lowidx;
      __global LinearBVHLeafNode* subtree_leaf_globalptr =  &amp;(((__global BVHTree*)accelstruct)-&gt;leaf_nodes[leafnodes_lowidx]);
  
      int leaf_nodes_beg_idx = thread_local_idx * ((n_subtree_leaf_nodes / local_dim) + 1);
      int leaf_nodes_end_idx = min((thread_local_idx + 1) * ((n_subtree_leaf_nodes / local_dim) + 1), leafnodes_highidx);
  
      // Copy the data for leaf nodes from the global memory to local memory
      for(int i = leaf_nodes_beg_idx; i &lt; leaf_nodes_end_idx; i++){
  
        subtree.leaf_nodes[ i ].lowIdx  = subtree_leaf_globalptr[ i ].lowIdx;
        subtree.leaf_nodes[ i ].highIdx = subtree_leaf_globalptr[ i ].highIdx;
      }
  
    // Wait all the threads to finish the copying task.
    barrier(CLK_LOCAL_MEM_FENCE);
  </code></pre>
  
  <p>it tooks 0.1s for my dataset to copy the data from global memory to local memory which is too much. As I understood the <code>async_work_group_copy</code> should perform it faster than manual copying, so I changed to <code>async_work_group_copy</code>:</p>
  
  <pre><code>    __global LinearBVHInteriorNode* subtree_globalptr           =  &amp;(((__global BVHTree*)accelstruct)-&gt;interior_nodes[subtree_interior_idx]);
      __global LinearBVHInteriorNodeInfo* subtree_info_globalptr  =  &amp;(((__global BVHTree*)accelstruct)-&gt;interior_nodes_info[subtree_interior_idx]);
  
      int last_subtree_interior_idx  = subtree_info_globalptr-&gt;last_interior;
  
      int n_subtree_interior_nodes = last_subtree_interior_idx - subtree_interior_idx + 1;
  
      int interior_nodes_beg_idx = thread_local_idx * ((n_subtree_interior_nodes / local_dim) + 1);
      int interior_nodes_end_idx = min((thread_local_idx + 1) * ((n_subtree_interior_nodes / local_dim) + 1), last_subtree_interior_idx);
  
      if(thread_local_idx == 0){
        subtree.interior_base_idx = subtree_info_globalptr[1].parent;
        subtree.leaf_base_idx     = subtree_info_globalptr[0].leaf_lowidx;
        subtree.tree              = accelstruct;
      }
  
      event_t copy_events[2];
  
      // Copy the data for interior nodes from the global memory to local memory
      copy_events[0] = async_work_group_copy((__local long2*)(&amp;subtree.interior_nodes[ interior_nodes_beg_idx ]), (__global long2 *)(&amp;subtree_globalptr[ interior_nodes_beg_idx ]), (interior_nodes_end_idx - interior_nodes_beg_idx + 1) * 5, 0);
  
      int leafnodes_lowidx                                = subtree_info_globalptr-&gt;leaf_lowidx;
      int leafnodes_highidx                               = subtree_info_globalptr-&gt;leaf_highidx;
      int n_subtree_leaf_nodes                            = leafnodes_highidx - leafnodes_lowidx;
      __global LinearBVHLeafNode* subtree_leaf_globalptr =  &amp;(((__global BVHTree*)accelstruct)-&gt;leaf_nodes[leafnodes_lowidx]);
  
      int leaf_nodes_beg_idx = thread_local_idx * ((n_subtree_leaf_nodes / local_dim) + 1);
      int leaf_nodes_end_idx = min((thread_local_idx + 1) * ((n_subtree_leaf_nodes / local_dim) + 1), leafnodes_highidx);
  
      // Copy the data for leaf nodes from the global memory to local memory
      copy_events[1] = async_work_group_copy((__local long*)&amp;subtree.interior_nodes[ leaf_nodes_beg_idx ], (__global long*)&amp;subtree_globalptr[ leaf_nodes_beg_idx ], (leaf_nodes_end_idx - leaf_nodes_beg_idx), 0);
  
  
    // Wait all the threads to finish the copying task.
    barrier(CLK_LOCAL_MEM_FENCE);
  </code></pre>
  
  <p>But it performs the copying in <code>1.0s</code> which is very strange. The struct which I have used are defined as follows:</p>
  
  <pre><code>typedef struct {
    AABB      left_bound, right_bound;
    int       children[2];
    ushort    splitAxis;
    int       pad;
  
  } LinearBVHInteriorNode;
  
  typedef struct {
    int       parent;
    int       leaf_lowidx, leaf_highidx;
    int       last_interior;
  
  } LinearBVHInteriorNodeInfo;
  
  typedef struct {
    int  lowIdx, highIdx;
  } LinearBVHLeafNode;
  
  typedef struct {
    int  parent;
  } LinearBVHLeafNodeInfo;
  
  typedef struct {
    __global  LinearBVHInteriorNode*      interior_nodes;         //!&lt; a pointer to interior nodes
    __global  LinearBVHInteriorNodeInfo*  interior_nodes_info;    //!&lt; a pointer to information of interior nodes
    __global  LinearBVHLeafNode*          leaf_nodes;             //!&lt; a pointer to leaf nodes 
    __global  LinearBVHLeafNodeInfo*      leaf_nodes_info;        //!&lt; a pointer to information of leaf nodes
    uint      n_interior_nodes;                                   //!&lt; Number of interior nodes
    uint      n_leaf_nodes;                                       //!&lt; Number of leaf nodes
  } BVHTree;
  
  
  typedef struct {
    __local LinearBVHInteriorNode* interior_nodes;
    __local LinearBVHLeafNode*     leaf_nodes;
  
    int     interior_base_idx, leaf_base_idx;
  
    __global BVHTree*              tree;
  } local_BVHTree;
  </code></pre>
  
  <p>I was looking for a function like <code>memcpy</code> in opencl kernel. because both of the arrays has the same structure and can be copied with such instruction. I think <code>async_work_group_copy</code> is doing something similar. Anyone ever had the same problem?</p>