我想找到最多两个包含8 x 16位无符号int元素的向量.
__m128i vi_A= _mm_loadu_si128(reinterpret_cast(&pSrc[0])); // 8 16-Bit Elements __m128i vi_B= _mm_loadu_si128(reinterpret_cast (&pSrc1[0])); // 8 16-Bit Elements __m128i vi_Max = _mm_max_epi16(vi_A,vi_B); //<-- Error
但这_mm_max_epi16
是一个签名的int比较,这会导致溢出.所以我尝试使用SSE4.1内在的无符号版本
vi_Max = _mm_max_epu16(vi_A,vi_B);
但我不允许使用SSE4.1内在函数.那么找到这些元素的最大值的有效方法是什么?
一种(效率有点低)的方法是将输入值偏移0x8000,然后将此偏移量添加回结果,例如:
#ifndef __SSE4_1__ inline __m128i _mm_max_epu16(const __m128i v0, const __m128i v1) { return _mm_add_epi16( _mm_max_epi16( _mm_sub_epi16(v0, _mm_set1_epi16(0x8000)), _mm_sub_epi16(v1, _mm_set1_epi16(0x8000))), _mm_set1_epi16(0x8000)); } #endif
使用gcc或clang,它为常量和四个算术指令生成一个加载指令.
_mm_xor_si128
代替_mm_add_epi16
/ _mm_sub_epi16
,意图更明确,并且可以在目标体系结构上提供更好的性能:
#ifndef __SSE4_1__ inline __m128i _mm_max_epu16(const __m128i v0, const __m128i v1) { return _mm_xor_si128( _mm_max_epi16( _mm_xor_si128(v0, _mm_set1_epi16(0x8000)), _mm_xor_si128(v1, _mm_set1_epi16(0x8000))), _mm_set1_epi16(0x8000)); } #endif