2

SSE(Visual Studio上)を使用してメソッドを高速化しようとしています。私はその地域の初心者です。私のメソッドで使用する主なデータ型はサイズ32のビットセットであり、主に使用する論理演算はAND演算です(_BitScanForwardはほとんど使用されていません)。SSE命令を使用して手順をスピードアップできるかどうか疑問に思いました。

これが私が今している方法です(私は完全に完了しており、結果を直接比較することはできません):

_mm_set_psを使用してオペランド(ビットセット)をロードします。ビットセットでto_ulong()を使用して、ビットセットを符号なし長整数に変換します。

__m128 v1 = _mm_set_ps(b1.to_ulong(),b2.to_ulong(),b3.to_ulong(),b4.to_ulong());
__m128 v2 = _mm_set1_ps(b.to_ulong())

これに実際のAND演算が続きます。

__m128 v3 = _mm_and_ps(v1,v2);

この時点で、2つの質問があります。

  1. 私がそれをしている方法(to_ulong()を使用してビットセットを符号なし長整数に変換する)はそれを行う良い方法ですか?SSEを使用することで得られる可能性のあるパフォーマンスの向上を損なう可能性のある大きなオーバーヘッドがあるのではないかと思います。

  2. v3を4ビットセットの形でメモリに保存する最良の方法は何ですか?_mm_storeu_ps組み込み関数を使用することを計画しています。

4

1 に答える 1

3

いくつかのこと:

  • ビットセットが基本的に32ビットintの場合は、適切な整数SIMDタイプを使用する必要があります。つまり__m128i、浮動小数点(__m128)ではありません。

  • _mm_set_XXX_mm_set_XXXマクロは比較的高価です-通常のSSE組み込み関数とは異なり、かなりの数の命令を生成できます-実行しているのが1つのAND操作だけの場合、_mm_and_XXX操作によるパフォーマンス上の利点は、操作のコストによって一掃されるだけではありません。

理想的には、配列内のビットセットの束をANDしたいだけの場合、コードは次のようになります。

const int N = 1024;

int32_t b1[N]; // 2 x arrays of input bit sets
int32_t b2[N];
int32_t b3[N]; // 1 x array of output bit sets

for (int i = 0; i < N; i += 4)
{
    __m128i v1 = _mm_loadu_si128(&b1[i]); // load input bits sets
    __m128i v2 = _mm_loadu_si128(&b2[i]);
    __m128i v3 = _mm_and_si128(v1, v2);   // do the bitwise AND
    _mm_storeu_si128(&b3[i], v3);         // store the result
}

固定マスクを使用して配列をインプレースでANDするだけの場合は、次のように簡略化できます。

const int N = 1024;

int32_t b1[N]; // input/output array of bit sets

const __m128i v2 = _mm_set1_epi32(0x12345678); // mask

for (int i = 0; i < N; i += 4)
{
    __m128i v1 = _mm_loadu_si128(&b1[i]); // load input bits sets
    __m128i v3 = _mm_and_si128(v1, v2);   // do the bitwise AND
    _mm_storeu_si128(&b1[i], v3);         // store the result
}

注:パフォーマンスを向上させるには、入出力配列が16バイトに整列されていることを確認してから、上記のように整列されていない配列ではなく_mm_load_si128/を使用してください。_mm_store_si128

于 2012-05-29T15:53:51.277 に答える