如何在pyOpenCL中传递向量数组

如何在pyOpenCL中传递向量数组,opencl,pyopencl,Opencl,Pyopencl,我正在将一个模拟移到pyOpenCL中,无法让我的数据访问正常工作。我试图提供一个一维向量数组(实际上有几个,但我所包含的示例只使用了一个) 目前,几个向量被复制得很好,但是数据根本不是我提供的 我想我以前没有在这里发过帖子,所以如果有任何格式/表达错误,我深表歉意。另外,我刚刚剥离了所有的模拟代码,所以我意识到这段代码目前实际上没有做任何事情,我只是想让缓冲区正确通过 提前谢谢 内核(kertest.py): 将数据复制到设备的代码很好。但是,您的内核至少有两个问题: float3根据Open

我正在将一个模拟移到pyOpenCL中,无法让我的数据访问正常工作。我试图提供一个一维向量数组(实际上有几个,但我所包含的示例只使用了一个)

目前,几个向量被复制得很好,但是数据根本不是我提供的

我想我以前没有在这里发过帖子,所以如果有任何格式/表达错误,我深表歉意。另外,我刚刚剥离了所有的模拟代码,所以我意识到这段代码目前实际上没有做任何事情,我只是想让缓冲区正确通过

提前谢谢

内核(kertest.py):


将数据复制到设备的代码很好。但是,您的内核至少有两个问题:

  • float3
    根据OpenCL 1.2规范6.1.5,值应为16字节对齐:

    对于三分量矢量数据类型,数据类型的大小为4*
    sizeof
    (分量)。这意味着3分量矢量数据类型将与4*
    大小的
    (分量)边界对齐。vload3vstore3内置函数可分别用于从压缩标量数据类型数组中读取和写入三分量矢量数据类型

    上载到设备的值没有正确对齐,内核无法直接读取
    float3

  • 您的限额计算
    int lim=X*Y*3略微关闭。您已经在尝试从
    float3
    数组中读取,因此
    *3
    是多余的

  • 这两个问题的解决方案都很简单:如规范中所述,您应该使用vload3
    float
    s数组加载:

    #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);
                }
             }
    }
    
    #pragma OPENCL扩展cl_amd_printf:启用
    #定义xdim
    #定义Y ydim
    __内核无效k1(uu全局浮点*旋转,
    __本地浮动(3*tile)
    {
    ushort lid=2*获取本地id(0);
    ushort group=2*获取组id(0);
    ushort num=获取数量组(0);
    int lim=X*Y;
    对于(ushort i=0;i
    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()
    
    #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);
                }
             }
    }