为什么我从 `clSetKernelArg` 得到 `CL_INVALID_MEM_OBJECT`?

Why do I get `CL_INVALID_MEM_OBJECT` from `clSetKernelArg`?

我即将完成将一些 CUDA 代码重写为 OpenCL 的工作。但是我遇到了这个可怕的运行时错误。

我调用的内核接受这样的参数:

__kernel void kernel_forwardProject(
  __global float *proj_out,
  __gloabl float *proj_in,
  __global float *vol,
  __read_only image3d_t tex_vol,
  __constant float *transformMatrices,
  __constant float *sourcePositions)

我正在使用 OpenCL 的 cl2.hpp 包装器,当我为参数 0 调用 clSetKernelArg 的等价物时,即 proj_out,返回 CL_INVALID_MEM_OBJECT

我在切换参数 0 和 1 时也得到相同的结果。 我已经尝试了我知道的三种分配设备缓冲区的方法:

// 1)
  auto dev_proj_out = cl::Buffer(queue, h_proj_out, h_proj_out + proj_size,
    /*read_only*/false, /*useHostPtr*/true, &err);
// 2)
  auto dev_proj_out = cl::Buffer(ctx, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
    proj_size * sizeof(float), (void*)&h_proj_out[0], &err);
// 3)
  auto dev_proj_out = cl::Buffer(ctx, CL_MEM_WRITE_ONLY,
    req_dev_alloc, nullptr, &err);
  queue.enqueueWriteBuffer(dev_proj_out, CL_TRUE, 0, 0, (void *)&h_proj_out[0]);

h_proj_out在测试用例中是float*proj_size64*64*16。 我已经为 read_onlyuseHostPtr.

尝试了 falsetrue 的所有 4 种组合

我在所有 OpenCL API 调用之后检查 err,在 clSetKernelArg 之前没有错误。

我已经使用 gdb 逐步完成所有组合的代码,第一个参数总是在 clSetKernelArg 处给出错误。

我已经尝试了两种 Nvidia and Intel CPU OpenCL 运行时。 (POCL 不支持 nvidia gpus 的图像类型,所以我不能使用它)

主机代码可以在这里找到:https://gitlab.com/agravgaard/cbctrecon/blob/master/Library/CbctReconLib/rtkExtension/rtkOpenCLForwardProjectionImageFilter.cpp#L130

OpenCL 内核: https://gitlab.com/agravgaard/cbctrecon/blob/master/Library/CbctReconLib/rtkExtension/forward_proj.cl#L71 内核使用面向 OpenCL 离线编译器的英特尔 SDK 进行编译,没有任何警告(与运行时给出的定义相同)。

错误发生在line 247 of the host code. The KernelFunctor calls setArgs<> which calls setArg of the kernel, which calls clSetKernelArg at line 5398 of cl2.hpp

问题有两个部分来自混合设备、上下文和队列以及内核管理。

如果给定 none,cl2.hpp 使用默认设备、上下文和队列。由于我与上面示例中的默认值不一致,因此不同的队列和上下文 "owned" 不同的对象。

我最初通过重写我管理内核的方式摆脱了 CL_INVALID_MEM_OBJECT,包括添加:

program.createKernels(&kernel_list)

并使用该列表初始化 KernelFunctor