0

GPUシミュレーターでタスクの並列処理を試みています。EnQueueNDRangeKernelの代わりに、Out-of-order-execution-mode-enableでEnQueueTask(4つのdiffカーネルを使用)を使用しています。これら2つをグローバルメモリに書き込もうとすると、非同期モードのために間違った動作をします。私は次のような1つのユーザーイベントを作成しました。

clSetUserEventStatus(user_event, CL_COMPLETE);
ret = clEnqueueWriteBuffer(command_queue, Amobj, CL_TRUE, 0, 16*16*sizeof(float), A, 1, &user_event, NULL);
clSetUserEventStatus(user_event, CL_COMPLETE);
    ret = clEnqueueWriteBuffer(command_queue, Bmobj, CL_TRUE, 0, 16*16*sizeof(float), B, 1, &user_event, NULL);

しかし、それは正しい結果を与えていません、時々その失速です..

cl_event timing_event1, timing_event2, timing_event3, timing_event4;
cl_ulong starttime1=0,starttime2=0,starttime3=0,starttime4=0,
         endtime1=0,endtime2=0,endtime3=0,endtime4=0,
         time_spent1,time_spent2=0,time_spent3=0,time_spent4=0, time_spent_all_0=0, time_spent_all_1=0;
ret = clEnqueueTask(command_queue, kernel[0], 0, NULL, &timing_event1);
ret = clEnqueueTask(command_queue, kernel[1], 0, NULL, &timing_event2);
ret = clEnqueueTask(command_queue, kernel[2], 0, NULL, &timing_event3);
ret = clEnqueueTask(command_queue, kernel[3], 0, NULL, &timing_event4);

  clGetEventProfilingInfo(timing_event1,CL_PROFILING_COMMAND_START,sizeof(cl_ulong),&starttime1,NULL);
clGetEventProfilingInfo(timing_event1,CL_PROFILING_COMMAND_END,sizeof(cl_ulong),&endtime1,NULL);
time_spent1 = endtime1 - starttime1;
  clGetEventProfilingInfo(timing_event2,CL_PROFILING_COMMAND_START,sizeof(cl_ulong),&starttime2,NULL);
clGetEventProfilingInfo(timing_event2,CL_PROFILING_COMMAND_END,sizeof(cl_ulong),&endtime2,NULL);
time_spent2 = endtime2 - starttime2;
    clGetEventProfilingInfo(timing_event3,CL_PROFILING_COMMAND_START,sizeof(cl_ulong),&starttime3,NULL);
clGetEventProfilingInfo(timing_event3,CL_PROFILING_COMMAND_END,sizeof(cl_ulong),&endtime3,NULL);
time_spent3 = endtime3 - starttime3;
    clGetEventProfilingInfo(timing_event4,CL_PROFILING_COMMAND_START,sizeof(cl_ulong),&starttime4,NULL);
clGetEventProfilingInfo(timing_event4,CL_PROFILING_COMMAND_END,sizeof(cl_ulong),&endtime4,NULL);
time_spent4 = endtime4 - starttime4;

time_spent_all_0 = time_spent1 + time_spent2 + time_spent3 + time_spent4;
time_spent_all_1 = endtime4 - starttime1;

printf("\n time_spent1 = %llu", time_spent1);
printf("\n time_spent2 = %llu", time_spent2);
printf("\n time_spent3 = %llu", time_spent3);
printf("\n time_spent4 = %llu", time_spent4);
printf("\n time_spent_all_0 = %llu", time_spent_all_0);
printf("\n time_spent_all_1 = %llu\n", time_spent_all_1);

これを行った後、私はすべてゼロを取得しています。

 size_t resolution;
  clGetDeviceInfo(device, CL_DEVICE_PROFILING_TIMER_RESOLUTION, sizeof(resolution), &resolution, NULL);
  printf("resolution size : %d", resolution);  

これを行った後、私は17145896522のような多数を取得しています..これはどういう意味ですか?

今、私の疑問は、コードclFlushをどこに置く必要があるのか​​ということです。clFinish個々のカーネルのタイミングと、すべてのカーネルのタイミングの合計が必要です。これが価値がない場合は、ミリ秒、マイクロ秒、またはナノ秒で正確なタイミング情報を取得する他の方法を提案してください。

前もって感謝します..


コードを修正した後、結果を追加しました。

gettimeofday( &t1, NULL );
ret = clEnqueueTask(command_queue, kernel[0], 0, NULL, &kernel_event1);
printf("Enqueue Task 0 successful: %d\n",ret);
gettimeofday( &t2, NULL );
ret = clEnqueueTask(command_queue, kernel[1], 0, NULL, &kernel_event2);
printf("Enqueue Task 1 successful: %d\n",ret);
gettimeofday( &t3, NULL );
ret = clEnqueueTask(command_queue, kernel[2], 0, NULL, &kernel_event3);
printf("Enqueue Task 2 successful: %d\n",ret);
gettimeofday( &t4, NULL );
ret = clEnqueueTask(command_queue, kernel[3], 0, NULL, &kernel_event4);
printf("Enqueue Task 3 successful: %d\n",ret);
gettimeofday( &t5, NULL );
clFinish(command_queue);

ret = clGetEventProfilingInfo(kernel_event1, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &starttime1, NULL);
printf("profiling starttime 1 : %d\n",ret);
ret = clGetEventProfilingInfo(kernel_event1, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &endtime1,NULL);
time_spent1 = endtime1 - starttime1;
printf("time_spent 1 = %llu\t profiling endtime 1 = %d\n", time_spent1, ret);

profiling starttime 1 : 0
time_spent 1 = 0
profiling endtime 1 = 0

これらは私が得ている結果です。それで、私は今何ができるでしょうか?

4

1 に答える 1

2

コマンドキューを作成するときに、 CL_QUEUE_PROFILING_ENABLEを追加することを忘れないでください。

デバイスでプロファイリングを使用できない場合があるため、各OpenCL呼び出し、特にclCreateCommandQueue呼び出しのリターンコードを確認してください。

プロファイリング情報を取得する前に、エンキューされたコマンドが終了するのを待つ必要があります。たとえば、4つのエンキューの後にclFinishを挿入します。

于 2013-02-22T16:57:52.530 に答える