enqueueNDRange 上的 InvalidKernelArgs 而类似的调用工作正常
InvalidKernelArgs on enqueueNDRange while a similar call works fine
我正在使用 JavaCL 处理图像。
我不断得到
com.nativelibs4java.opencl.CLException$InvalidKernelArgs: InvalidKernelArgs
在调用 enqueueNDRange 时调用此(部分)函数:
FloatBuffer outBuffer = ByteBuffer.allocateDirect(4*XYZ.length).order(context.getByteOrder()).asFloatBuffer();
CLFloatBuffer cl_outBuffer = context.createFloatBuffer(CLMem.Usage.Output, outBuffer, false);
CLFloatBuffer cl_inBuffer = context.createFloatBuffer(CLMem.Usage.Input,XYZ.length);
FloatBuffer inBuffer = cl_inBuffer.map(queue, CLMem.MapFlags.Write).put(XYZ);
inBuffer.rewind();
event = cl_inBuffer.unmap(queue, inBuffer);
XYZ2RGBKernel.setArgs(cl_inBuffer, XYZ.length/4,cl_outBuffer);
event = XYZ2RGBKernel.enqueueNDRange(queue, new int[]{XYZ.length/4}, event);
event = cl_outBuffer.read(queue, outBuffer, true, event);
XYZ 是一个像素数组,每个像素有 4 个浮点数(编码类似于 RGBARGBARGBA....)
相关的内核头文件是:
__kernel void XYZ2RGB( __constant float3* inputXYZ,
int numberOfPixels,
__global float* output
)
我不知道为什么它在调用 enqueueNDRange 后不起作用:
CLFloatBuffer cl_Rbuffer = context.createFloatBuffer(CLMem.Usage.Input, R.length);
FloatBuffer R_buffer = cl_Rbuffer.map(queue, CLMem.MapFlags.Write).put(R);
R_buffer.rewind();
event = cl_Rbuffer.unmap(queue, R_buffer);
CLFloatBuffer cl_Gbuffer = context.createFloatBuffer(CLMem.Usage.Input, G.length);
FloatBuffer G_buffer = cl_Gbuffer.map(queue, CLMem.MapFlags.Write, event).put(G);
G_buffer.rewind();
event = cl_Gbuffer.unmap(queue, G_buffer);
CLFloatBuffer cl_Bbuffer = context.createFloatBuffer(CLMem.Usage.Input, B.length);
FloatBuffer B_buffer = cl_Bbuffer.map(queue, CLMem.MapFlags.Write, event).put(B);
B_buffer.rewind();
event = cl_Bbuffer.unmap(queue, B_buffer);
FloatBuffer outBuffer = ByteBuffer.allocateDirect(4*4*R.length).order(context.getByteOrder()).asFloatBuffer();
CLFloatBuffer cl_outBuffer = context.createFloatBuffer(CLMem.Usage.Output, outBuffer, false);
RGB2XYZKernel.setArgs(cl_Rbuffer, cl_Gbuffer, cl_Bbuffer, cl_outBuffer);
event = RGB2XYZKernel.enqueueNDRange(queue, new int[]{R.length}, event);
event = cl_outBuffer.read(queue, outBuffer, true, event);
与关联的内核头文件:
__kernel void RGB2XYZ( __constant float* inputR,
__constant float* inputG,
__constant float* inputB,
__global float3* output)
工作没有任何问题。
在任何人问之前,float3 或 float4 的工作方式相同,因为 OpenCL 规范对两者都使用 4*sizeof(float) 对齐。我试过在两者之间切换。
我也尝试将输入作为 float* 传递,但它也不起作用。
两个电话一个接一个地发生。
更新
我在几个小时后修复了它:
- __constant 似乎有大小限制(虽然在规格中找不到)。 XYZ 的大小是 R、G 或 B 的 4 倍,它在运行时崩溃了。
- 之后我在使用 float3 时遇到了问题。看来我被迫使用的库不是最新的,所以它的支持不够好,所以我切换到 float4
但是,如果你们中的任何人对 __constant 大小限制和其他内容有更多见解,请告诉我,我相信这对遇到此主题的人来说会很方便。
__constant seems to have a size limit (couldn't find that in the specs though).
限制取决于设备。常量缓冲区有每个缓冲区的大小限制(CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,最小 64KB),并且对可以传递给内核的常量参数的数量也有限制(CL_DEVICE_MAX_CONSTANT_ARGS,最小 8)。 AMD 和 Nvidia GPU 通常都接近最小值,因此可以传递的数据总量 __constant 可能非常小。
“恒定”内存的要点不是将只读输入用户数据传递给内核(正如您似乎正在使用它);重点是存储特定于算法的常量(查找表、matrix/polynomial/filter 系数等)。如果要传递只读输入数据,通常的做法是将内核参数声明为__global const <type>*
,并用CL_MEM_READ_ONLY
.
创建相应的缓冲区
Here 更深入一些。
我正在使用 JavaCL 处理图像。 我不断得到
com.nativelibs4java.opencl.CLException$InvalidKernelArgs: InvalidKernelArgs
在调用 enqueueNDRange 时调用此(部分)函数:
FloatBuffer outBuffer = ByteBuffer.allocateDirect(4*XYZ.length).order(context.getByteOrder()).asFloatBuffer();
CLFloatBuffer cl_outBuffer = context.createFloatBuffer(CLMem.Usage.Output, outBuffer, false);
CLFloatBuffer cl_inBuffer = context.createFloatBuffer(CLMem.Usage.Input,XYZ.length);
FloatBuffer inBuffer = cl_inBuffer.map(queue, CLMem.MapFlags.Write).put(XYZ);
inBuffer.rewind();
event = cl_inBuffer.unmap(queue, inBuffer);
XYZ2RGBKernel.setArgs(cl_inBuffer, XYZ.length/4,cl_outBuffer);
event = XYZ2RGBKernel.enqueueNDRange(queue, new int[]{XYZ.length/4}, event);
event = cl_outBuffer.read(queue, outBuffer, true, event);
XYZ 是一个像素数组,每个像素有 4 个浮点数(编码类似于 RGBARGBARGBA....)
相关的内核头文件是:
__kernel void XYZ2RGB( __constant float3* inputXYZ,
int numberOfPixels,
__global float* output
)
我不知道为什么它在调用 enqueueNDRange 后不起作用:
CLFloatBuffer cl_Rbuffer = context.createFloatBuffer(CLMem.Usage.Input, R.length);
FloatBuffer R_buffer = cl_Rbuffer.map(queue, CLMem.MapFlags.Write).put(R);
R_buffer.rewind();
event = cl_Rbuffer.unmap(queue, R_buffer);
CLFloatBuffer cl_Gbuffer = context.createFloatBuffer(CLMem.Usage.Input, G.length);
FloatBuffer G_buffer = cl_Gbuffer.map(queue, CLMem.MapFlags.Write, event).put(G);
G_buffer.rewind();
event = cl_Gbuffer.unmap(queue, G_buffer);
CLFloatBuffer cl_Bbuffer = context.createFloatBuffer(CLMem.Usage.Input, B.length);
FloatBuffer B_buffer = cl_Bbuffer.map(queue, CLMem.MapFlags.Write, event).put(B);
B_buffer.rewind();
event = cl_Bbuffer.unmap(queue, B_buffer);
FloatBuffer outBuffer = ByteBuffer.allocateDirect(4*4*R.length).order(context.getByteOrder()).asFloatBuffer();
CLFloatBuffer cl_outBuffer = context.createFloatBuffer(CLMem.Usage.Output, outBuffer, false);
RGB2XYZKernel.setArgs(cl_Rbuffer, cl_Gbuffer, cl_Bbuffer, cl_outBuffer);
event = RGB2XYZKernel.enqueueNDRange(queue, new int[]{R.length}, event);
event = cl_outBuffer.read(queue, outBuffer, true, event);
与关联的内核头文件:
__kernel void RGB2XYZ( __constant float* inputR,
__constant float* inputG,
__constant float* inputB,
__global float3* output)
工作没有任何问题。
在任何人问之前,float3 或 float4 的工作方式相同,因为 OpenCL 规范对两者都使用 4*sizeof(float) 对齐。我试过在两者之间切换。 我也尝试将输入作为 float* 传递,但它也不起作用。 两个电话一个接一个地发生。
更新
我在几个小时后修复了它:
- __constant 似乎有大小限制(虽然在规格中找不到)。 XYZ 的大小是 R、G 或 B 的 4 倍,它在运行时崩溃了。
- 之后我在使用 float3 时遇到了问题。看来我被迫使用的库不是最新的,所以它的支持不够好,所以我切换到 float4
但是,如果你们中的任何人对 __constant 大小限制和其他内容有更多见解,请告诉我,我相信这对遇到此主题的人来说会很方便。
__constant seems to have a size limit (couldn't find that in the specs though).
限制取决于设备。常量缓冲区有每个缓冲区的大小限制(CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,最小 64KB),并且对可以传递给内核的常量参数的数量也有限制(CL_DEVICE_MAX_CONSTANT_ARGS,最小 8)。 AMD 和 Nvidia GPU 通常都接近最小值,因此可以传递的数据总量 __constant 可能非常小。
“恒定”内存的要点不是将只读输入用户数据传递给内核(正如您似乎正在使用它);重点是存储特定于算法的常量(查找表、matrix/polynomial/filter 系数等)。如果要传递只读输入数据,通常的做法是将内核参数声明为__global const <type>*
,并用CL_MEM_READ_ONLY
.
Here 更深入一些。