カーネルの実行が重複しているかどうかを判断するには、それらをプロファイリングする必要があります。これにはいくつかの手順が必要です。
1. コマンドキューの作成
プロファイリング データは、 command-queue が次のプロパティで作成された場合にのみ収集されますCL_QUEUE_PROFILING_ENABLE
。
cl_command_queue queues[10];
for (int i = 0; i < 10; ++i) {
queues[i] = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE,
&errcode);
}
2. すべてのカーネルが同時に起動するようにする
CPUがカーネルを順番にキューに入れるというあなたの仮定は正しいです。ただし、1 つのユーザー イベントを作成して、すべてのカーネルの待機リストに追加することはできます。これにより、ユーザー イベントが完了する前にカーネルが実行を開始しません。
// Create the user event
cl_event user_event = clCreateUserEvent(context, &errcode);
// Reserve space for kernel events
cl_event kernel_events[10];
// Enqueue kernels
for (int i = 0; i < 10; ++i) {
clEnqueueNDRangeKernel(queues[i], kernel, work_dim, global_work_offset,
global_work_size, 1, &user_event, &kernel_events[i]);
}
// Start all kernels by completing the user event
clSetUserEventStatus(user_event, CL_COMPLETE);
3. プロファイリング時間を取得する
最後に、カーネル イベントのタイミング情報を収集できます。
// Block until all kernels have run to completion
clWaitForEvents(10, kernel_events);
for (int i = 0; i < 10; ++i) {
cl_ulong start;
clGetEventProfilingInfo(kernel_event[i], CL_PROFILING_COMMAND_START,
sizeof(start), &start, NULL);
cl_ulong end;
clGetEventProfilingInfo(kernel_event[i], CL_PROFILING_COMMAND_END,
sizeof(end), &end, NULL);
printf("Event %d: start=%llu, end=%llu", i, start, end);
}
4. アウトプットの分析
すべてのカーネル実行の開始時刻と終了時刻がわかったので、(手動またはプログラムで) オーバーラップをチェックできます。出力単位はナノ秒です。ただし、デバイス タイマーは特定の解像度に対してのみ正確であることに注意してください。次を使用して解像度を照会できます。
size_t resolution;
clGetDeviceInfo(device, CL_DEVICE_PROFILING_TIMER_RESOLUTION,
sizeof(resolution), &resolution, NULL);
FWIW、CC 2.0(同時カーネルをサポートする必要がある)を搭載したNVIDIAデバイスでこれを試したところ、カーネルが順番に実行されることがわかりました。