0

私は SSE を初めて使用し、知識が限られています。コード (C++、gcc を使用) をベクトル化しようとしていますが、これは実際には非常に単純です。unsigned int の配列があり、ある定数よりも >= または <= である要素のみをチェックします。その結果、条件に合格した要素を持つ配列が必要になります。「mm_cmpge_ps」をマスクとして使用することを考えていますが、この構成は int ではなく float で機能します!? :(

どんな提案でも、助けていただければ幸いです。

4

3 に答える 3

1

どうぞ。ここでは 3 つの関数について説明します。

最初の関数 はfoo_v1、Paul R の回答に基づいています。

2 番目の関数 はfoo_v2、今日の一般的な質問に基づいています

3 番目の関数は、foo_v3Agner Fog の vectorclass を使用します。これは、彼のクラスを使用することがいかに簡単でクリーンかを示すためだけに追加したものです。#include "vectorclass.h"クラスがない場合は、行とfoo_v3関数をコメントアウトしてください。これは、利用可能な場合は AVX2 を使用Vec8uiし、それ以外の場合は 2 つの Vec4ui に分割することを意味するため、AVX2 の利点を得るためにコードを変更する必要はありません。

#include <stdio.h>
#include <nmmintrin.h>                 // SSE4.2
#include "vectorclass.h"

void foo_v1(const int N, int *a, const int MAX_VAL, const int MIN_VAL) {
    for (int i = 0; i < N; i += 4) {
        __m128i v = _mm_load_si128((const __m128i*)&a[i]);
        __m128i vcmp0 = _mm_cmpgt_epi32(v, _mm_set1_epi32(MIN_VAL - 1));
        __m128i vcmp1 = _mm_cmplt_epi32(v, _mm_set1_epi32(MAX_VAL + 1));
        __m128i vcmp = _mm_and_si128(vcmp0, vcmp1);
        v = _mm_and_si128(v, vcmp);
        _mm_store_si128((__m128i*)&a[i], v);
    }
}

void foo_v2(const int N, int *a, const int MAX_VAL, const int MIN_VAL) {
    //if ((unsigned)(number-lower) < (upper-lower))
    for (int i = 0; i < N; i += 4) {
        __m128i v = _mm_load_si128((const __m128i*)&a[i]);
        __m128i dv = _mm_sub_epi32(v, _mm_set1_epi32(MIN_VAL));
        __m128i min_ab = _mm_min_epu32(dv,_mm_set1_epi32(MAX_VAL-MIN_VAL));
        __m128i vcmp = _mm_cmpeq_epi32(dv,min_ab);
        v = _mm_and_si128(v, vcmp);
        _mm_store_si128((__m128i*)&a[i], v);
    }
}

void foo_v3(const int N, int *a, const int MAX_VAL, const int MIN_VAL) {
    //if ((unsigned)(number-lower) < (upper-lower))
    for (int i = 0; i < N; i += 8) {
        Vec8ui va = Vec8ui().load(&a[i]);
        va &= (va - MIN_VAL) <= (MAX_VAL-MIN_VAL);
        va.store(&a[i]);
    }
}

int main() {
    const int N = 16;
    int* a = (int*)_mm_malloc(sizeof(int)*N, 16);
    for(int i=0; i<N; i++) {
        a[i] = i;
    }
    foo_v2(N, a, 7, 3);
    for(int i=0; i<N; i++) {
        printf("%d ", a[i]);
    } printf("\n");
    _mm_free(a);
}
于 2013-06-14T13:07:19.987 に答える
0

最初に確認する場所は、インテル® イントリンシックス ガイドです。

于 2013-06-14T09:34:05.027 に答える