如何使用OpenCL和OpenCL数组传递OpenCL变量

2024-09-26 18:03:49 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我必须使用PyOpenCL或使用Python将一些数据传递给OpenCL内核。数据在内核端作为一个结构读取,我不能改变内核,因为它运行良好,是我的代码必须处理的更大项目的一部分。在

内核如下所示:

typedef struct VglClStrEl{ 
    float data[VGL_ARR_CLSTREL_SIZE];
    int ndim;
    int shape[VGL_ARR_SHAPE_SIZE];
    int offset[VGL_ARR_SHAPE_SIZE];
    int size;
} VglClStrEl;

typedef struct VglClShape{ 
    int ndim;
    int shape[VGL_ARR_SHAPE_SIZE];
    int offset[VGL_ARR_SHAPE_SIZE];
    int size;
} VglClShape;

__kernel void kernel(__global unsigned char* img_input, 
                     __global unsigned char* img_output,  
                     __constant VglClShape* img_shape,
                     __constant VglClStrEl* window)
{

    // do what is needed

}

因此,如您所见,VglClShape和VglClStrEl结构具有不同的类型数组和静态位大小变量。在

[1]解决方法只支持一个类型数组的结构(或者不幸的是,我未能找到一种方法来处理多个数组类型)。在

关于如何将Python数据传递到OpenCL内核结构的方法,[2]解决方法是PyOpenCL文档参考。这种方法根本不支持数组。在

那么,如何在OpenCL内核可以读取的情况下传递python数据呢?我已经有了Python端的所有数据,我只需要知道如何将数据从Python传递到内核。在

在你问:我正在使用python3,我不能更改内核。在

是的,数组大小是静态的。你可以这样假设:

^{pr2}$

[1]Passing struct with pointer members to OpenCL kernel using PyOpenCL

[2]https://documen.tician.de/pyopencl/howto.html#how-to-use-struct-types-with-pyopencl


Tags: 数据方法pyopenclsize数组结构内核struct
1条回答
网友
1楼 · 发布于 2024-09-26 18:03:49

有一种老套的方法需要一些乏味的字节争论。假设您对部署一个小型OpenCL探测内核没问题吧?(PyOpenCL在某些情况下会在引擎盖下执行此操作)

其基本思想是:

  • 了解OpenCL设备如何通过运行单个实例内核来对齐结构的所有元素
  • 创建一个numpy字节数组以匹配OpenCL结构的大小
  • 按字节将Python结构的每个元素复制到此数组中
  • 当调用不可更改的OpenCL内核时,通过一包字节缓冲区传递这个数组

以下内核执行此任务:

__kernel void get_struct_sizes( __global uint *struct_sizes )
{
    const uint global_id = get_global_id(0u)+get_global_id(1u)*get_global_size(0u);
    VglClStrEl vgclstrel;
    VglClShape vgclshape;
    uint offset;

    printf("In GPU (probing):\n Kernel instance = %d\n", global_id);

    if (global_id==0) {
        offset = (uint)&(vgclstrel.data);
        struct_sizes[0] = (uint)sizeof(vgclstrel);
        struct_sizes[1] = (uint)&(vgclstrel.ndim)-offset;
        struct_sizes[2] = (uint)&(vgclstrel.shape)-offset;
        struct_sizes[3] = (uint)&(vgclstrel.offset)-offset;
        struct_sizes[4] = (uint)&(vgclstrel.size)-offset;
        offset = (uint)&(vgclshape.ndim);
        struct_sizes[5] = (uint)sizeof(vgclshape);
        struct_sizes[6] = (uint)&(vgclshape.shape)-offset;
        struct_sizes[7] = (uint)&(vgclshape.offset)-offset;
        struct_sizes[8] = (uint)&(vgclshape.size)-offset;
    }
    return;
}

执行此内核并将struct_sizes返回到vgclshape_sizes,创建此数组:

^{pr2}$

把你需要的东西复制进去:

^{3}$

我跳过了一些步骤;把它们填进去你会发现这种方法很有效。我能够将一个demo结构传递给你的不可侵犯内核的一个虚拟副本。在

我很想知道是否有更优雅的方法来完成这些步骤。我也希望在endianness等方面会有一些问题,否则会是透明的。幸运的话,你可以在他们身边工作。在

相关问题 更多 >

    热门问题