2017-03-16 10 views
1

私は、より大きなアプリケーションのためのテストであるopenCL 1.2でアプリケーションを作成しています。このテストでは、カーネル実行ごとに4x4行列の各値に1を加算します。ダブルバッファリングが機能するようにすることです。私は実際に同じことをする2つのカーネルを作成しました。同じREAD_WRITEバッファを共有するので、最後のカーネルの実行は続行できますが、出力バッファが異なるために違います。出力バッファの1つちょうどこのように、他のデータを読みながら、カーネル:コードのOpenCL、1つのデバイスに2つのコマンドキューを使用したダブルバッファリング

Diagram

作品だと思うが関連しているか、次のようである、私は念のため、キュー、バッファ、およびイベントを含むが、問題となる可能性私はこれについてのすべてを変更してみました:

キュー

各カーネル

clSetKernelArg(kernel_1, 0, sizeof(cl_mem), &input_matA); 
    clSetKernelArg(kernel_1, 1, sizeof(cl_mem), &input_Parametros); 
    clSetKernelArg(kernel_1, 3, sizeof(cl_mem), &output_buffer); 

    clSetKernelArg(kernel_2, 0, sizeof(cl_mem), &input_matA); 
    clSetKernelArg(kernel_2, 1, sizeof(cl_mem), &input_Parametros); 
    clSetKernelArg(kernel_2, 3, sizeof(cl_mem), &output_buffer_2); 

イベント

cl_event event_1, event_2, event_3, event_4; 
0に設定
compute_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &err); 
data_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &err); 

バッファ

input_Parametros = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(double) * 5, Parametros, NULL); 
input_matA = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(double) * 4, matA_1, NULL); // The 4x4 matrix 
output_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY , sizeof(double) * 4 * iteraciones_por_kernel, NULL, NULL); 
output_buffer_2 = clCreateBuffer(context, CL_MEM_WRITE_ONLY , sizeof(double) * 4 * iteraciones_por_kernel, NULL, NULL); 

引数

カーネルと読むが、私はちょうどこれもすべてが完璧に罰金見せかけで動作するように取得することはできません

//////////////////////////////////////////////////////////////// 
    // START 
    //////////////////////////////////////////////////////////////// 

clEnqueueNDRangeKernel(compute_queue, kernel_1, 1, NULL, global, local, 0, 0, &event_1); 

clEnqueueNDRangeKernel(compute_queue, kernel_2, 1, NULL, global, local, 0, 0, &event_2); 

clEnqueueReadBuffer(data_queue, output_buffer, CL_FALSE, 0, sizeof(double)*4*iteraciones_por_kernel, datos_salida, 1 , &event_1, &event_3); 

    //////////////////////////////////////////////////////////////// 
    // ENQUEUE LOOP 
    //////////////////////////////////////////////////////////////// 

for (int i = 1; i <= (n_iteraciones_int - 2); i++){ 

     //////////////////////////////////////////////////////////////// 
     // LOOP PART 1 
     //////////////////////////////////////////////////////////////// 

     if (i % 2 != 0){ 
      clEnqueueNDRangeKernel(compute_queue, kernel_1, 1, NULL, global, local, 1, &event_3, &event_1); 

      clEnqueueReadBuffer(data_queue, output_buffer_2, CL_FALSE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[i*iteraciones_por_kernel_int*4], 1, &event_2, &event_4); 
     } 

     //////////////////////////////////////////////////////////////// 
     // LOOP PART 2 
     //////////////////////////////////////////////////////////////// 

     if (i % 2 == 0){ 

      clEnqueueNDRangeKernel(compute_queue, kernel_2, 1, NULL, global, local, 1, &event_4, &event_2); 

      clEnqueueReadBuffer(data_queue, output_buffer, CL_FALSE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[i*iteraciones_por_kernel_int * 4], 1, &event_1, &event_3); 
     } 

    } 

    //////////////////////////////////////////////////////////////// 
    // END 
    //////////////////////////////////////////////////////////////// 

