6

私はこれを達成したい:

for (int i=0;i<n,i++){
  if (x[i] > 2.0f || x[i] < -2.0f) 
     a[i] += x[i]; 
}

私はここまで行きましたが、次に何をすべきかわかりません:

__m128 P2f = _mm_set1_ps(2.0f);
__m128 M2f = _mm_set1_ps(-2.0f);
for(int i=0;i<n,i+=4){
__m128 xv = _mm_load_ps(x+i);
__m128 av = _mm_load_ps(a+i);

__m128 c1 = _mm_cmpgt_ps(xv, P2f);
__m128 c2 = _mm_cmplt_ps(xv, M2f);

__m128 or = _mm_or_ps(c1,c2);
    =???==
av = _mm_add_ps(av, xv);
_mm_store_ps(a+i, av);
}
4

2 に答える 2

4

あなたは近いです:

const __m128 P2f = _mm_set1_ps(2.0f);
const __m128 M2f = _mm_set1_ps(-2.0f);
for (int i = 0; i < n; i += 4)
{
    __m128 xv = _mm_load_ps(x + i);
    __m128 av = _mm_load_ps(a + i);

    __m128 c1v = _mm_cmpgt_ps(xv, P2f);
    __m128 c2v = _mm_cmplt_ps(xv, M2f);

    __m128 cv = _mm_or_ps(c1v, c2v);

    xv = _mm_and_ps(xv, cv);

    av = _mm_add_ps(av, xv);

    _mm_store_ps(a + i, av);
}

秘訣は、2つの比較結果を取得し、この結合された結果をマスクとして使用して、ビット演算ORを使用してテストに合格しなかったX値をゼロにすることです。AND次に、マスクされたXベクトルを追加します。これにより、マスクに従ってAの各要素に0または元のX値が追加されます。


以下のコメントに記載されている代替バージョンの場合は、次のようにします。

const __m128 P2f = _mm_set1_ps(2.0f);
const __m128 M2f = _mm_set1_ps(-2.0f);
for (int i = 0; i < n; i += 4)
{
    __m128 xv = _mm_load_ps(x + i);
    __m128 av = _mm_load_ps(a + i);

    __m128 c1v = _mm_cmpgt_ps(xv, P2f);
    __m128 c2v = _mm_cmplt_ps(xv, M2f);

    __m128 cv = _mm_or_ps(c1v, c2v);

    xv = _mm_and_ps(P2f, cv); // <<< change this line to get a[i] += 2.0f
                              //     instead of a[i] += x[i]

    av = _mm_add_ps(av, xv);

    _mm_store_ps(a + i, av);
}

以下のコメントで言及する3番目のバージョン(a[i] *= 2.0)の場合、少し注意が必要ですが、式をa[i] += a[i]次のように考えることで実行できます。

const __m128 P2f = _mm_set1_ps(2.0f);
const __m128 M2f = _mm_set1_ps(-2.0f);
for (int i = 0; i < n; i += 4)
{
    __m128 xv = _mm_load_ps(x + i);
    __m128 av = _mm_load_ps(a + i);

    __m128 c1v = _mm_cmpgt_ps(xv, P2f);
    __m128 c2v = _mm_cmplt_ps(xv, M2f);

    __m128 cv = _mm_or_ps(c1v, c2v);

    xv = _mm_and_ps(av, cv)); // <<< change this line to get a[i] *= 2.0f (a[i] += a[i])
                              //     instead of a[i] += x[i]

    av = _mm_add_ps(av, xv);

    _mm_store_ps(a + i, av);
}
于 2013-03-12T21:52:57.513 に答える
1

ゼロに関する対称性を利用して、単一の比較のみを行う必要があるというポールの優れた回答に追加するだけです。

const __m128 absMask = (__m128)_mm_set1_epi32(0x7fffffff);
const __m128 two = _mm_set1_ps(2.0f);

for (int i = 0; i < n; i += 4) {
    __m128 xv = _mm_load_ps(x + i);
    __m128 av = _mm_load_ps(a + i);
    __m128 absxv = _mm_and_ps(xv, absMask); // |x|
    __m128 mask = _mm_cmpgt_ps(absxv, two); // |x| > 2 ?
    xv = _mm_and_ps(xv, cv);                // |x| > 2 ? x : 0
    av = _mm_add_ps(av, xv);                // |x| > 2 ? a + x : a + 0
    _mm_store_ps(a + i, av);
}
于 2013-03-12T23:04:34.680 に答える