6

次のボトルネック関数があります。

typedef unsigned char byte;
void CompareArrays(const byte * p1Start, const byte * p1End, const byte * p2, byte * p3)
{
     const byte b1 = 128-30;
     const byte b2 = 128+30;
     for (const byte * p1 = p1Start; p1 != p1End; ++p1, ++p2, ++p3) {
        *p3 = (*p1 < *p2 ) ? b1 : b2;
    }
}

C++コードを SSE2 組み込み関数に置き換えたい。試してみ_mm_cmpgt_epi8ましたが、符号付き比較を使用しました。符号なしの比較が必要です。

私の問題を解決するためのトリック (SSE、SSE2、SSSE3) はありますか?

注: この場合、マルチスレッドを使用したくありません。

4

6 に答える 6

9

符号付きの値をオフセットして符号なしにする代わりに、次のようにする方が少し効率的です。

  • _mm_min_epu8p1、p2 の符号なし最小値を取得するために使用します
  • を使用して、この最小値を p2 と等しいかどうか比較します_mm_cmpeq_epi8
  • 結果のマスクは、p1 < p2 の要素では 0x00 になり、p1 >= p2 の要素では 0xff になります。
  • このマスクを_mm_or_si128とで使用_mm_andc_si128して、適切な b1/b2 値を選択できるようになりました

オフセット + 符号付き比較アプローチを使用した場合の 5 命令と比較して、これは合計 4 命令であることに注意してください。

于 2010-10-21T12:58:18.897 に答える
2

数値から 127 を引いて、_mm_cmpgt_epi8 を使用できます。

于 2010-10-21T12:13:39.550 に答える
2

はい、これは SIMD で実行できますが、マスクを作成するにはいくつかの手順が必要です。

Ruslik は正しかったと思います。各コンポーネントを 0x80 で xor して、符号付きと符号なしの比較の意味を反転させます。_mm_xor_si128 ( PXOR) はそれを取得します -- SIMD レジスターにロードする前に、静的な char 配列としてマスクをどこかに作成する必要があります。次に、_mm_cmpgt_epi8 がマスクを取得し、ビットごとの AND (例: _mm_and_si128) を使用してマスクされた移動を実行できます。

于 2010-10-21T12:19:07.013 に答える
1

はい、SSE はここでは機能しません。OpenMP を使用して、マルチコア コンピューターでこのコードのパフォーマンスを向上させることができます。

void CompareArrays(const byte * p1Start, const byte * p1End, const byte * p2, byte * p3)
{
     const バイト b1 = 128-30;
     const バイト b2 = 128+30;

     int n = p1End - p1Start;
     #pragma omp parallel for
     for (int i = 0; i < n; ++p1, ++i)
     {
        p3[i] = (p1[i] < p2[i]) ? b1 : b2;
     }
}
于 2010-10-21T12:01:35.280 に答える
-1

残念ながら、上記の回答の多くは正しくありません。3ビットワードを仮定しましょう:

符号なし: 4 5 6 7 0 1 2 3 == 符号付き: -4 -3 -2 -1 0 1 2 3 (ビット: 100 101 110 111 000 001 010 011)

Paul R の方法は正しくありません。3 > 2 かどうかを知りたいとします。min(3,2) == 2 であり、イエスを示唆しているため、この方法はここで機能します。ここで、7 > 2 かどうかを知りたいとします。値 7 は、符号付き表現では -1 であるため、min(-1,2) == -1 であり、これは、7 が 2 符号なしよりも大きくないことを誤って示唆しています。

アンドレイの方法も間違っています。7 > 2、または a = 7、および b = 2 かどうかを知りたいとします。値 7 は符号付き表現では -1 であるため、最初の項 (a > b) は失敗し、メソッドは 7 が大きくないことを示唆します。 2より。

ただし、Alexey によって修正された BJobnh による方法は正しいです。値から 2^(n-1) を引くだけです。n はビット数です。この場合、4 を引いて新しい対応する値を取得します。

古い署名: -4 -3 -2 -1 0 1 2 3 => 新しい署名: 0 1 2 3 -4 -3 -2 -1 == 新しい署名なし 0 1 2 3 4 5 6 7.

つまり、unsigned_greater_than(a,b) は signed_greater_than(a - 2^(n-1), b - 2^(n-1)) と同等です。

于 2013-07-04T00:37:03.123 に答える
-3

pcmpeqb を使用して、あなたと共に力になります。

于 2010-10-21T12:06:54.507 に答える