use*_*317 11 c++ sse max minimum avx
我有一个使用SSE的功能来做很多事情,并且分析器向我显示我用来计算水平最小值和最大值的代码部分大部分时间消耗.
我一直在使用以下实现作为最小例子:
static inline int16_t hMin(__m128i buffer) {
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m1));
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m2));
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m3));
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m4));
return ((int8_t*) ((void *) &buffer))[0];
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我需要计算16个1字节整数的最小值和最大值.
任何好的建议都非常感谢:)
谢谢
Evg*_*uev 12
SSE 4.1的指令几乎可以满足您的需求.它的名字是PHMINPOSUW,C/C++内在的_mm_minpos_epu16.它仅限于16位无符号值,不能给出最大值,但这些问题很容易解决.
_mm_srli_pi16或_mm_shuffle_epi8,然后_mm_min_epu8在偶数字节中获得8个最小值,在某个XMM寄存器的奇数字节中获得零.(这些零是由shift/shuffle指令产生的,应该保留在它们的位置之后_mm_min_epu8)._mm_minpos_epu16找到这些值中最低._mm_cvtsi128_si32.这是一个返回最多16个有符号字节的示例:
static inline int16_t hMax(__m128i buffer)
{
__m128i tmp1 = _mm_sub_epi8(_mm_set1_epi8(127), buffer);
__m128i tmp2 = _mm_min_epu8(tmp1, _mm_srli_epi16(tmp1, 8));
__m128i tmp3 = _mm_minpos_epu16(tmp2);
return (int8_t)(127 - _mm_cvtsi128_si32(tmp3));
}
Run Code Online (Sandbox Code Playgroud)
我建议两个改变:
((int8_t*) ((void *) &buffer))[0]为_mm_cvtsi128_si32.替换_mm_shuffle_epi8为_mm_shuffle_epi32/ _mm_shufflelo_epi16在最近的AMD处理器和Intel Atom上具有较低的延迟,并将节省您的内存加载操作:
static inline int16_t hMin(__m128i buffer)
{
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi32(buffer, _MM_SHUFFLE(3, 2, 3, 2)));
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi32(buffer, _MM_SHUFFLE(1, 1, 1, 1)));
buffer = _mm_min_epi8(buffer, _mm_shufflelo_epi16(buffer, _MM_SHUFFLE(1, 1, 1, 1)));
buffer = _mm_min_epi8(buffer, _mm_srli_epi16(buffer, 8));
return (int8_t)_mm_cvtsi128_si32(buffer);
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
5804 次 |
| 最近记录: |