2

ホストで複数の C++11 スレッド (GCC 4.7.1) を並列に実行する必要があります。それぞれが GPU などのデバイスを使用する必要があります。OpenCL 1.2 仕様 (p. 357) によると:

All OpenCL API calls are thread-safe75 except clSetKernelArg. 
clSetKernelArg is safe to call from any host thread, and is safe
to call re-entrantly so long as concurrent calls operate on different
cl_kernel objects. However, the behavior of the cl_kernel object is
undefined if clSetKernelArg is called from multiple host threads on
the same cl_kernel object at the same time.

洗練された方法は、thread_local cl_kernel オブジェクトを使用することであり、私が考えることができる他の方法は、i 番目のスレッドが i 番目のオブジェクトを使用するように、これらのオブジェクトの配列を使用することです。私は以前にこれらを実装していなかったので、2 つのうちのいずれかが優れているかどうか、または物事を成し遂げるためのより良い方法があるかどうか疑問に思っていました。

3 つ目の方法は、単一の cl_object にミューテックスを使用し、それをイベント ハンドラーに関連付けることです。その後、スレッドはイベントが終了するまで待機できます。マルチスレッドの状況でこれが機能するかどうかはわかりません...

4

1 に答える 1

3

主な問題は、これらすべてのスレッドが同じカーネルを使用する必要があるのか​​、それともそれぞれが独自の異なるカーネルを取得するのかということです。thread_local cl_kernelオブジェクトまたはn個のカーネルオブジェクトの配列のいずれかを使用するというアイデアは、どちらもn個のカーネルオブジェクトが作成される結果であり、OpenCLの観点からも同様に適切です。ただし、それらすべてに同じコードが含まれている場合は、不必要にスペースを浪費する/コンテキストスイッチを引き起こす/キャッシュを台無しにする/ ...そして、一定のバイナリコードセグメントを共有せずにアプリケーションバイナリをメモリに複数回ロードすることに匹敵します。

実際に複数のスレッド内から同じカーネルを使用したい場合は、単一のcl_kernelオブジェクトで手動同期を実行することをお勧めします。他のスレッドが作業を完了するまでスレッドの待機をブロックしたくない場合は、非同期コマンドキューイングとイベントを使用して、特定のスレッドの作業が完了したら通知を受け取ることができます(GPUよりも速く作業をキューに入れるスレッドを防ぐため)それを処理するか、もちろん結果を読み返します)。

スレッドが異なるカーネルプログラムを実行する場合は、実行を簡素化するために、スレッドごとに個別のコマンドキューを作成することをお勧めします。これらのオブジェクトハンドルをスレッドローカルストレージ、グローバル配列、またはその他の場所に格納することを選択した場合、それは完全にあなた次第です。

于 2012-10-08T00:15:49.410 に答える