2016-09-28 4 views
0

OpenCLカーネルを実行するマルチスレッドJavaアプリケーションを実行しようとしています。カーネルの終了時にスレッドの1つに通知したいので、clSetEventCallbackメソッドを使用しようとしました。そのためJOCL eventCallbackは別のカーネルが起動するまで呼び出されません

は、私は、この関数は5 secongsギャップ挟んで三つの異なるカーネルを実行するために呼び出すメソッド

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); 
} 

を調製しました。コードは正常に実行され、期待される結果が得られます。しかし、アプリケーションの出力を見ると、コールバックメソッドは実際のカーネル完了時には実行されませんが、プログラムが再度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ライブラリです。私は、ubuntu 16.04とintel i7と統合GPUを使用しています。どんな勧告? –

+0

(私はJOCLが私のライブラリの1つであるので尋ねました。**もし問題がJOCLに起因するならば、私はこれを詳しく見ています)。したがって、GPUはインテルのものです(AMDまたはNVIDIAではありません)?この問題はドライバーに関連している可能性があるため、この情報は関連性があります。疑わしいことに、ベンダーのサポートフォーラムで尋ねることも試してみる価値があるかもしれませんが(CVEで書かれた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); 
} 
関連する問題