2017-08-07 7 views
4

は、私がrowscolsと呼ば__m256i 2つの変数を持っていること、例えば、のは言わせて、その中の値は、次のとおりです。効率的に配列にアクセスするために__m256i` `からの値を使用して - SIMD

rows: 0, 2, 7, 5, 7, 2, 3, 0 
cols: 1, 2, 7, 5, 7, 2, 2, 6 

、これらの値8点のためxy位置を表すので、この場合には、私はこれらの点を有するであろう:

p0: [0, 1], p1: [2, 2], p2: [7, 7], p3: [5, 5] 
p4: [7, 7], p5: [2, 2], p6: [3, 2], p7: [0, 6] 

Iはまた、アレイはlutと呼ばたの値を有することタイプ:

lut: [0, 1, 2, 3, ..., 60, 61, 62, 63] 

私が何をしたいのかは、rowscols変数からこれらの位置値を使用することでlut配列にアクセスし、lutアクセス値を使用して新しい__m256i値を作成することです。

私はそれを行う方法を知っている方法は、一度にlut配列1から値を読み、新しい_m256i値を作成するために_mm256_set_epi32()を使用し、サイズ8の2つのint配列にrowscols値を格納することです。

これはうまくいきますが、非常に非効率的なようです。私の質問は、それをより速く行う方法があるかどうかです。

これらの値は単なるより具体的な例のためのものであることに注意してください、とlutは、順序付けされた値またはサイズ64

感謝を持っている必要はありません!

+3

ルックアップテーブルは、常に最新のプロセッサではあまり効率的ではありません。なぜなら、それらは常にデータ依存関係を作成するからです。ルックアップテーブルをある種の算術式で置き換える方法を見つけることができれば、それはより速くすることができます。それ以外の場合は、chtzの回答を参照してください。 –

+0

あなたのコードを教えてください。あなたに最適化のヒントを与えることは可能かもしれません。 – xMRi

+1

インデックスを4ビットのチャンクにスライスし、 'pshufb'でそれらを使って16要素のLUTを得ることができます。 (例えば、http://wm.ite.pl/articles/sse-popcount.htmlのようなSSE/AVXポップカウントの実装を見てください。)しかし、あなたのインデックスが「分離可能」でないときは、下位バイトで複数のシャッフルを行い、上位バイトでブレンドする必要があります。したがって、これはO(2 ^(n-4))です。 nビット= 4ビットである。 –

答えて

5

ので

// index = (rows << 3) + cols; 
const __m256i index = _mm256_add_epi32(_mm256_slli_epi32(rows, 3), cols); 
// result = lut[index]; 
const __m256i result = _mm256_i32gather_epi32(lut, index, 4); 

は、あなたが実際にresultを使用する前に、いくつかの命令をインターリーブすることができない限り、現在のCPU上で、これがない場合があり、命令はかなり巨大な待ち時間を有する集めることに注意してくださいのようなあなたは、avx2 gather instructionを使用してソリューションを構築することができます使う価値がある。

__m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale) 

scale要因は、実際のバイト・オフセット、すなわちとして考慮され、各指標について返される値は次のとおりです:

*(const int*)((const char*) base_addr + scale*index) 

私は「ドン4の要因を説明するために

その動作に多くのユースケースがあるかどうかを知ることができます(おそらく、1バイトまたは2バイトのエントリを持つLUTにアクセスできるようにするためです)。おそらく、これはちょうど許されました.4でスケーリングすることは可能ですが、1/4または1/2でスケーリングすることはできません(誰かが本当に必要な場合)。

+0

ありがとう、それは私が欲しかったものです!ちょうど1つの事、私はなぜスケールがこの場合4である得る得ることができなかった。あなたはなぜ私に説明することができますか? –

+0

@ E.B。私は説明を追加しましたが(実際の動作の動機についてはわかりませんが) – chtz

+1

解凍/デコード機能は、Cスタイルのスケーリングされていないインデックスではなく、ベクトルのバイトオフセットを持つ可能性があります。私は、通常の目的のために使用するかもしれない命令エンコーディングの2ビットを持っていたので、1,2,4、または8倍のスケーリングの柔軟性を与えることにしたと思います。 VSIBバイトのデコードは、通常のSIBバイト( 'mov eax、[rdi + rcx * 4 + 1234]'のような通常の非収集インデックス付きアドレッシングモードで使用される)として、デコーダ(および内部uopフォーマット) )。 –

関連する問題