在另一个内核启动之前,不会调用JOCL eventCallback

时间:2016-09-28 18:28:35

标签: java callback opencl jocl

我试图运行一个执行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秒。代码运行正常,我得到了预期的结果。但是,当我查看应用程序输出时,回调方法不会在实际内核完成时执行,而是在程序再次调用run方法时执行。永远不会执行最后执行的内核的回调(由于获得的结果是正确的,因此执行内核)。

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库没有正确地通知内核?

1 个答案:

答案 0 :(得分:0)

显然,我使用的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);
}
相关问题