3

SSE Intrinsics を使用するように変換した Windows 用のマンデルブロ ジェネレーターを開発しました。反復の終わりを検出するために、通常の算術演算では、大なり比較を実行してブレークアウトします。SSE でこれを行うと、_mm_cmpgt_pd/_mm_cmpgt_ps を使用してベクトル全体の比較を行うことができますが、これは、気になる場合にすべて 1 の新しい 128 ビット ベクトルを書き込みます。

私の質問は、2 つのパックされた 64 INT をチェックするよりも、すべての 1 を検出するより効率的な方法はありますか? または、すべての 0 を検出する方が効率的である場合は、より少ない値で比較できます。これが私が現在持っているものです:

_m128d CompareResult = Magnitude > EarlyOut;
const __m128i Tmp = *reinterpret_cast< __m128i* >( &CompareResult );
if ( Tmp.m128i_u64[ 0 ] == Tmp.m128i_u64[ 1 ] == -1 )
{
    break;
}

より良い方法を見つけたい理由は、キャストが好きではないためですが、vTune によると、反復時間の 30% 以上がこの最後の行に費やされているためでもあります。その多くがブランチ自体にあることはわかっていますが、0 または 1 をより適切に検出することでこれを減らすことができると思います。

ありがとう

4

1 に答える 1

6

比較の結果をテストしていると仮定すると、各バイトの MS ビットを 16 ビット int として抽出し、これをテストできます。

int mask = _mm_movemask_epi8((__m128i)CompareResult);
if (mask == 0xffff)
{
    // compare results are all "true"
}

これは、SSE における SIMD 述語のより一般的な手法の 1 つの例であることに注意してください。

mask == 0xffff // all "true"
mask == 0x0000 // all "false"
mask != 0xffff // any "false"
mask != 0x0000 // any "true"
于 2013-04-15T15:21:56.347 に答える