c++ - 用于 C++/SSE 代码的高效 NEON 内在函数

标签 c++ arm sse neon intrinsics

如何高效地将以下代码片段转换为 NEON 内在函数?

C++

int diff_scale, c0, c1;
cost = (short)(cost + std::min(c0, c1) >> diff_scale));

上交所

__m128i ds = _mm_cvtsi32_si128(diff_scale);
__m128i c0 = _mm_load_si128((__m128i*)(cost));
__m128i c1 = _mm_load_si128((__m128i*)(cost + 8));
__m128i z = _mm_setzero_si128();    
_mm_store_si128((__m128i*)(cost), _mm_adds_epi16(c0, _mm_srl_epi16(_mm_unpacklo_epi8(diff, z), ds)));
_mm_store_si128((__m128i*)(cost + 8), _mm_adds_epi16(c1, _mm_srl_epi16(_mm_unpackhi_epi8(diff, z), ds)));

最佳答案

SSE 看起来应该是这样的:

int8x16_t ds = vdupq_n_s8(-diff_scale);
int16x8_t c0 = vld1q_s16(cost);
int16x8_t c1 = vld1q_s16(cost + 8);
uint8x16_t diff_ds = vshlq_u8(diff, ds);
#if defined(MAY_SATURATE)
vst1q_s16(cost,     vqaddq_s16(c0, vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(diff_ds)))));
vst1q_s16(cost + 8, vqaddq_s16(c1, vreinterpretq_s16_u16(vmovl_u8(vget_high_s8(diff_ds)))));
#else
vst1q_s16(cost,     vreinterpretq_s16_u16(vaddw_u16(vreinterpretq_u16_s16(c0), vget_low_u8(diff_ds))));
vst1q_s16(cost + 8, vreinterpretq_s16_u16(vaddw_u16(vreinterpretq_u16_s16(c1), vget_high_s8(diff_ds))));
#endif

C++ 需要对 vector 进行某种外推……也许是这样的?:

int diff_scale, c0[8], c1[8];
int32x4_t ds = vdupq_n_s32(-diff_scale);
int32x4_t c0lo = vld1q_s32(c0);
int32x4_t c0hi = vld1q_s32(c0 + 4);
int32x4_t c1lo = vld1q_s32(c1);
int32x4_t c1hi = vld1q_s32(c1 + 4);
int16x8_t c = vld1q_s16(cost);
c0lo = vshlq_s32(vaddw_s32(vminq_s32(c0lo, c1lo), vget_low_s16(c), ds);
c0hi = vshlq_s32(vaddw_s32(vminq_s32(c0hi, c1hi), vget_high_s16(c), ds);
vst1q_s16(cost, vcombine_s16(vmovn_s16(c0lo), vmovn_s16(c0hi)));

如果 diff_scale 是一个常量,则改为:

const int diff_scale = 1;
int c0[8], c1[8];
int32x4_t c0lo = vld1q_s32(c0);
int32x4_t c0hi = vld1q_s32(c0 + 4);
int32x4_t c1lo = vld1q_s32(c1);
int32x4_t c1hi = vld1q_s32(c1 + 4);
int16x8_t c = vld1q_s16(cost);
c = vcombine_s16(vshrn_n_s32(vaddw_s32(vminq_s32(c0lo, c1lo), vget_low_s16(c), diff_scale),
                 vshrn_n_s32(vaddw_s32(vminq_s32(c0hi, c1hi), vget_high_s16(c), diff_scale));
vst1q_s16(cost, c);

虽然这些看起来都可以通过更多上下文变得更简单。

关于c++ - 用于 C++/SSE 代码的高效 NEON 内在函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30314628/

相关文章:

c++ - 对 Eigen Map 稀疏对象的操作

c++ - 通过套接字 C++ 从设备接收消息

c++ - 术语 "method"是否由 C++ 标准定义?

if-statement - armv8 NEON 如果条件

visual-studio - 从 Visual Studio 交叉编译 ARM7 代码

c++ - 调用显式专用类成员模板函数时出现奇怪的编译错误

gcc - 为什么我不能使用GCC编译ARM BE8 ELF?

c++ - vector * matrix 乘积效率问题

c++ - 由 Visual Studio 2013 Update 2 和 Update 3 生成的 SSE 4 指令

image-processing - 有没有办法强制 PMULHRSW 将 0x8000 视为 1.0 而不是 -1.0?