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; }
ネガポジ反転
入力データを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; }
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