OpenCL结构值在CPU上正确但在GPU上不正确

时间:2014-06-27 11:33:02

标签: c++ c floating-point opencl gpu

我在主机代码和内核

中包含的文件中有一个结构
typedef struct {
    float x, y, z,
          dir_x, dir_y, dir_z;
    int     radius;
} WorklistStruct;

我在我的c ++主机代码中构建这个结构,并通过缓冲区将它传递给OpenCL内核。

如果我选择CPU设备进行计算,我将得到以下结果:

 printf ( "item:[%f,%f,%f][%f,%f,%f]%d,%d\n", item.x, item.y, item.z, item.dir_x, item.dir_y,
                 item.dir_z , item.radius ,sizeof(float));

主机:

item:[20.169043,7.000000,34.933712][0.000000,-3.000000,0.000000]1,4

设备(CPU):

item:[20.169043,7.000000,34.933712][0.000000,-3.000000,0.000000]1,4

如果我选择GPU设备(AMD)进行计算,则会发生奇怪的事情:

主机:

item:[58.406261,57.786015,58.137501][2.000000,2.000000,2.000000]2,4

设备(GPU):

item:[58.406261,2.000000,0.000000][0.000000,0.000000,0.000000]0,0

值得注意的是,sizeof(float)在gpu上是垃圾。

我认为不同设备上的浮动布局存在问题。

注意:struct包含在这种类型的结构数组中,并且此数组中的每个结构都是GPU上的垃圾

任何人都知道为什么会出现这种情况以及如何预测这一点?

编辑我在和添加了%d并将其替换为1,结果是:1065353216

编辑:这里有两个我使用的结构

typedef struct {
      float x, y, z,//base coordinates 
      dir_x, dir_y, dir_z;//directio
      int     radius;//radius
} WorklistStruct;

typedef struct {
    float base_x, base_y, base_z; //base point 
    float radius;//radius 
    float dir_x, dir_y, dir_z; //initial direction
} ReturnStruct;

我测试了一些其他的东西,看起来像printf的问题。价值似乎是正确的。我将参数传递给了返回结构,读取它们并且这些值是正确的。

我不想发布所有相关代码,这将是几百行。 如果没有人有想法,我会稍微压缩一下。

啊,打印我使用#pragma OPENCL EXTENSION cl_amd_printf : enable

修改 看起来真的像printf的问题。我根本就不再使用它了。

2 个答案:

答案 0 :(得分:2)

有一种简单的方法可以检查会发生什么:

1 - 创建主机端数据&初始化它:

int num_points = 128;

std::vector<WorklistStruct> works(num_points);
std::vector<ReturnStruct> returns(num_points);

for(WorklistStruct &work : works){
    work = InitializeItSomehow();
    std::cout << work.x << " " << work.y << " " << work.z << std::endl;
    std::cout << work.radius << std::endl;
}

// Same stuff with returns
...

2 - 使用COPY_HOST_PTR标志创建设备端缓冲区,映射它&amp;检查数据一致性:

cl::Buffer dev_works(..., COPY_HOST_PTR, (void*)&works[0]);
cl::Buffer dev_rets(..., COPY_HOST_PTR, (void*)&returns[0]);

// Then map it to check data
WorklistStruct *mapped_works = dev_works.Map(...);
ReturnStruct *mapped_rets = dev_rets.Map(...);

// Output values & unmap buffers
...

3 - 像以前一样检查设备端的数据一致性。

另外,确保代码(可能是 - 标题),包含在内核和内容中。主机端代码是纯OpenCL C(AMD编译器有时可以&#34;吞下&#34;一些错误)以及您在构建OpenCL内核时包含搜索的导入目录(&#34; -I&#34 ;在clBuildProgramm阶段标记)

编辑: 在每一步,请收集返回代码(或捕获例外)。除此之外,&#34; -Werror&#34; clBuildProgramm阶段的标志也可以是有用的。

答案 1 :(得分:0)

看起来我使用错误的OpenCL标头进行编译。如果我在英特尔平台上试用代码(OpenCL 1.2),一切都很好。但是在我的AMD平台(OpenCL 1.1)上,我得到了奇怪的价值。

我会尝试其他标题。