我在OpenCL中的主机和设备之间的对齐结构时遇到麻烦。我在主机和设备上定义了许多自定义结构,除了一个。
我正在阵列中的两个结构上发送。第一个结构中的所有值(Sobject [0](都在设备中正确读取,但是第二个(sobject [1](的读数是以一种看似损坏的方式读取的,其中所有值都被混合在一起并且有些丢失。
根据我阅读的内容,这可能是数据对齐的问题,在该数据对齐中,主机和设备可能具有不同的类型分配或填充,但我已经验证了数据类型在主机和设备上都具有相同的大小我尝试使用诸如#pragma pack(8)
,__attribute__ ((aligned (128)))
和__attribute__ ((packed))
之类的对齐方式,尽管我不确定它们是否与编译器合作(VS2017(。
这是主机和设备上的结构的代码:
主机:
typedef struct _cl_tag_sObject {
cl_double3 m_vCenter;
cl_double3 m_vBounds1;
cl_double3 m_vBounds2;
cl_double m_dRadius;
cl_bool m_type;
} sObject;
设备:
typedef struct _cl_tag_sObject {
double3 m_vCenter;
double3 m_vBounds1;
double3 m_vBounds2;
double m_dRadius;
bool m_type;
} sObject;
这是主机上的分配值,以及从设备读取的值:
主机:
m_vCenter = (0,-100.5,0)
m_vBounds1 = (2,2,2)
m_vBounds2 = (3,3,3)
m_dRadius = 100
m_type = 0
设备:
m_vCenter = (0,0,2)
m_vBounds1 = (2,0,3)
m_vBounds2 = (3,0,100)
m_dRadius = 1
m_type = 0
似乎省略了-100.5
的值,(2,2,2)
和(3,3,3)
中的中间值正在代替填充,尽管我是OpenCL的新手,并且不确定此过程如何实际工作。
是什么引起了这个问题,如何解决?
谢谢。
wrt结构包装:__attribute__ ((packed))
导致GCC和LLVM上的结构元素之间的零填充。我不知道您的设备的实现是否使用它们。我几乎没有VS的经验,但我认为#pragma pack(1)
是您在主机方面需要获得零填充所需的。
除了打包外,您还需要意识到cl_<type>3
类型在cl/cl_platform.h标头中类型为cl_<type>4
类型。因此,在 host 方面,它们本质上是相同的。
因此,即使包装包装,您的结构也具有4个元素的cl_double4,并且在主机内存中应该像这样(铸造到双打数组(:
0 100.5 0 0 | 2 2 2 0 | 3 3 3 0 | 100
i 可疑您的设备的编译器忽略了主机约定,而是为double3使用True 3元素向量。您可以简单地通过更改设备端结构以使用Double4:
来验证 double4 m_vCenter;
double4 m_vBounds1;
double4 m_vBounds2;
不幸的是,结构是OpenCL中的灰色区域。最好避免结构内的3个元素向量。