OpenCL enqueue_kernel调用抛出-59错误异常问题咨询
OpenCL 2.0 内核调用enqueue_kernel触发CL_INVALID_OPERATION(-59)错误解决方案
问题复现环境与现象
测试内核代码
kernel void check_run() { unsigned global_id = get_global_id(0); queue_t q = get_default_queue(); ndrange_t ndrange = ndrange_1D(1, 1); printf("Running my kernel %u\n", global_id); enqueue_kernel(q, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, ^{ size_t id = get_global_id(0); printf("%zu\n", id); } ); }
注:原代码中printf行末尾缺失分号属于笔误,正常编译需补全
内核编译选项
-I "/home/development/cl" -g -cl-std=CL2.0 -cl-mad-enable
运行硬件为支持OpenCL 2.1的Intel(R) Gen9 HD Graphics NEO。
主机端启动代码
try { auto check_run = cl::KernelFunctor<>(cl::Kernel{program_, "check_run"}); check_run(cl::EnqueueArgs(queue, cl::NDRange(1))); } catch (const cl::Error& e) { std::cout << "We should not have thrown in the profiling test.\n\n" << "cl error: " << e.err() << " name: " << e.what(); }
报错信息
cl error: -59 | what: clEnqueueNDRangeKernel
公开文档标注-59(CL_INVALID_OPERATION)仅在D3D9互操作参数冲突时触发,与实际使用场景不符。隔离测试确认注释掉enqueue_kernel调用后程序可正常运行,且Khronos官方OpenCL 2.0规范中enqueue_kernel接口的合法返回码不包含-59。
触发原因
该错误属于Intel NEO驱动的私有实现逻辑触发,和规范中公开的D3D互操作场景无关,核心触发条件为:
- 主机端创建传入内核的命令队列时,未添加设备侧入队所需的属性标记,导致内核中
get_default_queue()获取到的队列不支持设备侧核函数入队操作,驱动直接在核函数启动阶段返回CL_INVALID_OPERATION。 - 部分旧版本Intel NEO驱动存在实现bug:当编译选项携带
-g调试信息标记时,会错误拦截设备侧入队操作,抛出相同错误。
修复步骤
- 修改主机端命令队列创建逻辑,显式添加设备侧队列支持属性,参考实现:
cl_queue_properties queue_props[] = { CL_QUEUE_PROPERTIES, CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, 0 }; cl::CommandQueue queue(context, device, queue_props);
可提前调用clGetDeviceInfo查询CL_DEVICE_MAX_ON_DEVICE_QUEUES参数,确认返回值大于0,验证设备侧入队特性可用,Gen9核显硬件本身支持该特性,正常情况返回值不会为0。
- 若修改队列属性后仍报错,先暂时移除编译选项中的
-g参数,同时升级Intel NEO驱动到2022年之后发布的稳定版本,旧版本带调试信息编译设备侧入队内核的bug已在后续驱动版本中修复。
内容的提问来源于stack exchange,提问作者Fantastic Mr Fox
相关产品推荐
相关产品推荐

