OpenCL结构值对CPU正确,但对GPU不正确
OpenCL struct values correct on CPU but not on 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,%dn", 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上是垃圾。
我想在不同的设备上浮动的布局有问题。
注意:该结构包含在该类型的结构数组中,该数组中的每个结构在GPU上都是垃圾
有谁知道为什么会这样,我怎么能预测这个吗?
我在and处加了一个%d,并用1代替,结果是:1065353216EDIT:这里有两个结构体,我使用
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;
我测试了一些其他的东西,它看起来像一个问题与打印。价值观似乎是正确的。我将参数传递给返回结构体,读取它们,这些值是正确的。
我不想张贴所有相关的代码,这将是几百行。如果没有人有想法,我就把这个压缩一下。
啊,对于打印,我使用#pragma OPENCL EXTENSION cl_amd_printf : enable
。
看起来真的是打印出了问题。我再也不用它了
有一个简单的方法来检查发生了什么:
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标志创建设备端缓冲区,映射它&检查数据一致性:
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编译器有时可以"吞下"一些错误),你已经导入目录包括搜索,当构建OpenCL内核("-I"标志在clBuildProgramm阶段)
编辑:在每一步,请收集返回代码(或捕获异常)。除此之外,clBuildProgramm阶段的"-Werror"标志也很有帮助。
看起来我使用了错误的OpenCL头进行编译。如果我在英特尔平台(OpenCL 1.2)上尝试代码,一切都很好。但是在我的AMD平台(OpenCL 1.1)上,我得到了奇怪的值。
我会尝试其他标题
- 试图对缓存进行跨步测试,但程序并没有结束
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- 我正在尝试按降序对地图进行排序,但没有得到预期的结果?
- 尽管显式声明了返回类型,但对lambda的调用是不明确的
- 为什么重载运算符上的异常说明符'<<'不适用于任何 std::ostream 对象,但对库中定义的运算符不起作用?
- CIN >> 在较大的数字下失败,但对较小的数字有效?
- 使用pinvoke调用的简单C++.dll;对我有效,但对其他人无效
- WiFi上的原生C++webrtc客户端降低了视频质量,但对来自chrome的呼叫很好
- 矢量在C++对一种方法没有反应,但对其他方法很好
- C4244对复合加法赋值的4级警告,但对和和赋值没有警告
- 是否存在对类型名称有效但对基本类型无效的语言构造
- 警告 ofstream 的模棱两可,但对 ostream 则不然。有什么区别?
- 如何专门化模板类方法基于类型特征?使用std::enable_if对非类函数有效,但对类方法无效
- 语句调用构造函数,但对构造函数不做任何操作——为什么它不能编译
- cc1plus:警告:命令行选项 "-Wstrict-prototypes" 对 Ada/C/ObjC 有效,但对 C++ 无效
- OpenCL结构值对CPU正确,但对GPU不正确
- 为什么非模板化函数具有相同的名称和参数但不同的返回类型是非法的?(但对模板函数合法吗?)
- 模板默认实参SFINAE对clang有歧义,但对g++很好
- 为什么对基类的赋值有效,但对派生类的赋值是编译错误
- 以基于迭代器的方式学习C++:这对获得背景很好,但对获得工作实用吗