上交所的添加和转换
SSE addition and conversion
事情是这样的,如何使用SSE添加两个无符号字符数组并将结果存储在无符号短数组中。谁能给我一些帮助或提示。这就是我到目前为止所做的。我只是不知道错误在哪里。需要一些帮助
#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;
}
假设所有内容都与_Alignof(__m128i)
对齐并且数组的大小是sizeof(__m128i)
的倍数,这样的事情应该可以工作:
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)));
}
}
FWIW,NEON会更简单一些(使用vaddl_u8
和vaddl_high_u8
)。
如果您正在处理未对齐的数据,您可以使用_mm_loadu_si128
/_mm_storeu_si128
. 如果大小不是 16 的倍数,则只需在没有 SSE 的情况下完成其余部分。
请注意,这可能是您的编译器可以自动执行的操作(我尚未检查)。 您可能想尝试这样的事情:
#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
),或者你可以希望编译器足够聪明,没有编译指示提示。
相关文章:
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 我正在尝试编写将 ASCII 转换为十进制、添加并转换回 ASCII 的软件
- 转换为大写会在末尾添加一个额外的字母吗
- 尝试向 COM 对象添加另一个接口时出现静态强制转换错误 C2440
- 如何将任何值转换为对象并使用 boost::p roperty_tree json 添加成员
- 上交所的添加和转换
- Catch2 迫使我在异常中添加对 std::string 的强制转换,这会产生其他问题吗?
- C++ 如何将用户控件添加到窗体,以便我可以在面板之间转换
- 如何将整数向量转换为 2 位十六进制并按顺序添加到 c 字符串?
- C++基本的转换,然后添加用户输入
- 在范围内添加位操作和转换式的枚举 - 圣诞节探索
- C :转换为int和添加时,我的角色数组获得了奇怪的值
- 如何编写特征转换以将"const"添加到类型*
- 运算符重载:简单添加...错误 C2677:二进制"+":未找到采用类型 ___ 的全局运算符(或者不存在可接受的转换)
- C++将友元添加到模板类中以便进行类型转换
- 降低字符串字符,并在转换的大写字母前添加一个_
- 当我添加OpenGL转换时,我的图像不断消失
- 向向下转换结构添加属性值会导致分段错误
- Delphi中的类型转换指针添加
- c++转换/添加char到string