我正在学习使用向量内在函数重写我的个人图像处理库来使用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]; }
但是有可能做全部添加SIMD指令?我想试试这个:
__m128i mask = (0x100<<8*(n - n16))-1;
_mm_maskmoveu_si128(xmm1, mask, (__m128i*) (B + i));
为额外的元素,但会导致未定义的行为? mask
应该保证没有访问实际上通过数组边界(我认为)。另一种方法是首先执行额外的元素,但是数组需要对齐n-n16
,这看起来不正确。
是否有另一种更优化的模式,如矢量化循环?
你可以确保你的代码长度数组总是的16个字节的倍数(实际上,虽然使用可能更少的元素),所以这绝不收尾出现。但是,在速度方面,epilog并不重要。 – Walter 2012-04-16 15:34:38