Hi, RoaTheChaos,
你的代码已经阅读, 请注意你存在多处理解和概念上的BUG:
(1) OpenCL因为要兼容多种硬件, 它们具有不同的访存对齐性要求, 因此float3被规范定义成没有最后一个分量的float4, 这意味着在OpenCL中:
大小: sizeof(float3) == 16 //不是你认为的12!
对齐性要求: float3 MUST be aligned to 16B边界! 不是你认为的对齐到4B的边界.
这点是和CUDA的显著区别. 来自CUDA的人要特别注意点和OpenCL的区别.
(2)OpenCL规范不约定Host Compiler和设备端的Struct的内存中的layout一致性.
这是因为OpenCL要针对多种不同的Host C Compiler, 而每种Host C Compiler甚至可能互相之间就布局不同.
甚至更为严重的, Host Compiler根本就不是C编译器, 连struct这个概念都没有.
这就是为何所说的, struct不能在host和device间传递. 否则将导致未定义的结果.
这点也是来自CUDA的人经常犯错的一点. 因为CUDA要求了这一点. Host编译器和设备端的struct编译结果相同. 但是OpenCL却从来没有约定这一点.
(3)在OpenCL 2.0之前, 指针在Device上和Host上不能等价. 例如sizeof(void *)可能在host和device上是两种不同的结果. 甚至OpenCL 1.2根本可能就没有一个扁平的内存布局(segmented).
建议的解决方案:
(A) 不使用struct. 在OpenCL的设备端和主机端传递struct本身就是一个错误.
(B) 凑合勉强使用. 但修补你的struct使它尽量在Host和Device间以致.
例如如果你这里其他元素都能布局一致(特别小心指针). 而已经定位问题在Point上, 可以考虑尽量通过1个4B的元素(例如float或者int)的padding, 来修补成一致.
但(B)方案不建议. 这只能凑合, 依然有潜伏的BUG. 特别是当你更换编译环境的时候.
Regards,
屠戮人神.