2016-09-28 34 views
0

我试图运行一个执行OpenCL内核的多线程Java应用程序。我想在内核完成时通知其中一个线程,所以我尝试使用clSetEventCallback方法。直到另一个内核启动才调用JOCL eventCallback

对于我制备的方法

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个secongs间隙其间执行三个不同的内核。代码运行良好,我得到了预期的结果。但是,当我查看应用程序输出时,回调方法不会在实际的内核完成时执行,但一旦程序再次调用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库没有正确地通知内核结束?

+0

你确定它是由底层OpenCL实现后引起?无论如何,我会尽力重现这一点(我不能在接下来的几天内做到这一点,但尽量做到这一点)。不得不排队一个空内核看起来像一个可疑的解决方法... – Marco13

+0

这是opencl实现上的东西。我检查了它使用相同的JOCL版本运行相同的程序,它在我的手机上工作,所以...这是我的笔记本电脑的libOpenCL.so库。我使用的是intel i7和集成GPU的ubuntu 16.04。任何建议? –

+0

(我只是问,因为JOCL是我的图书馆之一,**如果**问题是由JOCL引起的,我会仔细看看这个)。所以GPU也来自英特尔(不是AMD或NVIDIA)?这个问题也可能与司机有关,所以这个信息可能是相关的。毫无疑问,在供应商的支持论坛上询问也是值得一试的(尽管他们可能期望用C语言编写一个[MCVE],以便他们可以轻松地再现问题) – Marco13

回答

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); 
} 
相关问题