次の図に、1 つの順不同コマンド キューの例を示します。スケジューラは、キューからのコマンドをどの順序でも実行できます。必要に応じて、ユーザーがイベントの依存性と同期を手動で定義する必要があります。
図 1. 1 つの順不同コマンド キュー
次は、concurrent_kernel_execution_c 例の host.cpp からのコードで、1 つの順不同コマンド キューを設定し、必要に応じてコマンドをエンキューしています。
OCL_CHECK(
err,
cl::CommandQueue ooo_queue(context,
device,
CL_QUEUE_PROFILING_ENABLE |
CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
&err));
...
printf("[OOO Queue]: Enqueueing scale kernel\n");
OCL_CHECK(
err,
err = ooo_queue.enqueueTask(
kernel_mscale,nullptr, &ooo_events[0]));
set_callback(ooo_events[0], "scale");
...
// This is an out of order queue, events can be executed in any order. Since
// this call depends on the results of the previous call we must pass the
// event object from the previous call to this kernel's event wait list.
printf("[OOO Queue]: Enqueueing addition kernel (Depends on scale)\n");
kernel_wait_events.resize(0);
kernel_wait_events.push_back(ooo_events[0]);
OCL_CHECK(err,
err = ooo_queue.enqueueTask(
kernel_madd,
&kernel_wait_events, // Event from previous call
&ooo_events[1]));
set_callback(ooo_events[1], "addition");
// This call does not depend on previous calls so we are passing nullptr
// into the event wait list. The runtime should schedule this kernel in
// parallel to the previous calls.
printf("[OOO Queue]: Enqueueing matrix multiplication kernel\n");
OCL_CHECK(err,
err = ooo_queue.enqueueTask(
kernel_mmult,
nullptr,
&ooo_events[2]));
set_callback(ooo_events[2], "matrix multiplication");
[Application Timeline] ビューには、複数の順番キュー手法と単一の順不同キュー手法の両方を使用して、計算ユニット mmult_1
が計算ユニット mscale_1
および madd_1
と並列で実行されているとことが示されます。
図 2. mult_1 が mscale_1 と madd_1 と並列実行されていることを示す [Application Timeline] ビュー