gpt4 book ai didi

c++ - clEnqueueNDRangeKernel 触发 CL_INVALID_MEM_OBJECT (-38)

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:10:58 40 4
gpt4 key购买 nike

我正在为 OpenCL 使用 C++ 绑定(bind),当我的一个内核入队时,我得到一个 cl::Error,它说 -38 (CL_INVALID_MEM_OBJECT) for clEnqueueNDRangeKernel.

此错误未列为 clEnqueueNDRangeKernel 的可能错误之一.通知功能给我以下输出:

CL_INVALID_MEM_OBJECT error executing CL_COMMAND_NDRANGE_KERNEL on GeForce GTX 560 (Device 0).

我还没有找到展示这种行为的最小示例。

在调用这个函数时,什么会导致这种错误?

使用谷歌我只找到了这个 answer然而。它声明我需要重新setKernelArg 附加的内存对象(如果它已更新)。 (至少这是我对它的解释,没有详细解释更新的含义。)然而,我怀疑这是正确的,尽管我无法证明这一点。也许您知道这方面的官方消息来源?

更新

经过一些测试,我发现向内核添加一个 __global const float* 参数会引入错误。我还发现,如果我在另一个(已经存在的)参数之后 clSetKernelArg 这个新参数,那么每次都会发生错误。如果我在设置另一个参数之前这样做,它会每隔两次工作一次。当然这不是一个选项,因为我需要能够随时设置参数。

更新2

我注意到通过调试单步执行代码会“重新引入”我在另一个参数之前设置新参数的版本中的错误。 (这意味着错误每次都会再次发生。)

这可能是某种竞争条件吗?我自己不使用多线程,但在调试器中有 7 个线程可能来自 Qt 或 OpenCL。

最小工作示例

#include <CL/cl.hpp>
#include <vector>
#include <iostream>

#define STRINGIFY(x) #x

std::string kernel = STRINGIFY(
__kernel void apply(__global const float *param1)
{
}
);


template <class T>
cl::Buffer genBuffer(const cl::Context &context, const std::vector<T> &data,
cl_mem_flags flags = CL_MEM_READ_ONLY)
{
return cl::Buffer(context, flags | CL_MEM_COPY_HOST_PTR,
data.size() * sizeof(data[0]),
const_cast<T*>(&data[0]));
}

int main()
{
std::vector<cl::Platform> clPlatforms;
cl::Platform::get(&clPlatforms);
cl_context_properties props[] = {
CL_CONTEXT_PLATFORM, (cl_context_properties)clPlatforms[0](),
0};
cl::Context clContext = cl::Context(CL_DEVICE_TYPE_GPU, props);
std::vector<cl::Device> devices = clContext.getInfo<CL_CONTEXT_DEVICES>();
if(devices.empty())
{
std::cerr << "No devices found!\n";
exit(-1);
}
cl::Device clDevice = devices[0];
cl::CommandQueue clQueue = cl::CommandQueue(clContext, clDevice, 0, 0);
cl::Program program(clContext, cl::Program::Sources(1,
std::make_pair(kernel.c_str(), kernel.size())));
program.build(devices);
cl::Kernel kernel(program, "apply");

//this introduces the error
kernel.setArg(0, genBuffer(clContext, std::vector<cl_float>(100));
//the error is triggered here
clQueue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(100), cl::NullRange);
}

最佳答案

问题是我将缓冲区附加到内核,假设内核会保留缓冲区。然后我销毁了所有引用 cl::Buffer/Memory 的对象,这导致 OpenCL 实现删除缓冲区。


通过 valgrind 运行我的程序后,我注意到 opencl.so 访问了先前在 cl::~Buffer 子例程中释放的对象的内存。继续阅读 clSetKernelArg我注意到:

Users may not rely on a kernel object to retain objects specified as argument values to the kernel.

不确定的行为显然是驱动程序访问释放的内存区域从而进入 UB 域的结果。

修正后的 MWE

#include <CL/cl.hpp>
#include <vector>
#include <iostream>

#define STRINGIFY(x) #x

std::string kernel = STRINGIFY(
__kernel void apply(__global const float *param1)
{
}
);


template <class T>
cl::Buffer genBuffer(const cl::Context &context, const std::vector<T> &data,
cl_mem_flags flags = CL_MEM_READ_ONLY)
{
return cl::Buffer(context, flags | CL_MEM_COPY_HOST_PTR,
data.size() * sizeof(data[0]),
const_cast<T*>(&data[0]));
}

int main()
{
std::vector<cl::Platform> clPlatforms;
cl::Platform::get(&clPlatforms);
cl_context_properties props[] = {
CL_CONTEXT_PLATFORM, (cl_context_properties)clPlatforms[0](),
0};
cl::Context clContext = cl::Context(CL_DEVICE_TYPE_GPU, props);
std::vector<cl::Device> devices = clContext.getInfo<CL_CONTEXT_DEVICES>();
if(devices.empty())
{
std::cerr << "No devices found!\n";
exit(-1);
}
cl::Device clDevice = devices[0];
cl::CommandQueue clQueue = cl::CommandQueue(clContext, clDevice, 0, 0);
cl::Program program(clContext, cl::Program::Sources(1,
std::make_pair(kernel.c_str(), kernel.size())));
program.build(devices);
cl::Kernel kernel(program, "apply");

//this version triggers the error
//kernel.setArg(0, genBuffer(clContext, std::vector<cl_float>(100));

//This is how it is done correctly
cl::Buffer buffer = genBuffer(clContext, std::vector<cl_float>(100));
kernel.setArg(0, buffer);

clQueue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(100), cl::NullRange);
}

关于c++ - clEnqueueNDRangeKernel 触发 CL_INVALID_MEM_OBJECT (-38),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18902575/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com