2012-07-31 5 views
3

시뮬레이션을 pyOpenCL로 이동하고 데이터 액세스가 작동하지 않습니다. 나는 1D 배열의 벡터를 제공하려고 노력하고있다. (실제로는 여러 개이지만 예제는 사용했다.)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

코드는 잘입니다. 3 성분의 벡터 데이터를 들어

:

    값은 16 바이트가 오픈 CL 1.2 사양에 따라 정렬 될 것으로 예상된다
  1. float3 , 6.1.5 : 그러나, 커널은 적어도 두 가지 문제점을 가지고 유형 인 경우 데이터 유형의 크기는 4 * sizeof (구성 요소)입니다. 즉, 3 요소 벡터 데이터 형식이 4 * sizeof (구성 요소) 경계에 정렬됩니다. vload3vstore3 내장 함수는 압축 된 스칼라 데이터 형식의 배열에서 3 개 요소 벡터 데이터 형식을 각각 읽고 쓰는 데 사용할 수 있습니다.

장치에 업로드 한 값이 커널이 float3 값을 직접 읽을 수 있도록 제대로 정렬되지 않았습니다.

  • 한계 계산 int lim = X*Y*3;은 약간 꺼져 있습니다. float3의 배열에서 이미 읽으려고하므로 *3은 불필요합니다.

  • 두 문제에 대한 해결책은 간단하다 :

    #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); 
          } 
         } 
    } 
    
    : 사양에 명시된 바와 같이, 당신은 vload3float의 배열에서로드 할 때 사용한다