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

teh*_*rus 5 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);
Run Code Online (Sandbox Code Playgroud)

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

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

typedef struct {
  float position[2];
  float velocity[2];
  float radius;
  float resultant_force[2];
} ocl_element_2d_t;
Run Code Online (Sandbox Code Playgroud)

(也在内核中定义为)

const char* kernel_string = 
  "typedef struct { float position[2]; float velocity[2]; float radius; float resultant_force[2]; } ocl_element_2d_t;"...
Run Code Online (Sandbox Code Playgroud)

我使用相同/非常相似的代码写入我的struct数组的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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

teh*_*rus 2

这一切都归功于@0A0D对我选择的代码样本的怀疑。问题确实在于我未能正确初始化结构

我的借口很简单,我习惯于使用结构指针,而不是结构,所以写

ocl_element_2d_t element = host_buffer[i];
element.position[0] = 1.2;
element.position[1] = 5.7;
Run Code Online (Sandbox Code Playgroud)

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

struct_instance = other_struct_instance;
Run Code Online (Sandbox Code Playgroud)

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

因此,当我测试本地结构变量的输出时,我期望的值就在那里,但仍然离host_buffer.

这里可能有两个教训:

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