首页 > 解决方案 > OpenCL 在 GPU 上分配结构会导致垃圾

问题描述

我在 C++ 主机代码中定义了以下结构:

    struct __declspec(align(16)) MyNode {
    cl_uchar        mData;
    cl_int3         mPos;
};

在 OpenCL 中:

struct  __attribute__((aligned(16))) MyNode {
    uchar mData;
    int3 mPos;
};

现在从主机代码我打电话:

MyNode node= {0};
node.mPos.x = 1;
node.mPos.y = 2;
node.mPos.z = 3;

cl_mem clnode_mem = clCreateBuffer(
        mOpenCLctx, 
        CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, 
        sizeof(MyNode), 
        &node, 
        &err);

clSetKernelArg(m_kernel_test, 0, sizeof(cl_mem), &clnode_mem));

然后我在 GPU 上调用一个测试内核,定义为:

__kernel void test(__global MyNode* node)
{
    printf("pos = %d,%d,%d\n",
        node->mPos.x,
        node->mPos.y,
        node->mPos.z);
}

但我看到的输出是pos = 0,0,0,如果我mData从主机和设备结构定义中删除该成员,那么它打印正确。这里发生了什么 ?

我正在使用具有 x64 配置的 VS2015 构建并在 NVIDIA GPU 上运行 OpenCL 1.2。

标签: c++openclgpgpugpu

解决方案


似乎可能是对齐问题。int3可能有 16 字节对齐,而 C 类型cl_int3可能只有 4 字节对齐。所以内核会在偏移量 16 处寻找它,而 CPU 在偏移量 4 处提供它。

一个好的完整性检查是打印sizeof(MyNode)主机和内核。如果这些不同,我建议为结构字段尝试显式数量的填充或对齐注释。


推荐阅读