2016-09-08 10 views
1

デバイス側で3つのキューを同時に待つことができる特別な「待機待ち」機能があります。ホスト側?3つのキュー+すべてのキューの終了またはデバイス側のチェックポイント

他のコマンドキューが同じ(垂直)バリア/チェックポイントをヒットして待機してデバイス側から続行するのを待たなければならないようにコマンドキューに送信するチェックポイントコマンドがあるので、ホスト側の往復は必要ありません?

は今のところ、私は2つの異なるバージョンを試みた:秒1は少し速くなる

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); 
} 

を(私は他の誰かからそれを見て)との両方が3つのフラッシュコマンドの後に実行されています。

CodeXLプロファイラの結果を見ると、最初は終了点の間隔が長くなり、一部の操作は重複していないように見えます。 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フィニッシュコマンドがホスト側から必要とされている

私は3から3キューをバインドする方法(すべてのキューのためのより良い、唯一の1つの仕上げ?)イベントは "clWaitForEvents(3、evt_);"今のところ:

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

この「エンキューバリア」が他のキューと話すことができれば、どうすれば実現できますか?すべてのキューが終了するか、キューを削除したり後で再利用できるようになるまで、ホスト側のイベントを有効に保つ必要がありますか?

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? 

誰もこれを試してみました:ドキュメントから、それはので、多分それは同様である第一1のイベントと一緒に三番目に置くことが可能な第2キュー2つ目の障壁イベントに置くことができる最初の障壁のイベントのように思えますか?ホスト側から何らかのイベントを発生させるか、または "enqueue"の実行が%100を信頼できる "私がフラッシュ/終了するまで開始しない"にするまで、バリアを持つすべてのキューを開始する必要がありますか?ホストからデバイスへイベントを発生させるには(sameEvtには "raise"機能はありませんが、clCreateUserEventですか?)

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

また、enqueueWaitList(これは廃止予定ですか?)とclEnqueueMarkerがありますが、それらを使用する方法はわかりませんし、KhronosのWebサイトには例がありません。

答えて

1

唯一の解決策を提供するために多すぎる質問をしたり多すぎる表現をしたので、私は一般的に最も適切な解決策を見つけ出すことができます。

キューが、同じコンテキスト(場合によっては同じコンテキスト内の異なるデバイス)にバインドされていて、イベントを通じてそれらを同期させることができる場合。私。 1つのキューに送信されたコマンドからイベントを取得し、このイベントを使用して別のキューに送信されたコマンドを同期させることができます。この例では

queue1.enqueue(comm1, /*dependency*/ NULL, /*result event*/ &e1); 
queue2.enqueue(comm2, /*dependency*/ &e1, /*result event*/ NULL); 

comm2comm1完了するのを待ちます。

最初にコマンドをエンキューする必要があるが、実行できないようにするには、ユーザイベント(clCreateUserEvent)を作成して手動で通知してください(clSetUserEventStatus)。インプリメンテーションでは、キューに登録するとすぐにコマンドを処理できます(ドライバはflushを待つ必要はありません)。

バリアは、キューに以前に送信されたすべてのコマンドを待機するため、目的のために過度のように見えます。実際にはclEnqueueMarkerを使用して、すべてのイベントを待機し、他のコマンドに使用するイベントを提供することができます。

私が知っている限り、もっと必要がなければいつでもイベントを保持することができます。実装は、内部目的のために必要な場合は、イベントの存続時間を延長する必要があります。

enqueueWaitListは分かりません。

オフトピック:計算間の依存関係が些細な場合は、TBB flow graphopencl_nodeと考えてください。 opencl_nodeは、同期化のためにイベントを使用し、可能であれば "ホストデバイス"の同期を回避します。ただし、同じデバイスに対して複数のキューを使用するのは難しいことがあります。

私の知る限り、インテルHDグラフィックス530は、アウト・オブ・オーダー・キュー(少なくともホスト側)をサポートしています。

+0

ありがとうございました。私は最初のエンキューとしてマーカーを使用し、その後flush + finishの1秒後にclsetusereventstatusで設定しました。すべてのキューを正確に1秒間開始しました。私はエンドポイントと同じイベントを待ちます(マーカーを使用してデバイス側のイベントを使用)。 –

1

あなたは、必要以上に難しくなっています。書き込みキューでイベントを起こします。これを計算キューの計算の条件として使用し、別のイベントを実行します。これを読み取りキューの読み取りの条件として使用します。他の同期を強制する理由はありません。注:仕様の解釈は、そのイベントを別のキューの条件として使用する前に、イベントを取得したキューでclFlushする必要があることです。

+0

あなたのやり方を試してみましょう。単純に3つのキューに1ウェイのイベントチェーンがあり、ドライバはそれらの位置が重複してしまい、結果的にすべての小さなカーネルができませんでした。 1キュー(順序付け)が127ミリ秒かかっていたのに対し、140ミリ秒かかりました。別のキューに同じイベントを追加すると(自分のキューには必要ありません)、双方向イベントは、read + write + computeのオーバーラップ実行を有効にして112ミリ秒になります。どちらかCodeXLのタイムライングラフが間違っていると私自身のC#のストップウォッチタイマーが間違っているか、ドライバができません。計算を開始する前に書き込みを完全に完了します。その後、計算が終了し、読み取りが開始されます。しかし、すべての場合において、イベントは1〜2ミリ秒の待ち時間を有する。 –

+0

R7-240は、計算が存在しないためハードウェア(ソフトウェアをエミュレートする)で3キューの同時実行ができない場合があります。たぶん唯一の計算+読み取りまたは計算+書き込み可能ですか? –

+0

あなたは正しいです、それをもっと難しくする必要はありませんでした。私はちょうど4つのキューを使用し、パイプラインを垂直でなく水平にし、イベントなしで、コマンド間に穴がないことを効率的にオーバーラップさせました。 –

関連する問題