6

SSE-copy、AVX-copy、および std::copy のパフォーマンスに加えて。次の方法でいくつかのループをベクトル化する必要があるとします。1) AVX を介して最初のループバッチ (8 の倍数) をベクトル化します。2) ループの残りを 2 つのバッチに分割します。SSE を介して 4 の倍数であるバッチをベクトル化します。3) シリアル ルーチンを介してループ全体の残りのバッチを処理します。配列をコピーする例を考えてみましょう:

#include <immintrin.h>

template<int length,
         int unroll_bound_avx = length & (~7),
         int unroll_tail_avx  = length - unroll_bound_avx,
         int unroll_bound_sse = unroll_tail_avx & (~3),
         int unroll_tail_last = unroll_tail_avx - unroll_bound_sse>
void simd_copy(float *src, float *dest)
{
    auto src_  = src;
    auto dest_ = dest;

    //Vectorize first part of loop via AVX
    for(; src_!=src+unroll_bound_avx; src_+=8, dest_+=8)
    {
         __m256 buffer = _mm256_load_ps(src_);
         _mm256_store_ps(dest_, buffer);
    }

    //Vectorize remainder part of loop via SSE
    for(; src_!=src+unroll_bound_sse+unroll_bound_avx; src_+=4, dest_+=4)
    {
        __m128 buffer = _mm_load_ps(src_);
        _mm_store_ps(dest_, buffer);
    }

    //Process residual elements
    for(; src_!=src+length; ++src_, ++dest_)
        *dest_ = *src_;
}

int main()
{  
    const int sz = 15;
    float *src = (float *)_mm_malloc(sz*sizeof(float), 16);
    float *dest = (float *)_mm_malloc(sz*sizeof(float), 16);
    float a=0;
    std::generate(src, src+sz, [&](){return ++a;});

    simd_copy<sz>(src, dest);

    _mm_free(src);
    _mm_free(dest);
}

SSE と AVX の両方を使用するのは正しいですか? AVX から SSE への移行を避ける必要がありますか?

4

2 に答える 2

9

SSE と AVX の組み込み関数を自由に組み合わせることができます。

確認したい唯一のことは、正しいコンパイラ フラグを指定して AVX を有効にすることです。

  • GCC:-mavx
  • ビジュアルスタジオ:/arch:AVX

そうしないと、コードがコンパイルされない (GCC) か、Visual Studio の場合は次の
ような問題が発生します。

このフラグが行うことは、すべての SIMD 命令で VEX エンコーディングを使用して、上記の質問で説明した状態切り替えのペナルティを回避することです。

于 2013-08-19T18:29:20.370 に答える