我有以下OpenCL内核:
//OPENCL KERNEL
struct MyStruct
{
float A;
float B;
float C;
float D;
float E;
};
__kernel void kernelMain(struct MyStruct* outputBuffer)
{
size_t idx = get_global_id(0);
//Do some stuff here with the outputBuffer
outputBuffer[idx].A = 42.0;
}
如您所见,它定义了一个名为MyStruct的自定义类型。
在主机方面,我有相同的结构定义(copy-pasta' d):
//HOST SIDE
struct MyStruct
{
float A;
float B;
float C;
float D;
float E;
};
我正在尝试创建一个用于写入内核数据的缓冲区,同样是主机端代码:
//HOST SIDE
cl::Buffer outputBuffer(clContext, CL_MEM_READ_WRITE, (size_t)numElements * sizeof(MyStruct));
clKernel.setArg(0, outputBuffer);
当我调用clKernel.setArg时会出现问题。它失败了,错误代码为-51,根据OpenCL文档,这是一个内核无效的参数大小错误。
我尝试过使用openCL数据类型,重新编写struct的主机定义:
struct MyStruct
{
cl_float A;
cl_float B;
cl_float C;
cl_float D;
cl_float E;
};
但这也是错误的。
我的问题是: 创建用于处理自定义结构的OpenCL缓冲区的正确方法是什么?
答案 0 :(得分:1)
如果添加__global
关键字无效,则听起来可能有different struct padding between host and device。这会使结构中的结构或数据位置的大小不同。结构填充为platform and compiler dependent。
在使用OpenCL在主机和设备上使用相同的结构时,您应该考虑这一点。特别是如果您将软件定位到多个平台。
一种解决方法是使用浮点数组在主机和设备之间移动数据。
答案 1 :(得分:1)
如果您能够使用C ++,则可以使用BOOST_COMPUTE_ADAPT_STRUCT()
宏来处理包装结构并使其可用于OpenCL内核。
包装后,您可以使用boost::compute::vector<T>
容器类为结构集合创建一个OpenCL内存缓冲区:
// adapt "MyStruct" for OpenCL
BOOST_COMPUTE_ADAPT_STRUCT(MyStruct, MyStruct, (A, B, C, D, E));
// create a OpenCL buffer with 100 "MyStruct" objects
boost::compute::vector<MyStruct> my_structs(100);
// use "my_structs" with an opencl kernel
my_kernel.set_arg(0, my_structs);