SSEで画像処理 --- 導入

下記記事にてアラインされたstd::vectorを作成する方法を記述しました。
アラインされたstd::vector - 何でもプログラミング

今回はそれを利用して、SSEで簡単な画像処理を行ってみます。

準備

今回はintrinsicを用いて実装するため、#include します。

また記述の簡便化のため、aligned_vectorを定義しておきます。

#include <intrin.h>

template<class T> using aligned_vector = std::vector<T, AlignedAllocator<T, 16>>;


ただのコピー

レジスタに転送、取得を行うだけのコードになります。

srcのサイズが16の倍数でない場合は、余りを処理するコードが必要ですが、今回は考慮していません。

aligned_vector<byte> Copy(const aligned_vector<byte>& src)
{
    aligned_vector<byte> dst(src.size());
    for (int i = 0; i < (int)src.size(); i += 16)
    {
        // レジスタに転送
        __m128i data = _mm_load_si128((__m128i*)(src.data() + i));

        // レジスタから取得
        _mm_store_si128((__m128i*)(dst.data() + i), data);
    }
    return dst;
}
f:id:any-programming:20170319005947j:plain f:id:any-programming:20170319005947j:plain


ネガポジ反転

入力データをbit反転することで実現します。

aligned_vector<byte> NegaPosi(const aligned_vector<byte>& src)
{
    aligned_vector<byte> dst(src.size());

    // 全bitが1のデータ
    __m128i c = _mm_set1_epi8((byte)0xff);
    for (int i = 0; i < (int)src.size(); i += 16)
    {
        __m128i px = _mm_load_si128((__m128i*)(src.data() + i));

        // bit反転
        px = _mm_xor_si128(px, c);

        _mm_store_si128((__m128i*)(dst.data() + i), px);
    }
    return dst;
}
f:id:any-programming:20170319005947j:plain f:id:any-programming:20170428192953j:plain


CPUの対応確認

CPUがSSEに対応しているかどうかは、__cpuidを用いて確認できます。

次のコードは一例となります。

int cpuInfo[4];
__cpuid(cpuInfo, 1);
bool sse2  = (cpuInfo[3] >> 26) & 1;
bool sse3  = (cpuInfo[2] >>  0) & 1;
bool sse41 = (cpuInfo[2] >> 19) & 1;
bool sse42 = (cpuInfo[2] >> 20) & 1;
bool avx   = (cpuInfo[2] >> 28) & 1;

詳細は下記ページを参照してください。
__cpuid, __cpuidex