在另一个内核启动之前不调用 JOCL eventCallback
JOCL eventCallback not called until another kernel starts
我正在尝试 运行 一个执行 OpenCL 内核的多线程 Java 应用程序。我想在内核完成时通知其中一个线程,所以我尝试使用 clSetEventCallback 方法。
为此我准备了一个方法
void runKernel(
cl_program program,
String functionName,
Object... params,
long[] globalWorkSize,
long[] localWorkSize
){
System.out.println(System.currentTimeMillis() +": Preparing Kernel "+kernel+);
int[] errCode = new int[1];
int errno;
cl_kernel kernel = CL.clCreateKernel(program, functionName, errCode);
/******INSERT ALL THE PARAMS******/
System.out.println(System.currentTimeMillis() +": Enqueueing Kernel "+kernel+);
cl_event event = new cl_event();
CL.clEnqueueNDRangeKernel(this.queue, kernel, 1, null, globalWorkSize, localWorkSize, 0, null, event);
CL.clSetEventCallback(event, CL_COMPLETE, new EventCallbackFunction() {
@Override
public void function(cl_event event, int command_exec_callback_type, Object user_data) {
System.out.println(System.currentTimeMillis() +": Finished kernel " + user_data);
}
}, kernel);
}
我调用这个函数来执行三个不同的内核,中间有 5 秒的间隔。代码 运行 很好,我得到了预期的结果。但是,当我查看应用程序输出时,回调方法不会在实际内核完成时执行,而是在程序再次调用 运行 方法后执行。 last executed kernel的回调从不执行(内核执行是因为得到的结果是正确的)。
1475085785924: Prepared Kernel cl_kernel[0x7f8b28098c90]
1475085785924: Enqueueing Kernel cl_kernel[0x7f8b28098c90]
1475085790925: Prepared Kernel cl_kernel[0x7f8b284fbd50]
1475085790925: Enqueueing Kernel cl_kernel[0x7f8b284fbd50]
1475085790925: Finished kernel cl_kernel[0x7f8b28098c90]
1475085795926: Prepared Kernel cl_kernel[0x7f8b2851abd0]
1475085795926: Enqueueing Kernel cl_kernel[0x7f8b2851abd0]
1475085795926: Finished kernel cl_kernel[0x7f8b284fbd50]
我的代码是否有任何问题,所以在下一个内核入队之前不会执行回调?我错过了什么?或者 JOCL/OpenCL 库没有正确通知内核结束?
显然,我使用的 OpenCL 实现存在错误。
作为一种变通方法,我将一个内核加入队列,该内核在将实际内核加入队列后什么也不做。
我有一个带有空程序的 cl_program 属性。
private cl_program doNothing;
int[] errCode = new int[1];
String blankCode = "__kernel void blank(){}";
doNothing = CL.clCreateProgramWithSource(context, 1, new String[]{blankCode}, new long[]{blankCode.length()}, errCode);
CL.clBuildProgram(doNothing, 1, new cl_device_id[]{deviceId}, null, null, errCode);
在将内核执行入队后,我调用了以下将空白内核入队的方法
private void addBlankKernel() {
int[] errCode = new int[1];
cl_kernel kernel = CL.clCreateKernel(this.doNothing, "blank", errCode);
CL.clEnqueueNDRangeKernel(this.queue, kernel, 1, null, new long[]{1}, new long[]{1}, 0, null, null);
}
我正在尝试 运行 一个执行 OpenCL 内核的多线程 Java 应用程序。我想在内核完成时通知其中一个线程,所以我尝试使用 clSetEventCallback 方法。
为此我准备了一个方法
void runKernel(
cl_program program,
String functionName,
Object... params,
long[] globalWorkSize,
long[] localWorkSize
){
System.out.println(System.currentTimeMillis() +": Preparing Kernel "+kernel+);
int[] errCode = new int[1];
int errno;
cl_kernel kernel = CL.clCreateKernel(program, functionName, errCode);
/******INSERT ALL THE PARAMS******/
System.out.println(System.currentTimeMillis() +": Enqueueing Kernel "+kernel+);
cl_event event = new cl_event();
CL.clEnqueueNDRangeKernel(this.queue, kernel, 1, null, globalWorkSize, localWorkSize, 0, null, event);
CL.clSetEventCallback(event, CL_COMPLETE, new EventCallbackFunction() {
@Override
public void function(cl_event event, int command_exec_callback_type, Object user_data) {
System.out.println(System.currentTimeMillis() +": Finished kernel " + user_data);
}
}, kernel);
}
我调用这个函数来执行三个不同的内核,中间有 5 秒的间隔。代码 运行 很好,我得到了预期的结果。但是,当我查看应用程序输出时,回调方法不会在实际内核完成时执行,而是在程序再次调用 运行 方法后执行。 last executed kernel的回调从不执行(内核执行是因为得到的结果是正确的)。
1475085785924: Prepared Kernel cl_kernel[0x7f8b28098c90]
1475085785924: Enqueueing Kernel cl_kernel[0x7f8b28098c90]
1475085790925: Prepared Kernel cl_kernel[0x7f8b284fbd50]
1475085790925: Enqueueing Kernel cl_kernel[0x7f8b284fbd50]
1475085790925: Finished kernel cl_kernel[0x7f8b28098c90]
1475085795926: Prepared Kernel cl_kernel[0x7f8b2851abd0]
1475085795926: Enqueueing Kernel cl_kernel[0x7f8b2851abd0]
1475085795926: Finished kernel cl_kernel[0x7f8b284fbd50]
我的代码是否有任何问题,所以在下一个内核入队之前不会执行回调?我错过了什么?或者 JOCL/OpenCL 库没有正确通知内核结束?
显然,我使用的 OpenCL 实现存在错误。
作为一种变通方法,我将一个内核加入队列,该内核在将实际内核加入队列后什么也不做。
我有一个带有空程序的 cl_program 属性。
private cl_program doNothing;
int[] errCode = new int[1];
String blankCode = "__kernel void blank(){}";
doNothing = CL.clCreateProgramWithSource(context, 1, new String[]{blankCode}, new long[]{blankCode.length()}, errCode);
CL.clBuildProgram(doNothing, 1, new cl_device_id[]{deviceId}, null, null, errCode);
在将内核执行入队后,我调用了以下将空白内核入队的方法
private void addBlankKernel() {
int[] errCode = new int[1];
cl_kernel kernel = CL.clCreateKernel(this.doNothing, "blank", errCode);
CL.clEnqueueNDRangeKernel(this.queue, kernel, 1, null, new long[]{1}, new long[]{1}, 0, null, null);
}