如何有效地将以下代码段转换为NEON内在函数?
C ++
int diff_scale, c0, c1;
cost = (short)(cost + std::min(c0, c1) >> diff_scale));
SSE
__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)));
答案 0 :(得分:1)
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 ++需要对向量进行某种推断......可能是这样的吗?:
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);
尽管这些看起来都可能因为更多的背景而变得更加简单。