0

あなたの助けを借りて、私は自分のコード (以下のサンプル) で SSE を使用してパフォーマンスを大幅に向上させましたが、AVX の 256 ビット レジスタを使用することでこの向上を改善できるかどうか疑問に思っていました。

int result[4] __attribute__((aligned(16))) = {0};
__m128i vresult = _mm_set1_epi32(0);
__m128i v1, v2, vmax;
    for (int k = 0; k < limit; k += 4) {
        v1 = _mm_load_si128((__m128i *) & myVector[positionNodeId + k]);
        v2 = _mm_load_si128((__m128i *) & myVector2[k]);
        vmax = _mm_add_epi32(v1, v2);
        vresult = _mm_max_epi32(vresult, vmax);
    }
_mm_store_si128((__m128i *) result, vresult);
return max(max(max(result[0], result[1]), result[2]), result[3]); 

そこで、3 つの質問があります。上記のかなり単純な SSE コードを AVX に変換するにはどうすればよいでしょうか? そのためにどのヘッダーをインポートする必要がありますか? また、AVX が動作するように (-sse4.1 の代わりに) gcc コンパイラにどのフラグを指定する必要がありますか?

前もって感謝します。あなたの助けに。

4

1 に答える 1

2
1.) This code can be easily converted to AVX2 (see below)
2.) #include <x86intrin.h>
3.) compile with -mavx2

AVX2 をサポートする CPU が必要です。現在、Intel Haswell プロセッサのみがこれをサポートしています。Haswell プロセッサを (まだ) 持っていないので、コードをテストできませんでした。

    int result[8] __attribute__((aligned(32))) = {0};
    __m256i vresult = _mm256_set1_epi32(0);
    __m256i v1, v2, vmax;

    for (int k = 0; k < limit; k += 8) {
        v1 = _mm256_load_si256((__m256i *) & myVector[positionNodeId + k]);
        v2 = _mm256_load_si256((__m256i *) & myVector2[k]);
        vmax = _mm256_add_epi32(v1, v2);    
        vresult = _mm256_max_epi32(vresult, vmax);
    }
    return horizontal_max_Vec8i(vresult);
    //_mm256_store_si256((__m256i *) result, vresult);
    //int mymax = result[0];
    //for(int k=1; k<8; k++) {
    //    if(result[k]>mymax) mymax = result[k];
    //}
    //return mymax;

編集: 64 個の要素しか実行していないため、水平方向の最大値の計算時間はわずかですが、取るに足らないものではないと思われます。horizontal_max_Vec4iSSE用の関数とAVX用の関数を思いつきましたhorizontal_max_Vec8i(AVX2は必要ありません)。に置き換えmax(max(max(result[0], result[1]), result[2]), result[3])てみてくださいhorizontal_max_Vec4i

int horizontal_max_Vec4i(__m128i x) {
    __m128i max1 = _mm_shuffle_epi32(x, _MM_SHUFFLE(0,0,3,2));
    __m128i max2 = _mm_max_epi32(x,max1);
    __m128i max3 = _mm_shuffle_epi32(max2, _MM_SHUFFLE(0,0,0,1));
    __m128i max4 = _mm_max_epi32(max2,max3);
    return _mm_cvtsi128_si32(max4);
}

int horizontal_max_Vec8i(__m256i x) {
    __m128i low = _mm256_castsi256_si128(x);
    __m128i high = _mm256_extractf128_si256(x,1);
    return horizontal_max_Vec4i(_mm_max_epi32(low,high));
}
于 2013-09-03T09:31:34.730 に答える