EventCallback JOCL не вызывается, пока не запустится другое ядро

Я пытаюсь запустить многопоточное приложение Java, которое выполняет ядра OpenCL. Я хотел уведомить один из потоков о завершении работы ядра, поэтому попытался использовать метод 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 ответ

Решение

Видимо, есть ошибка в реализации 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);
}
Другие вопросы по тегам