6

1D配列に格納されている3Dデータがあります。私は次のように1Dインデックスを計算します:

index = i + j * WIDTH + k * WIDTH * HEIGHT

から元のi,j,kインデックスを取り戻す必要があるよりindex。これを行うための明白な方法は、次のようなものです。

k = index / (WIDTH * HEIGHT) 
j = (index % (WIDTH * HEIGHT)) / WIDTH
i = index - j * WIDTH - k * WIDTH * HEIGHT

しかし、これを行うためのより効率的な方法はありますか?少なくともモジュロなしで...

この質問のコンテキスト-CUDAにカーネルがあり、データにアクセスしてi, j, kインデックスを計算します(index一意のスレッドIDに対応します)。それで、これを行うためのCUDA固有の方法があるのでしょうか?これは非常に一般的な問題だと思いますが、これを行うためのより良い方法を見つけることができませんでした...

あなたのアイデアをありがとう!

4

3 に答える 3

6

寸法を2の次の累乗に切り上げてみてください。次に、乗算、除算、モジュロの代わりにビットシフトとマスクを使用できます。

index = i | (j | k << HEIGHT_BITS) << WIDTH_BITS;

k = index >> (WIDTH_BITS + HEIGHT_BITS);
j = (index >> WIDTH_BITS) & ((1 << HEIGHT_BITS) - 1);
i = index & ((1 << WIDTH_BITS) - 1);
于 2012-12-15T17:17:30.377 に答える
6

あなたが持っているものは大丈夫です。モジュロを避けたい場合(GPUでは非常に高価であるため)、jこれまでに行ったことをそのまま使用できiます。

j = (index - (k*WIDTH*HEIGHT))/WIDTH

ロジックをもう少し明確にしたい場合で、元のロジックは必要ありませんindex

k = index/(WIDTH*HEIGHT); 
index -= k*WIDTH*HEIGHT; 

j = index/WIDTH; 
index -= j*WIDTH; 

i = index/1;

その後、これは非常に簡単に任意の次元に拡張されます。たとえば、プリコンピューティングなどを実行して上記を微調整することもできますが、WIDTH*HEIGHT最適化を有効にして、コンパイラがそれを実行することを信頼します。

2の累乗に切り上げることに関する提案は、インデックスの計算を高速化するという意味で正しいですが、かなりのコストがかかります。この(それほど悪くはない)ケースでWIDTH=HEIGHT=100は、3dアレイのメモリ要件が60%(WIDTH=HEIGHT=128)増加し、GPUのメモリは一般的にすでにタイトです。アレイを2の累乗のサイズにすると、アクセスパターンによっては、バンクの競合に関する問題が発生する可能性があります。

于 2012-12-17T01:02:38.373 に答える
1

寸法が2の累乗の場合のみ。ビットマスクを使用してください。たとえば、最初のインデックスの最大値が4の場合、インデックスの最初の2ビットを取る必要があります。

于 2012-12-15T17:14:17.147 に答える