3

2 つの整数レジスタをペアで比較し、SSE 命令を使用して等しい要素を抽出する最良の方法は何ですか? たとえば、a = [6 4 7 2]and b = [2 4 9 2](各レジスタに 4 つの 32 ビット整数が含まれている) の場合、結果は になります[4 2 x x]。この質問の代替形式は..0101b、シャッフルに使用できる、または事前計算されたテーブルでシャッフル命令のパラメーターを検索するためのインデックスとして使用できる、等しい要素のバイナリ マスク ( ) を取得する方法です。

4

2 に答える 2

3

1 つの命令で等しい要素を抽出して移動することはできません。しかし、等しい要素のマスクは次の方法で簡単に実現できますpcmpeqd

__m128i zero = _mm_set1_epi32(0);
__m128i a = _mm_set_epi32(6, 4, 7, 2);
__m128i b = _mm_set_epi32(2, 4, 9, 2);

__m128i mask = _mm_cmp_epi32(a, b);     // mask is now 0, -1, 0, -1
mask = _mm_sub_epi32(zero, mask);       // mask is now 0,  1, 0,  1

編集: シャッフル定数を含むルックアップ テーブルのインデックスが必要な場合は、追加の操作が必要です。お気に入り

static const __m128i zero = _mm_set1_epi32(0);
static const __m128i bits = _mm_set_epi32(1,2,4,8);

__m128i a = _mm_set_epi32(6, 4, 7, 2);
__m128i b = _mm_set_epi32(2, 4, 9, 2);

__m128i bitvector = _mm_and_si128(bits, _mm_cmp_epi32(a, b));
bitvector = _mm_hadd_epi32(bitvector, bitvector);
bitvector = _mm_hadd_epi32(bitvector, bitvector);
// now a index from 0...15 is the the low 32 bit of bitvector

シャッフルを計算するためにルックアップ テーブルを使用するよりも優れたアルゴリズムが存在する可能性があり、おそらく De Bruijn 乗算を使用して直接シャッフルを計算します。OTOH 比較する int が 4 つ以上ある場合、追加の 4 つの int は1 つの追加のコストでのみ発生しますphaddd

于 2012-05-12T14:16:29.390 に答える
2

私はおそらくdrhirsch提案するものの変形を使用します:

int index = _mm_movemask_ps((__m128)_mm_cmp_epi32(a, b));

これにより、2 つの操作のみを使用してシャッフル マスクを検索する際に使用する同じインデックスが得られます。

于 2012-05-13T12:54:56.433 に答える