【问题标题】:How to pass array of ctypes structures to pyOpenCL?如何将 ctypes 结构数组传递给 pyOpenCL?
【发布时间】:2020-04-19 10:37:41
【问题描述】:

我一直在关注使用 OpenCL 的在线教程,我在其中使用 python 和 pyOpenCL 做所有事情。作为我的问题的一个精简示例,我需要将一个 C 结构数组作为参数传递给 OpenCL 内核。

这是一个人工的 OpenCL 代码示例:

typedef struct Test{
    float a;
    float3 b;
} Test;

__kernel void render_kernel(__constant Test *tests, const int width, const int height, const int num_structs, __global float3* output)
{
    unsigned int work_item_id = get_global_id(0);
    unsigned int x_coord = work_item_id % width;
    unsigned int y_coord = work_item_id / width;

    Test test = tests[0];
    output[work_item_id] = test.b;
}

这会做一些愚蠢的事情,只是将float3 数组之一作为输出,但我只需要知道我实际上正在正确地将数据传递给内核。

我正在尝试使用以下代码在 python 端模拟这些结构的数组:

class Test(ctypes.Structure):
    _fields_ = [
        ("a", ctypes.c_float),
        ("b", (ctypes.c_float * 4))
    ]

class Test_Array(ctypes.Structure):
    _fields_ = [("TEST_ARRAY", ctypes.POINTER(Test))]

    def __init__(self, num_structs):
        elems = (Test * num_structs)()
        self.TEST_ARRAY = ctypes.cast(elems, ctypes.POINTER(Test))
        self.elements = num_structs
        for num in range(0, num_structs):
            self.TEST_ARRAY[num].a = 1.0
            self.TEST_ARRAY[num].b = (1.0, 0.0, 0.0, 1.0)

num_structs = 2

test_arr = Test_Array(num_structs)

#host buffer
color_out = np.empty((win.width * win.height, 4), dtype=np.float32)

cl_prog = CL()
cl_prog.load_program("shaders/struct.cl")

#device buffers
cl_structs = cl_prog.create_input_buffer(num_structs * ctypes.sizeof(Test))
cl_output = cl_prog.create_output_buffer(color_out.nbytes)

cl.enqueue_fill_buffer(cl_prog.queue, cl_structs, test_arr.TEST_ARRAY,
 0, num_structs * ctypes.sizeof(Test))

global_work_size = (win.width * win.height,)

cl_prog.program.render_kernel(cl_prog.queue, global_work_size, None,
                              cl_structs, np.int32(win.width), np.int32(win.height), 
                              np.int32(num_structs), cl_output)

cl_prog.retrieve_data(color_out, cl_output)
print(color_out)

这并不真正相关,因为此类中的函数只是 pyOpenCL 函数的包装器,但这里是实例化的 CL 类。

class CL:
    def __init__(self):
        self.platform = cl.get_platforms()[0]
        self.device = self.platform.get_devices()[0]
        self.ctx = cl.Context([self.device])
        self.queue = cl.CommandQueue(self.ctx)

    def load_program(self, file_path):
        with open(file_path) as f:
            src = f.read()
            self.program = cl.Program(self.ctx, src).build()

    def create_output_buffer(self, size):
        """
        creates and returns a write only cl.Buffer of size bytes.
        """
        mf = cl.mem_flags
        return cl.Buffer(self.ctx, mf.WRITE_ONLY, size)

    def create_input_buffer(self, size):
        """
        returns a read only cl.Buffer of size bytes.
        """
        mf = cl.mem_flags
        return cl.Buffer(self.ctx, mf.READ_ONLY, size)

    def retrieve_data(self, host_buffer, device_buffer):
        """
        retrieves data from a buffer on the device, device_buffer, and copies it
        over to host_buffer
        """
        cl.enqueue_copy(self.queue, host_buffer, device_buffer)

    def fill_buffer(self, memory, pattern, offset, size, wait_for=None):
        """
        A wrapper around cl.enqueue_fill_buffer which uses self.queue
        """
        cl.enqueue_fill_buffer(self.queue, memory, pattern, offset, size, wait_for)

    def enqueue_copy(self, device_buffer, host_buffer):
        cl.enqueue_copy(self.queue, device_buffer, host_buffer)

当我运行上面的代码时,它编译并运行良好,但我从缓冲区返回的信息只是内存中已经存在的垃圾。我不知道我的问题是与数据对齐、创建 ctypes 结构数组的方式有关,还是什么?

我不喜欢使用 C 结构的 C 数组。我怀疑有一种方法可以用 numpy 数组来做到这一点,但我想不通。任何将数据从主机正确获取到设备的方法都将不胜感激。

【问题讨论】:

    标签: python opencl ctypes pyopencl


    【解决方案1】:

    早在 2014 年就有人建议,这也许可以这样做:

    __kernel void render_kernel(struct Params Test, ...){
    
    }
    

    你可以看到这个post.

    否则,可以选择名为 Attributes of Variables 的东西?

    希望您能解决这个问题并分享经验。我很想看看这是如何完成的,因为我可能想尝试将 SQL 查询传递给内核进行处理。

    【讨论】:

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