【问题标题】:How to pass an array of vectors in pyOpenCL如何在pyOpenCL中传递向量数组
【发布时间】:2012-07-31 09:16:09
【问题描述】:

我正在将模拟移动到 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);
            }
         }
}"""

代码本身(gptest.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()

【问题讨论】:

    标签: opencl pyopencl


    【解决方案1】:

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

    1. float3 值应为 16 字节对齐,根据 OpenCL 1.2 Spec, 6.1.5:

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

      您上传到设备的值未正确对齐,内核无法直接读取float3 值。

    2. 您的限额计算int lim = X*Y*3; 略有偏差。您已经在尝试从 float3 的数组中读取数据,因此 *3 是多余的。

    解决这两个问题的方法很简单:如规范中所述,您应该使用 vload3floats 的数组中加载:

    #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);
                }
             }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多