clEnqueueReadBuffer(data_queue, output_buffer_2, CL_TRUE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[(n_iteraciones_int - 1) * 4], 1, &event_2, 0); 

をエンキュー。最初の読み込みでは期待値が得られますが、それ以降はカーネルがもう実行されないようです。なぜなら、output_buffer_2から0を取得し、最初の読み込み形式の最初のoutput_bufferと同じ値を取得するからです。

これは、同じカーネルと、最後に1回のデータ転送ですべてを行う1つのキューで完璧に機能しますが、その必要はありません。

私はすべてを改訂し、私ができると思ったすべてのバリエーションを試してみました。これは簡単で可能なはずだと思います...どこに問題がありますか?

私はAMD HD7970をデバイスとして使用しています。Windows 10とVisual Studio Community 2013は役に立ちましたか?フセインtugrulのbuyukisikヘルプに

+1

を読みますゼロ。 1つは1でなければなりません。 –

+1

最新のブロック読み取りでは、イベントが必要です。そのイベントを返すLast iterationで適切なステップがあることを確認してください。奇数番号の最後の反復は1と比較するのを忘れました –

+1

最後に、両方のキューをclflushする必要があります。ループの後に両方のキューを開始し、最後の読み取りで独自のキューiircのみを開始します。 –

答えて

1

おかげで、プログラムは以下のバリエーションで働い:

イベント

cl_event event[20]; //adjust this to your needs 

カーネルと両方モジュラスチェックが反対しているエンキュー

//////////////////////////////////////////////////////////////// 
// START 
//////////////////////////////////////////////////////////////// 

clEnqueueNDRangeKernel(compute_queue, kernel_1, 1, NULL, global, local, 0, 0, &event[0]); 


clEnqueueNDRangeKernel(compute_queue, kernel_2, 1, NULL, global, local, 0, 0, &event[1]); 


clEnqueueReadBuffer(data_queue, output_buffer, CL_FALSE, 0, sizeof(double)*4*iteraciones_por_kernel, datos_salida, 1 , &event[0], &event[2]); 

//////////////////////////////////////////////////////////////// 
// LOOP 
//////////////////////////////////////////////////////////////// 

for (int i = 1; i <= (n_iteraciones_int - 2); i++){ 

     //////////////////////////////////////////////////////////////// 
     // LOOP PART 1 
     //////////////////////////////////////////////////////////////// 

     if (i % 2 == 1){ 

      clEnqueueNDRangeKernel(compute_queue, kernel_1, 1, NULL, global, local, 1, &event[2+2*(i - 1)], &event[4 + 2 * (i - 1)]); 

      clEnqueueReadBuffer(data_queue, output_buffer_2, CL_FALSE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[i*(iteraciones_por_kernel_int) * 4], 1, &event[1+2*(i - 1)], &event[3 + 2 * (i - 1)]); 

     } 

     //////////////////////////////////////////////////////////////// 
     // LOOP PART 2 
     //////////////////////////////////////////////////////////////// 

     if (i % 2 == 0){ 

      clEnqueueNDRangeKernel(compute_queue, kernel_2, 1, NULL, global, local, 1, &event[3 + 2 * (i - 2)], &event[5 + 2 * (i - 2)]); 

      clEnqueueReadBuffer(data_queue, output_buffer, CL_FALSE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[i*(iteraciones_por_kernel_int) * 4], 1, &event[4 + 2 * (i - 2)], &event[6 + 2 * (i - 2)]); 
     } 

    } 

//////////////////////////////////////////////////////////////// 
// END 
//////////////////////////////////////////////////////////////// 

clFlush(compute_queue); 
clFlush(data_queue); 
clEnqueueReadBuffer(data_queue, output_buffer_2, CL_TRUE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[(n_iteraciones_int-1)*(iteraciones_por_kernel_int) * 4], 1, &event[5+2*(n_iteraciones_int-4)], 0); 
関連する問題