私は、ベクトル組み込み関数を使用して自分のパーソナル画像処理ライブラリを書き直してSIMD機能を使用する方法を学んでいます。一つの基本的な機能は、単純な「アレイ+=
」、すなわち任意の配列の長さについては任意の配列長のSIMD配列の追加
void arrayAdd(unsigned char* A, unsigned char* B, size_t n) {
for(size_t i=0; i < n; i++) { B[i] += A[i] };
}
、明白なSIMDコード(16で並ぶと仮定)であるようなものである:
size_t i = 0;
__m128i xmm0, xmm1;
n16 = n - (n % 16);
for (; i < n16; i+=16) {
xmm0 = _mm_load_si128((__m128i*) (A + i));
xmm1 = _mm_load_si128((__m128i*) (B + i));
xmm1 = _mm_add_epi8(xmm0, xmm1);
_mm_store_si128((__m128i*) (B + i), xmm1);
}
for (; i < n; i++) { B[i] += A[i]; }
は、しかし、それはすることが可能ですdo すべて SIMD命令での追加?余分な要素のための
__m128i mask = (0x100<<8*(n - n16))-1;
_mm_maskmoveu_si128(xmm1, mask, (__m128i*) (B + i));
、それは未定義の動作になります:私はこれをしようと思いましたか? mask
は、実際には配列境界を超えてアクセスが行われないことを保証する必要があります(私は思う)。代わりに最初に余分な要素を実行することですが、配列はn-n16
で整列する必要がありますが、それは正しいとは思われません。
ベクトル化されたループのような、より最適なパターンがありますか?
。しかしエピローグはスピードの点では重要ではありません。 – Walter