2017-12-21 26 views
0

OpenCLプログラミングの新機能です。私のOpenCLアプリケーションでは、すべてのカーネルを起動した後にclWaitForEventsを使用します。clWaitForEventsを使用しない場合の影響

ケース1:撮影した

time_start(); 
cl_event event; 
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event); 
clWaitForEvents(1, &event); 
time_end(); 

時間:(clWaitForEvents付き)250ミリ秒

を私はclWaitForEventsを削除する場合は()、私のカーネルは同じ出力でより速く動作します。

ケース2:撮影した

time_start(); 
cl_event event; 
cl_int status = clEnqueueNDRangeKernel(queue, ..., &event); 
time_end(); 

時間:(clWaitForEventsなし)220ミリ

私が順次10の異なるカーネルを起動しました。すべてのカーネルは、前のカーネルの出力に依存しています。すべてのカーネルの後にclWaitForEventを使用すると、実行時間が数100ミリ秒増加します。私はclWaitForEventsを使用していない場合は

は、出力が間違って行くことはできますか? clWaitForEventsまたはclFinishを使用しないと、おそらく何がうまくいかないかも理解したいと思います。

どのポインタも高く評価されています。

In-order-queue
+2

単一の順番待ち行列は待ちイベントを必要としません。 –

+1

clEnqueueReadBuffer(.. false ..)のような非同期コマンドがない限り、 "ブロッキング"は有効ではありません。 –

+0

@huseyintugrulbuyukisik AFAIK実際に非ブロッキングclEnqueueReadBuffer()は "非同期"コマンドではありません。ブロッキングパラメータは便宜上のものです。キューが順序どおりであれば、順番に実行されます。これはclEnqueueReadBuffer()を呼び出すのと同じです。 clFinish(); – mogu

答えて

2

うまくいけば、わずかに少ない複雑な答え:

私は順次10の異なるカーネルを起動しました。すべてのカーネルは、前のカーネルの出力に依存しています。

明示的clCreateCommandQueueに()の呼び出し(=通常の場合)をCL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLEプロパティを設定しない場合は、インオーダーキューになります。その中でコマンドを同期させる必要はありません(実際には実行を遅くする可能性があります)。 docsを参照してください:

If the CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE property of a command-queue is not set, the commands enqueued to a command-queue execute in order. For example, if an application calls clEnqueueNDRangeKernel to execute kernel A followed by a clEnqueueNDRangeKernel to execute kernel B, the application can assume that kernel A finishes first and then kernel B is executed. If the memory objects output by kernel A are inputs to kernel B then kernel B will see the correct data in memory objects produced by execution of kernel A.

私はclWaitForEventsまたはclFinishを使用しない場合、私はおそらく間違って行く可能性があるかを理解したいと思います。

単一のインオーダーキューで簡単な処理を行っている場合、clWaitForEvents()はまったく必要ありません。これは、複数のキューから複数のイベントを待つか、アウトオブオーダーのキューを使用する場合や、20個のコマンドをエンキューしたいが、4番目のキューなどを待つ場合に便利です。

単一の順序待ち行列の場合、clFinish()の後にすべてのコマンドが完了し、&すべてのイベントのステータスは、完了または失敗に更新されます。したがって、最も単純なケースでは、イベントを処理する必要はありません。必要なものをすべてエンキューして(エラーのエンキューをチェックしてください)、clFinish()を呼び出します。

wait/flush(WaitForEvents/Finish/blockingコマンド)を使用しない場合、実際にコマンドをデバイスにプッシュするのに時間がかかることに注意してください。 IOW you でなければなりません.1)WaitForEventsまたはFinishを使用するか、または2)の最後のコマンドとしてブロッキングコマンド(読み取り/書き込み/マップ/ unmap)をエンキューします。

+0

WaitForEventsまたはFinishを使用すると実行時間が長くなります。使用可能な代替ダミーブロックコマンドがありますか?ダミーのブロッキング読み出しを追加することはできますか? – Avis

+1

@svg *カーネルが起動するたびに* finish */waitを使う必要はありませんが、最後に*を少なくとも1つ*使用する必要があります。そうしないと、いつ結果が得られるか分かりません。単一のイン・オーダー・コマンド・キューでのブロッキング読み取りは、待機/終了と同じです。したがって、それは役に立ちません。 – mogu

1

は、暗黙的に、彼らはだけ装置側にエンキューされた順に、各コマンドの完了を待ちます。これは、ホストが何が起こったのか分からないことを意味します。

Out-of-order-queueはどこかで任意のコマンドの順序を保証するものではないとの問題を持つことができます。

「待ちイベント」コマンドのイベントをホスト側で待機します。

「完了」は、すべてのコマンドが完了するまでホスト側で待機します。

'非ブロッキングバッファの読み取り/書き込み'はホスト側で待機しません。 「バッファの読み取り/書き込みをブロックする」

は、ホスト側で待機しますが、他のコマンドを待機しません。


推奨ソリューション:

  • インターコマンドシンク(次のコマンドの入力としてコマンドの出力を使用する)で順序キュー
    • または別のコマンドのイベントを渡す(IFアウト・オブ・オーダーキューそのAN)
  • インターキュー(またはアウトオブオーダーキュー)同期(バッファコピーとカーネルの実行を重複するため)別のコマンドに対するコマンド(複数可)から
    • パスイベント
  • デバイス - ホスト(RAMに最新のデータを取得するための(またはRAMからの最初のデータを取得する)またはホストの一時停止)同期
    • バッファ上のオプションを遮断すること
    • またはclFinish
    • を追加したり、コマンドは(ベンチマークのような理由のために)完了したときに
  • に通知することclWaitForEvent
  • を使用するコマンドを有効
    • 使用のイベントコールバック
    • または常にクエリーイベント状態(CPU/pci-e使用率が増加)

エンキュー1の非ブロッキングバッファ書き込み+ 1000×カーネル+ 1つのブロッキングバッファーが正常に初期データに千のカーネルのチェーンを実行し、ホスト側の最新の結果を得ることができ、インオーダー・キューで読みます。

関連する問題