ベクトル命令での画像処理

2014年8月31日日曜日

SIMD

t f B! P L
最近、画像処理をintrinsicで書いてる。
その話をちょっと書いてみようかと。
対象はAVXやAVX2、AVX512ね。

画像のフィルター処理だと、例えば3×3のマス目にblurマスクを掛けるとか。
ここでは単純に前後3マスの合計値としましょうか。

Cだと、
D[X] = S[x] + S[x+1] + S[x+2];
なんて書くわけですが、AVXでこれをこのまま書くと、
__m256 v1 = _mm256_loadu_ps(&S[x]);
__m256 v2 = _mm256_loadu_ps(&S[x+1]);
__m256 v3 = _mm256_loadu_ps(&S[x+2]);
__m256 v = _mm256_add_ps(_mm256_add_ps(v1, v2), v3);
_mm256_storeu_ps(&D[x], v);
みたいになっちゃって、ちょっとロードが勿体なくない?とかなるわけです。
これを、
__m256 s00, s08;
s08 = _mm256_loadu_ps(&S[xb]);
for (x = xb; x < xe; ++x) {
    s00 = s08;
    s08 = _mm256_loadu_ps(&S[x+8]);
    __m256 v1 = s00;
    __m256 v2 = s00とs08を合わせて4バイトシフト
    __m256 v3 = s00とs08を合わせて8バイトシフト
    __m256 v = _mm256_add_ps(_mm256_add_ps(v1, v2), v3);
    _mm256_storeu_ps(&D[x], v);
}
なんてできれば良い感じになるじゃないですか。
これがフィルター処理の基本形ですかね。

3×3など複数行をまたぐ処理の場合は、これをs0_00, s1_00, s2_00みたいに、
複数行をベクトルレジスタに読んでおいて、似たような処理を行います。

こうやってintrinsicで書いても早くならない関数もありますが、
大体は早くなりますし、最近intrinsicで書くのに慣れてきたので、
最初からintrinsicで書いてもいいかなとか思い始めてたりw

ラベル

AndroidTV (1) chromebook (2) DIY (4) docker (1) git (4) Ingress (4) llvm (3) MacBook (1) MVNO (1) narou (1) PS4 (2) QNAPNAS (9) SIMD (9) SmartBand (8) Ubuntu (9) VAIO (1) Windows (2) wsl (2) wsl2 (1) Xperia (20) トルネ (3) プログラム (26) ルーター (18) 音楽 (6) 家事 (2) 自炊 (2) 電子書籍 (2) 洋食 (4)

フォロワー

QooQ