我有一个包含0或1的16个char的向量,我想使用SSE添加每个4个非重叠元素。
没有矢量化的代码的简化版本如下所示
char a[16]={1,0,0,1 ,0,0,1,0, 0,1,0,0, 0,0,0,1};
char sum1 = a[0] + a[1] + a[2] + a[3];
char sum2 = a[4] + a[5] + a[6] + a[7];
char sum3 = a[8] + a[9] + a[10] + a[11];
char sum4 = a[12] + a[13] + a[14] + a[15];
在我的应用程序中,向量的长度远大于16但它总是16的倍数。我使用其他SSE逻辑运算得到这个向量,这为我提供了一个很好的加速,所以我想知道我是怎么做的可以矢量化那些添加物。下面是完整的代码,其中vec1,vec2和vec3具有相同的长度n(16的倍数),矢量计数是n / 4。
void myfunc( const char *vec1, const char *vec2, char *vec3, int *counts, int n){
__m128i *r1 = (__m128i*)vec1;
__m128i *r2 = (__m128i*)vec2;
char *a = vec3;
char temp[16] __attribute__ ((aligned (16)));
for ( int i = 0; i < n; i+=16, r1++, r2++, a+=16 ) {
_mm_store_si128((__m128i*)a, _mm_and_si128(*r1, *r2));
_mm_store_si128((__m128i*)temp, _mm_or_si128(*r1, *r2));
char size = a[0]+a[1]+a[2]+a[3];
if( size == 0 ){
memcpy(a, temp, 4*sizeof(char));
counts[k]++;
}
k++;
size = a[4]+a[5]+a[6]+a[7];
if( size == 0 ){
memcpy(a+4, temp+4, 4*sizeof(char));
counts[k]++;
}
k++;
size = a[8]+a[9]+a[10]+a[11];
if( size == 0 ){
memcpy(a+8, temp+8, 4*sizeof(char));
counts[k]++;
}
k++;
size = a[12]+a[13]+a[14]+a[15];
if( size == 0 ){
memcpy(a+12, temp+12, 4*sizeof(char));
counts[k]++;
}
k++;
}
}
非常感谢任何帮助。
答案 0 :(得分:1)
您可以比较整数,而不是比较字节。将a
,temp
和counts
中的四个整数加载到SSE寄存器中(在下面的代码中将它们称为a4
,tmp4
和counts4
。然后,您可以使用SSE一次处理四个整数。这假设count是一个int32数组。
例如,假设a4 = {0,3,0,4},counts4 = {1,2,3,4},tmp4 = {5,6,7,8}。在下面的代码中
test
将为{-1,0,-1,0}。从计数中减去计数得出count = {2,2,4,4}。 test
与tmp4
的逻辑AND为{5,0,7,0}。将其添加到a4得到a4 = {5,3,7,4}。这应该做你想要的。
for ( int i = 0; i < n; i+=16, r1++, r2++, a+=16, k+=4 ) {
_mm_store_si128((__m128i*)a, _mm_and_si128(*r1, *r2));
_mm_store_si128((__m128i*)temp, _mm_or_si128(*r1, *r2));
__m128i a4 = _mm_load_si128((__m128i*)a);
__m128i tmp4 = _mm_load_si128((__m128i*)tmp);
__m128i counts4 = _mm_load_si128((__m128i*)&counts[k]);
__m128i test = _mm_cmpeq_epi32(_mm_set1_epi32(0), a4);
a4 = _mm_add_epi32(a4, _mm_and_si128(tmp4,test));
counts4 = _mm_sub_epi32(counts4, test);
_mm_store_si128((__m128i*)a, a4);
_mm_store_si128((__m128i*)counts, counts4);
}