将 stuct 数组传递给内核会导致写入时出现段错误

Passing array of stuct to kernel results in segfault on write?

本文关键字:段错误 错误 数组 stuct 内核      更新时间:2023-10-16

也许我错过了教程中的一些东西,因为这让我发疯了。

我要完成的:我想为 OpenCL 设备创建一个结构数组,以用作工作区。 主机不需要以任何方式看到它或与之交互,它只是作为内核在其中工作的"暂存"空间。

这是我所拥有的:

主程序和 OpenCL 内核均可访问的头文件中的结构声明:

typedef struct {
    uint64_t a;
    uint32_t b;
} result_list;

初始化暂存空间缓冲区"outputBuffer"以保存MAX_SIZE元素:

      cl_mem outputBuffer;
      outputBuffer = clCreateBuffer(this->context,
                                    CL_MEM_READ_WRITE,
                                    sizeof(result_list) * MAX_SIZE,
                                    NULL,
                                    &status);

我从不打电话给clEnqueueWriteBuffer,因为主机不在乎内存是什么。 它只是作为内核的工作空间。 我将其保留为未初始化但已分配。

将其设置为内核要使用的参数:

status = clSetKernelArg(myKernel,
                        1,
                        sizeof(cl_mem),
                        &this->outputBuffer);

内核(简化为删除非问题部分):

__kernel void kernelFunc(__global const uint32_t *input, __global result_list *outputBuffer) {
    if (get_global_id(0) >= MAX_SIZE) { return; }
    // Make a few local variables and play with them
    outputBuffer[0].a = 1234;  // Memory access violation here
    // Code never reaches here
}

我做错了什么?


我从AMD安装了CodeXL,它对调试此类问题没有多大帮助。 它给我的最多是"线程试图读取或写入它无权访问的虚拟地址"。


编辑:似乎它真的不喜欢typedefs。 我没有使用结构体,而是将其简化为typedef uint64_t result_list并且它拒绝编译,说"类型'ulong'的值不能分配给类型'result_list'的实体",即使result_list -> uint64_t ->无符号长。

您的问题是您不能将主机和设备的定义都放在一个标头中。您必须像这样将它们分开:

//HOST header
struct mystruct{
    cl_ulong a;
    cl_uint b;
};
//DEVICE header
typedef struct{
    ulong a;
    uint b;
} mystruct;

请注意,我还将数据类型更改为标准 OpenCL 数据类型。为了兼容,您应该改用它们。