在Zig中使用OpenCL创建无效内存对象的问题排查
问题分析与解决
你的代码核心问题出在clSetKernelArg的调用方式上。OpenCL的clSetKernelArg函数要求第四个参数必须是指向参数值的指针,而非参数值本身。
看你原代码里的这两行:
ret = c.clSetKernelArg(kernel, 0, @sizeOf(c.cl_mem), input_buffer); ret = c.clSetKernelArg(kernel, 1, @sizeOf(c.cl_mem), output_buffer);
这里直接把input_buffer(c.cl_mem类型,本质是指针)作为第四个参数传入,相当于把指针的数值当成了内存地址,内核实际读取到的是错误地址,自然触发"无效内存对象"的错误。
修正后的代码
将这两行改为传递指针的地址:
ret = c.clSetKernelArg(kernel, 0, @sizeOf(c.cl_mem), &input_buffer); // 现在input_buffer的地址被正确传入,内核能拿到有效的内存对象句柄 std.log.debug("{d}: {s}", .{ ret, @tagName(@as(CLErrorCode, @enumFromInt(-ret))), }); if (ret != c.CL_SUCCESS) { return CLError.SetKernelArgFailed; } ret = c.clSetKernelArg(kernel, 1, @sizeOf(c.cl_mem), &output_buffer); try handle_error(ret);
补充说明
clSetKernelArg的设计逻辑是通过指针,把用户空间的参数值拷贝到OpenCL运行时管理的内核参数存储区。对于cl_mem类型的参数,需要传递cl_mem变量的地址,这样运行时才能正确拷贝句柄值。- 你之前的
clEnqueueWriteBuffer调用是正确的,因为它的参数要求直接传入cl_mem对象句柄,无需传递地址。
内容的提问来源于stack exchange,提问作者Ben Miller
相关产品推荐
相关产品推荐

