c - SSE 添加字符

标签 c sse

我有一个包含 0 或 1 的 16 字符 vector ,我想使用 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];

在我的应用程序中, vector 的长度远大于 16,但它始终是 16 的倍数。我使用其他 SSE 逻辑运算获得此 vector ,这些运算为我提供了良好的加速,所以我想知道我如何可以向量化这些添加。下面是完整的代码,其中 vec1、vec2 和 vec3 具有相同的长度 n(16 的倍数)并且 vector 计数为 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++;
  }
}

如有任何帮助,我们将不胜感激。

最佳答案

您可以比较整数而不是比较字节。将 atempcounts 中的四个整数加载到 SSE 寄存器中(称它们为 a4tmp4,以及下面代码中的 counts4)。然后你可以用 SSE 一次处理四个整数。这假设 counts 是一个 int32 数组。

例如,我们假设 a4 = {0,3,0,4},counts4 = {1,2,3,4},tmp4 = {5,6,7,8}。在下面的代码中 test 将为 {-1, 0, -1, 0}。从计数中减去计数得到计数 = {2,2,4,4}。 testtmp4 的逻辑与是 {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);        
}

关于c - SSE 添加字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23072866/

相关文章:

c++ - 如何使用缓存技术提高性能

c - 如何将 GtkWidgets 发送到后面或前面?

c - 在 C 中的 unsigned char 中搜索关键字

c - 这是 Vernam 密码的 C 代码,如何将数字而不是字符串作为输入消息?

visual-studio-2012 - 为什么在这个例子中预取加速不是更大?

c - 对用 C 编码的 4 个整数大小的数组进行 SSE 操作

c - 这段代码有什么不同

c - x86-64 整数向量化优化

c - 让 GCC 在整个使用内联汇编的函数中保留 SSE 寄存器

assembly - xmm 寄存器的 vbroadcastsd 相当于什么?