1

デバイス側で同時に 3 つのキューを待機できる特別な「イベント待機」機能があるので、ホスト側からすべてのキューを順番に待機しませんか?

コマンド キューに送信するチェックポイント コマンドはありますか? 他のコマンド キューが同じ (垂直方向に) バリア/チェックポイントに到達するのを待機して、デバイス側から待機して続行する必要があるため、ホスト側のラウンドトリップは必要ありませんか?

今のところ、2 つの異なるバージョンを試しました。

clWaitForEvents(3, evt_);

int evtStatus0 = 0;
clGetEventInfo(evt_[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
    sizeof(cl_int), &evtStatus0, NULL);

while (evtStatus0 > 0)
{

    clGetEventInfo(evt_[0], CL_EVENT_COMMAND_EXECUTION_STATUS,
        sizeof(cl_int), &evtStatus0, NULL);
    Sleep(0);
}

int evtStatus1 = 0;
clGetEventInfo(evt_[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
    sizeof(cl_int), &evtStatus1, NULL);

while (evtStatus1 > 0)
{

    clGetEventInfo(evt_[1], CL_EVENT_COMMAND_EXECUTION_STATUS,
        sizeof(cl_int), &evtStatus1, NULL);
    Sleep(0);
}


int evtStatus2 = 0;
clGetEventInfo(evt_[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
    sizeof(cl_int), &evtStatus2, NULL);

while (evtStatus2 > 0)
{

    clGetEventInfo(evt_[2], CL_EVENT_COMMAND_EXECUTION_STATUS,
        sizeof(cl_int), &evtStatus2, NULL);

    Sleep(0);
}

2つ目は少し速く(他の人から見ました)、両方とも3回のフラッシュコマンドの後に実行されます。

CodeXL プロファイラーの結果を見ると、最初の 1 つは終了ポイント間でより長く待機し、一部の操作は重複していないように見えます。2 つ目は、3 つの終了ポイントがすべて 3 ミリ秒以内であることを示しているため、より高速で、より長い部分がオーバーラップしています (読み取り + 書き込み + 同時計算)。

ホスト側から 1 つの待機コマンドだけでこれを実現する方法がある場合は、その「フラッシュ」バージョンも必要ですが、見つかりませんでした。

各パイプラインステップ間にフラッシュを追加する代わりに、下の図を達成する方法はありますか?

queue1 write checkpoint write    checkpoint write
queue2  -               compute  checkpoint compute checkpoint compute
queue3  -                        checkpoint read    checkpoint read     

すべてのチェックポイントは垂直方向に同期する必要があり、これらすべてのアクションは信号が与えられるまで開始してはなりません。そのような:

queue1.ndwrite(...);
queue1.ndcheckpoint(...);
queue1.ndwrite(...);
queue1.ndcheckpoint(...);
queue1.ndwrite(...);
queue2.ndrangekernel(...);
queue2.ndcheckpoint(...);
queue2.ndrangekernel(...);
queue2.ndcheckpoint(...);
queue2.ndrangekernel(...);
queue3.ndread(...);
queue3.ndcheckpoint(...);
queue3.ndread(...);
queue3.ndcheckpoint(...);
queue3.ndread(...);

queue1.flush() 
queue2.flush()
queue3.flush()

queue1.finish()
queue2.finish()
queue3.finish()

チェックポイントはすべてデバイス側で処理され、ホスト側から必要な終了コマンドは 3 つだけです (さらに良いことに、すべてのキューに対して 1 つの終了だけですか?)

「clWaitForEvents(3, evt_);」で 3 つのキューを 3 つのイベントにバインドする方法 今のところは:

hCommandQueue->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[0]);
hCommandQueue2->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[1]);
hCommandQueue3->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[2]);

この「エンキューバリア」が他のキューと通信できる場合、どうすればそれを達成できますか? すべてのキューが終了するまでホスト側のイベントを有効にしておく必要がありますか?それとも後で削除したり再利用したりできますか? ドキュメントから、最初のバリアのイベントを 2 番目のキューに入れることができ、2 番目のバリア イベントを最初のイベントと一緒に 3 番目のキューに入れることができるように見えるので、おそらく次のようになります。

hCommandQueue->commandQueue.enqueueBarrierWithWaitList(NULL, &evt[0]);
hCommandQueue2->commandQueue.enqueueBarrierWithWaitList(evt_0, &evt[1]);
hCommandQueue3->commandQueue.enqueueBarrierWithWaitList(evt_0_and_1, &evt[2]);

in the end wait for only evt[2] maybe or using only 1 same event for all:

hCommandQueue->commandQueue.enqueueBarrierWithWaitList(sameEvt, &evt[0]);
hCommandQueue2->commandQueue.enqueueBarrierWithWaitList(sameEvt, &evt[1]);
hCommandQueue3->commandQueue.enqueueBarrierWithWaitList(sameEvt, &evt[2]);

where to get sameEvt object?

誰かがこれを試しましたか?すべてのキューをバリアで開始して、ホスト側から何らかのイベントを発生させるまで開始しないようにするか、または「エンキュー」の遅延実行が「フラッシュ/終了するまで開始しない」と信頼できる %100 になるようにする必要がありますか? ホストからデバイスにイベントを発生させるにはどうすればよいですか (sameEvt には「発生」機能がありません。clCreateUserEvent ですか?)

3 つのキューはすべてインオーダー タイプであり、同じコンテキストにあります。アウトオブオーダー タイプは、すべてのグラフィックス カードでサポートされているわけではありません。C++ バインディングが使用されています。

また、enqueueWaitList(これは非推奨ですか?) と clEnqueueMarker がありますが、それらの使用方法がわかりません。ドキュメントには、Khronos の Web サイトに例がありません。

4

2 に答える 2