2012-07-31 20 views
3

我正在將模擬轉移到pyOpenCL中,無法讓我的數據訪問工作。我試圖提供一維向量數組(實際上有好幾個,但我剛剛使用的例子只是使用了一個)。如何傳遞pyOpenCL中的向量數組

目前,幾個向量複製過來很好,但數據根本不是我提供的。

我不認爲我已經在這裏發佈過,所以如果任何格式/演示文稿是錯誤的道歉。此外,我剛剛刪除了所有的模擬代碼,所以我意識到這段代碼目前沒有做任何事情,我只想讓緩衝區傳遞正確。

在此先感謝。

內核(kertest.py):

step1 = """ 
#pragma OPENCL EXTENSION cl_amd_printf: enable 
#define X xdim 
#define Y ydim 
__kernel void k1(__global float3 *spins, 
       __local float3 *tile) 
{   
    ushort lid = 2 * get_local_id(0); 
    ushort group = 2 * get_group_id(0); 
    ushort num = get_num_groups(0); 
    int lim = X*Y*3; 

    for (ushort i = 0; i < lim; i++) 
     { 
      if (lid == 0 && group == 0) 
      { 
       printf("%f :: %d\\n", spins[i].x, i); 
      } 
     } 
}""" 

代碼本身(gputest.py):

import kertest as k2D 
import numpy as np 
import pyopencl as cl 

class GPU_MC2DSim(): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

     if x >= y: 
      self.xdim = int(self.x) 
      self.ydim = int(self.y) 
     else: 
      self.xdim = int(self.y) 
      self.ydim = int(self.x) 

     if self.xdim % 2 != 0: self.xdim += 1 

     if self.ydim % 2 != 0: self.ydim += 1 

     self.M = np.ones((self.xdim*self.ydim, 3)).astype(np.float32) 
     self.M[:, 1] += 1.0 
     self.M[:, 2] += 2.0 

     print self.M 

    def simulate(self): 
     ctx = cl.create_some_context() 
     q = cl.CommandQueue(ctx) 
     mf = cl.mem_flags 

     #Pass buffer: 
     M_buf = cl.Buffer(ctx, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf = self.M) 

     #Insert kernel parameters: 
     params = {"xdim" : "%d" % (self.xdim), 
        "ydim" : "%d" % (self.ydim), 
        } 
     for name in params: 
      k2D.step1 = k2D.step1.replace(name, params[name]) 

     #Compile kernel: 
     step1 = cl.Program(ctx, k2D.step1).build() 

     locmem = cl.LocalMemory(self.xdim*4*4) 

     step1.k1(q, ((self.xdim*self.ydim)/4,), (self.xdim/2,), M_buf, locmem).wait() 
     return None 

xdim = 4 
ydim = 4 
sim = GPU_MC2DSim(xdim, ydim) 
sim.simulate() 

回答

3

您的數據複製到設備代碼就好了。然而,內核具有至少兩個問題:

  1. float3值預計是16字節對齊,按1.2的OpenCL規格,6.1.5:

    對於3成分的矢量數據類型,數據類型的大小是4 * sizeof(組件)。這意味着3分量矢量數據類型將與4 * sizeof(分量)邊界對齊。可以使用內置函數分別從包裝標量數據類型的數組讀取和寫入3分量矢量數據類型。

    上傳到設備的值未正確對齊,以便內核直接讀取float3值。

  2. 您的極限計算int lim = X*Y*3;稍微偏離。您已經嘗試從float3的數組中讀取,因此*3是多餘的。

這兩個問題的解決方案是簡單:在規範中陳述,應使用vload3從的float秒的數組加載:

#pragma OPENCL EXTENSION cl_amd_printf: enable 
#define X xdim 
#define Y ydim 
__kernel void k1(__global float *spins, 
       __local float3 *tile) 
{ 
    ushort lid = 2 * get_local_id(0); 
    ushort group = 2 * get_group_id(0); 
    ushort num = get_num_groups(0); 
    int lim = X*Y; 

    for (ushort i = 0; i < lim; i++) 
     { 
      if (lid == 0 && group == 0) 
      { 
       float3 vec = vload3(i, spins); 
       printf("(%f, %f, %f) :: %d\\n", vec.x, vec.y, vec.z, i); 
      } 
     } 
}