首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SSE加法和转换

SSE加法和转换
EN

Stack Overflow用户
提问于 2017-06-13 10:21:23
回答 1查看 349关注 0票数 0

问题是,如何使用SSE将两个无符号字符数组相加,并将结果存储在一个无符号短数组中。有谁能给我一些帮助或提示。这就是我到目前为止所做的。我只是不知道error is..need在哪里有帮助

代码语言:javascript
复制
#include<iostream>
#include<intrin.h>
#include<windows.h>
#include<emmintrin.h>
#include<iterator>

using namespace std;

void sse_add(unsigned char * input1, unsigned char *input2, unsigned short  *output, const int N)
{   

unsigned char *op3 = new unsigned char[N];
unsigned char *op4 = new unsigned char[N];

__m128i *sse_op3 = (__m128i*)op3;
__m128i *sse_op4 = (__m128i*)op4;
__m128i *sse_result = (__m128i*)output;

for (int i = 0; i < N; i = i + 16)
{
     __m128i src = _mm_loadu_si128((__m128i*)input1);
     __m128i zero = _mm_setzero_si128();
     __m128i higher = _mm_unpackhi_epi8(src, zero);
     __m128i lower = _mm_unpacklo_epi8(src, zero);

     _mm_storeu_si128(sse_op3, lower);
     sse_op3 = sse_op3 + 1;
     _mm_storeu_si128(sse_op3, higher);
     sse_op3 = sse_op3 + 1;
    input1 = input1 + 16;

}

for (int j = 0; j < N; j = j + 16)
{
     __m128i src1 = _mm_loadu_si128((__m128i*)input2);
     __m128i zero1 = _mm_setzero_si128();
     __m128i higher1 = _mm_unpackhi_epi8(src1, zero1);
     __m128i lower1 = _mm_unpacklo_epi8(src1, zero1);

    _mm_storeu_si128(sse_op4, lower1);
    sse_op4 = sse_op4 + 1;
    _mm_storeu_si128(sse_op4, higher1);
    sse_op4 = sse_op4 + 1;
    input2 = input2 + 16;

}

__m128i *sse_op3_new = (__m128i*)op3;
__m128i *sse_op4_new = (__m128i*)op4;

for (int y = 0; y < N; y = y + 8)
{
    *sse_result = _mm_adds_epi16(*sse_op3_new, *sse_op4_new);
    sse_result = sse_result + 1;
    sse_op3_new = sse_op3_new + 1;
    sse_op4_new = sse_op4_new + 1;
}

}

void C_add(unsigned char * input1, unsigned char *input2, unsigned short *output, int N)
{
for (int i = 0; i < N; i++)
    output[i] = (unsigned short)input1[i] + (unsigned short)input2[i];

}



int main()
{
int n = 1023;
unsigned char *p0 = new unsigned char[n];
unsigned char *p1 = new unsigned char[n];
unsigned short *p21 = new unsigned short[n];
unsigned short *p22 = new unsigned short[n];
for (int j = 0; j < n; j++)
{
    p21[j] = rand() % 256;
    p22[j] = rand() % 256;
}

C_add(p0, p1, p22, n);
cout << "C_add finished!" << endl;
sse_add(p0, p1, p21, n);
cout << "sse_add finished!" << endl;

for (int j = 0; j < n; j++)
{
    if (p21[j] != p22[j])
    {
        cout << "diff!!!!!@@@@@@@" << endl;
    }
}
//system("pause");

delete[] p0;
delete[] p1;
delete[] p21;
delete[] p22;
return 0;


} 
EN

回答 1

Stack Overflow用户

发布于 2017-06-13 12:57:01

假设所有内容都与_Alignof(__m128i)对齐,并且数组的大小是sizeof(__m128i)的倍数,则应该可以使用下面的代码:

代码语言:javascript
复制
void addw(size_t size, uint16_t res[size], uint8_t a[size], uint8_t b[size]) {
  __m128i* r = (__m128i*) res;
  __m128i* ap = (__m128i*) a;
  __m128i* bp = (__m128i*) b;

  for (size_t i = 0 ; i < (size / sizeof(__m128i)) ; i++) {
    r[(i * 2)]     = _mm_add_epi16(_mm_cvtepu8_epi16(ap[i]), _mm_cvtepu8_epi16(bp[i]));
    r[(i * 2) + 1] = _mm_add_epi16(_mm_cvtepu8_epi16(_mm_srli_si128(ap[i], 8)), _mm_cvtepu8_epi16(_mm_srli_si128(bp[i], 8)));
  }
}

不过,霓虹灯会简单一点(使用vaddl_u8vaddl_high_u8)。

如果要处理未对齐的数据,可以使用_mm_loadu_si128/_mm_storeu_si128。如果大小不是16的倍数,则只能在没有SSE的情况下完成剩余部分。

请注意,这可能是您的编译器可以自动完成的事情(我还没有检查过)。您可能想要尝试这样的操作:

代码语言:javascript
复制
#pragma omp simd
for (size_t i = 0 ; i < size ; i++) {
  res[i] = ((uint16_t) a[i]) + ((uint16_t) b[i]);
}

这使用了OpenMP 4,但也有Cilk++ (#pragma simd),clang (#pragma clang loop vectorize(enable)),gcc (#pragma GCC ivdep),或者您可能只是希望编译器足够智能,而不是编译指示。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44511386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档