title: How to pass a list of strings to an opencl kernel using pyopencl?
body: <p>How to pass list of strings to an opencl kernel the right way?</p>
  
  <p>I tried this way using buffers (see following code), but I failed.</p>
  
  <p>OpenCL (struct.cl):</p>
  
  <pre><code>typedef struct{
            uchar uc[40];
  } my_struct9; 
  
  inline void try_this7_now(__global const uchar * IN_DATA ,
                            const uint IN_len_DATA ,
                            __global uchar * OUT_DATA){
      for (unsigned int i=0; i&lt;IN_len_DATA ; i++)  OUT_DATA[i] = IN_DATA[i];
  }
  
  __kernel void try_this7(__global const my_struct9 * pS_IN_DATA ,
                          const uint IN_len ,
                          __global my_struct9 * pS_OUT){
  
      uint idx = get_global_id(0);
  for (unsigned int i=0; i&lt;idx; i++) try_this7_now(pS_IN_DATA[i].uc, IN_len, pS_OUT[i].uc);
    }
  </code></pre>
  
  <p>Python (opencl_struct.py):</p>
  
  <pre><code># -*- coding: utf-8 -*- 
  
  import pyopencl as cl
  import pyopencl.array as cl_array
  import numpy
  
  ctx = cl.create_some_context()
  queue = cl.CommandQueue(ctx)
  # --------------------------------------------------------
  LIMIT = 40
  mf = cl.mem_flags
  
  import ctypes,sys,struct
  """
  typedef struct{
            uchar uc[40];
  } my_struct9; 
  """
  INlist = []
  INlist.append("That is VERY cool!")
  INlist.append("It is a list!")
  INlist.append("A big one!")
  #INlist.append("But it failes to output. :-(")  # PLAY WITH THOSE
  INlist.append("WTF is THAT?") # PLAY WITH THOSE
  print "INlist : "+str(INlist)
  print "largest string "+str( max( len(INlist[iL]) for iL in range(len(INlist)) ) )
  strLIMIT=str(LIMIT)
  s7 = struct.Struct(  (str(strLIMIT+'s') *len(INlist)) )
  IN_host_buffer = ctypes.create_string_buffer(s7.size)
  s7.pack_into(IN_host_buffer, 0, *INlist)
  IN_dev_buffer = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=IN_host_buffer)
  
  OUT_host_buffer = ctypes.create_string_buffer(s7.size)
  
  OUT_dev_buffer = cl.Buffer(ctx, mf.WRITE_ONLY, len(OUT_host_buffer))
  print "&gt; len(OUT_host_buffer) "+str(len(OUT_host_buffer))
  
  # ========================================================================================
  f = open("struct.cl", 'r')
  fstr = "".join(f.readlines())
  prg = cl.Program(ctx, fstr).build()
  
  #cl.enqueue_copy(queue, IN_dev_buffer, IN_host_buffer, is_blocking=True) # copy data to device
  cl.enqueue_write_buffer(queue, IN_dev_buffer, IN_host_buffer).wait()
  
  prg.try_this7(queue, (1,), None, IN_dev_buffer, numpy.uint32(LIMIT), OUT_dev_buffer)
  # ========================================================================================
  cl.enqueue_copy(queue, OUT_host_buffer, OUT_dev_buffer).wait()
  
  SSS = s7.unpack_from(OUT_host_buffer,0)
  
  # unpack here OUT_host_buffer
  print "(GPU) output : "+str( SSS )+" "
  
  for s in range(len(SSS)):
   print "&gt;&gt;&gt; (GPU) output : "+str( SSS[s] )
  </code></pre>
  
  <p>I ran the program first time with "but it failes to output" as 4th list element. Then I played around by increasing and decreasing elements of the list. Finally, there appeared this problem:
  <strong>The output of the program is supposed to be</strong> (short version)</p>
  
  <blockquote>
    <blockquote>
      <blockquote>
        <blockquote>
          <p>(GPU) output : That is VERY cool!</p>
          
          <p>(GPU) output : It is a list!</p>
          
          <p>(GPU) output : A big one!</p>
          
          <p>(GPU) output : WTF is THAT?</p>
        </blockquote>
      </blockquote>
    </blockquote>
  </blockquote>
  
  <p>But it is:</p>
  
  <blockquote>
    <p>python opencl_struct.py </p>
    
    <p>INlist : ['That is VERY cool!', 'It is a
    list!', 'A big one!', 'WTF is THAT?']</p>
    
    <p>largest string 18</p>
    
    <blockquote>
      <p>len(OUT_host_buffer) 160 (GPU) output : ('That is VERY cool!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
      'It is a
      list!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
      'A big
      one!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
      'But it failes to output.
      :-(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') </p>
      
      <blockquote>
        <blockquote>
          <p>(GPU) output : That is VERY cool!</p>
          
          <p>(GPU) output : It is a list!</p>
          
          <p>(GPU) output : A big one!</p>
          
          <p>(GPU) output : But it failes to output. :-(</p>
        </blockquote>
      </blockquote>
    </blockquote>
  </blockquote>
  
  <p>As you can see, the the 4th list element differes.</p>
  
  <p>So, maybe my approach is wrong or there is a bug in pyopencl or somewhere else.</p>
  
  <p>I am using a NVidia 9400 GPU.</p>
  
  <p>Rambo</p>