その話をちょっと書いてみようかと。
対象は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
0 件のコメント:
コメントを投稿