我正在尝试一个非常简单的OpenCL示例。我在下面开发了以下代码。它编译一个简单的内核,然后我创建一个简单的 float* 缓冲区并将其设置为 cl::Buffer。但是,当我尝试调用 kernel.setArg(( 函数时,它崩溃了,错误为 -38。此错误表明我的 cl::缓冲区无效。我不知道为什么会发生这种情况:
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include <CL/cl2.hpp>
#define MULTI_LINE_STRING(ARG) #ARG
namespace op
{
const char *resizeAndMergeKernel = MULTI_LINE_STRING(
__kernel void testKernel(__global float* image)
{
}
);
}
void testCL(){
cl::Device device;
cl::Context context;
cl::CommandQueue queue;
int deviceId = 0;
// Load Device
std::vector<cl::Platform> platforms;
std::vector<cl::Device> devices;
std::string deviceName;
cl_uint i, type;
cl::Platform::get(&platforms);
type = platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
if( type == CL_SUCCESS)
{
// Get only relavent device
cl::Context allContext(devices);
std::vector<cl::Device> gpuDevices;
gpuDevices = allContext.getInfo<CL_CONTEXT_DEVICES>();
bool deviceFound = false;
for(int i=0; i<gpuDevices.size(); i++){
if(i == deviceId){
device = gpuDevices[i];
context = cl::Context(device);
queue = cl::CommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE);
deviceFound = true;
cout << "Made new GPU Instance: " << deviceId << endl;
break;
}
}
if(!deviceFound)
{
throw std::runtime_error("Error: Invalid GPU ID");
}
}
// Create Kernel
cl::Program program = cl::Program(context, op::resizeAndMergeKernel, true);
cl::Kernel kernel = cl::Kernel(program, "testKernel");
// Simple Buffer
cl_int err;
float* test = new float[3*224*224];
cl::Buffer x = cl::Buffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(float) * 3 * 224 * 224, (void*)test, &err);
cout << err << endl;
kernel.setArg(0,x); // CRASHES WITH cl::Error -38
}
如您所见,最后一行 kernel.setArg(0,x( 崩溃并显示错误 -38。
这不是"崩溃",而是错误代码。OpenCL 错误 -38 CL_INVALID_MEM_OBJECT。这意味着cl_mem_obj无效。这是因为您要将 cl::Buffer 对象传递给 setArg,但您需要传递表示该缓冲区的cl_mem句柄。cl::Buffer operator(( 方法返回该值。所以使用kernel.setArg(0,x())
.请注意,()
是添加的部分(是的,它很微妙(。