处理结构的OpenCL缓冲区的正确方法是什么?

时间:2014-08-27 23:46:50

标签: c++ opencl

我有以下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缓冲区的正确方法是什么?

2 个答案:

答案 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);
相关问题