为什么我不能正确地将结构中的数据复制到openCL cl_mem缓冲区?

时间:2011-10-06 13:58:10

标签: c opencl

好的,所以我把它分解为一个非常具体的问题。

我的印象是你可以将OpenCL传递给数组缓冲区中的任何类型的数据; int,chars,你自己的自定义结构,只要它只是数据而且不包含指向GPU无法检索的堆对象的指针。

现在,我已经尝试了这个,我认为它适用于大量的整数,但是我的结构数组失败了。具体地,

cl_mem log_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, 
  num_elements * sizeof(int), NULL, NULL);

int* error_codes_in = (int*)malloc(num_elements * sizeof(int));

for (i = 0; i < num_elements; i++) {
  error_codes_in[i] = i;
}

error = clEnqueueWriteBuffer(command_queue, log_buffer, CL_TRUE,
  0, num_elements * sizeof(int), error_codes_in, 0, NULL, NULL);

这很好用,我在GPU上获得了一组数字,可以并行地成功操作它们。

但是,当我使用自己的自定义结构时:

typedef struct {
  float position[2];
  float velocity[2];
  float radius;
  float resultant_force[2];
} ocl_element_2d_t;

(也在内核中定义为)

const char* kernel_string = 
  "typedef struct { float position[2]; float velocity[2]; float radius; float resultant_force[2]; } ocl_element_2d_t;"...

我使用相同/非常相似的代码写入我的struct array的GPU版本:

cl_mem gpu_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE,
  num_elements * sizeof(ocl_element_2d_t), NULL, NULL);

error = clEnqueueWriteBuffer(command_queue, (cl_mem)gpu_buffer, CL_TRUE,
  0, num_elements * sizeof(ocl_element_2d_t), host_buffer, 0, NULL, NULL);

我在GPU中获得了空白值,偶尔会在结构中的所有浮点值中出现垃圾(350或3中的三个或四个值)。两个返回值均为CL_SUCCESS

关于我哪里出错的任何建议?我唯一的想法是GPU编译器在内存中生成一个具有不同间隙的结构,并且由于复制方法忽略了项目的内部结构并且只是复制了一个连续的RAM块,因此最终会出现不匹配和可能的异相项。我的操作系统是否可能是i7(四核)上的64位(OS X Lion),而我的GPU运行的是32位,这就是问题所在?它是ATI Radeon HD 5750,没有双精度支持,并声称拥有128位总线(可能相关或不相关,我不知道这些东西究竟是什么意思。)

有没有正确的方法呢?我是否必须使用所有FORTRAN并拥有7个不同的数组,每个数组都有自己的内核参数,用于结构中的不同属性?

2 个答案:

答案 0 :(得分:2)

由于对我的选择性代码示例持怀疑态度,所有归功于@0A0D。问题确实存在于我未能正确初始化结构

我的理由只是我习惯使用struct指针,而不是结构,所以写

ocl_element_2d_t element = host_buffer[i];
element.position[0] = 1.2;
element.position[1] = 5.7;

是向对象添加属性的标准方法。我有一个快速的结构谷歌,我遇到了一个非常非常基本的C教程,http://www.asic-world.com/scripting/structs_c.html指出

struct_instance = other_struct_instance;

执行深层复制,而不是参考副本。

因此,当我测试 local struct变量的输出时,我期待的值就在那里,但仍然不在host_buffer的数组附近。

这里可能有两个教训:

  1. 确保在询问StackOverflow问题时发布所有相关代码 - 包括所有初始化 - 以便可以考虑所有可能的问题。
  2. 使用库时,特别是像OpenCL这样复杂的库,不要认为它的开发人员会犯下愚蠢的错误 - 他们几乎肯定是你自己的!

答案 1 :(得分:0)

我不确定你的编译器如何对齐你的'浮动'结构,但是你可以尝试使用gcc:

#pragma pack(1)

让它无间隙地对齐。

撤消此包装使用:

#pragma pack()

您也可以尝试重新排列成员,如下所示:

typedef struct {
  float position[2];
  float velocity[2];
  float resultant_force[2];
  float radius;
} ocl_element_2d_t;