2012-06-16 6 views
5

私のOpenCLプログラムでは、各カーネルがアクセスできる必要がある60以上のグローバルメモリバッファで終わるつもりです。各カーネルにこれらのバッファのそれぞれの位置を知らせるための推奨される方法は何ですか?多くのメモリオブジェクトのOpenCLカーネルに通知する適切な方法はありますか?

バッファ自体はアプリケーションの存続期間中は安定しています。つまり、アプリケーションの開始時にバッファを割り当て、複数のカーネルを呼び出した後、アプリケーション終了時にバッファの割り当てを解除します。しかし、それらの内容はカーネルの読み書きによって変わることがあります。

CUDAでは、私がこれをやったのは、私のCUDAコードで60個以上のプログラムスコープのグローバル変数を作成することでした。私は、ホスト上で、私がこれらのグローバル変数に割り当てたデバイスバッファのアドレスを書きます。そして、カーネルはこれらのグローバル変数を使って、必要なバッファを見つけるだけです。

OpenCLでこれを行うにはどうすればよいでしょうか? CLのグローバル変数はCUDAとは少し違いますが、私のCUDAメソッドが機能するかどうかについての明確な答えを見つけることはできません。もしそうならば、バッファポインタをグローバル変数に移す方法。それがうまくいかない場合は、それ以外は何が最善の方法ですか?

答えて

1

60グローバル変数は大変です!小さなアルゴリズムを使用してアルゴリズムをリファクタリングする方法がないのは確かですか?各カーネルは最小限の作業単位でなければならず、巨大なものではないことを覚えておいてください!

ただし、1つの解決策があります。 60個の配列が既知のサイズであると仮定すると、それらをすべて1つの大きなバッファに格納してから、その大きな配列のさまざまな部分にアクセスするためにオフセットを使用できます。ここでは3つの配列を持つ非常に単純な例です:

A is 100 elements 
B is 200 elements 
C is 100 elements 

big_array = A[0:100] B[0:200] C[0:100] 
offsets = [0, 100, 300] 

次に、あなただけのカーネルにbig_arrayとオフセットを渡す必要があり、そしてあなたは、各配列にアクセスすることができます。たとえば:

A[50] = big_array[offsets[0] + 50] 
B[20] = big_array[offsets[1] + 20] 
C[0] = big_array[offsets[2] + 0] 

私はこれがあなたの特定のデバイス上でのキャッシングに影響を与えるだろうが、私の最初の推測があるかどうかはわかりません「ではないだけでなく。」この種の配列アクセスは少し厄介です。私はそれが有効かどうかは分かりませんが、各オフセットを抽出して元のポインタのコピーに追加するコードで各カーネルを開始することができます。

ホスト側では、配列にアクセスしやすくするために、clCreateSubBuffer:http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clCreateSubBuffer.htmlを使用することができます。オフセット配列なしで特定の配列への参照を渡すこともできます。

私はこの解決策が60個のカーネル引数を渡すよりも良いとは思っていませんが、OpenCL実装のclSetKernelArgsによってはより高速かもしれません。引数リストの長さは確実に短くなります。

+0

60の議論は、私が参加している研究プロジェクトのための特別なコードシンセサイザによってこのコードが生成されているためです。残念ながら、私はその部分を制御することはできません。私は、あなたが概説したバッファ充填方法を使用して終了しました。うまくいけば、それは60の議論よりも良い方法です。ご協力いただきありがとうございます! – int3h

0

あなたは2つのことをする必要があります。そのカーネルの各利用のバッファが表示されているように

kernel void awesome_parallel_stuff(global float* buf1, ..., global float* buf60) 

:まず、各グローバルメモリバッファを使用する各カーネルは、このような何かを 1の引数を宣言する必要があります。そして、のホスト側では、パーティを開始するためにclEnqueueNDRangeKernelを呼び出す前に、各バッファを作成し、与えられたカーネル引数に特定のメモリバッファを接続するために、それぞれのバッファを作成してください。

カーネルがカーネルの実行ごとに同じバッファを使用し続ける場合は、カーネルの引数を1回だけ設定する必要があることに注意してください。ホスト側のパフォーマンスを引き出すことができるよくある間違いは、完全に不要な状況で繰り返しclSetKernelArgと呼ぶことです。

+0

カーネル関数ごとに60個の引数を持つことはできません。私は引数を残しておくことができますが、stilは、各スレッドが240バイトのメモリを使用してポインタを開始することを意味します。ポインタは変更されず、すべてのカーネルで同じです。さらに、引数を渡す際にパフォーマンス上のオーバーヘッドが発生する可能性があります。これらのカーネルは毎秒60回呼び出されます。 – int3h

関連する問題