从__m128i中查找最小/最大值

FiR*_*iTi 5 c++ x86 sse simd

我想使用SIMD操作在字节数组中找到最小/最大值.到目前为止,我能够通过数组并将最小/最大值存储到__m128i变量中,但这意味着我正在寻找的值与其他值混合在一起(确切地说是15个其他值).

我在这里这里找到了这些讨论的整数,这个页面用于浮点数,但我不明白如何工作_mm_shuffle*.所以我的问题是:

  1. 为了从__m128i变量中提取最小/最大字节(或无符号字节)值,我必须执行哪些SIMD操作?
  2. _mm_shuffle*如何工作?当我在网上查看"最小"文档时,我不明白.我知道它与_MM_SHUFFLE宏有关,但我没有得到这个例子.

Pau*_*l R 6

以下是横向最大值的示例uint8_t:

#include "tmmintrin.h" // requires SSSE3

__m128i _mm_hmax_epu8(const __m128i v)
{
    __m128i vmax = v;

    vmax = _mm_max_epu8(vmax, _mm_alignr_epi8(vmax, vmax, 1));
    vmax = _mm_max_epu8(vmax, _mm_alignr_epi8(vmax, vmax, 2));
    vmax = _mm_max_epu8(vmax, _mm_alignr_epi8(vmax, vmax, 4));
    vmax = _mm_max_epu8(vmax, _mm_alignr_epi8(vmax, vmax, 8));

    return vmax;
}
Run Code Online (Sandbox Code Playgroud)

最大值将在所有元素中返回.如果您需要将值作为标量,那么请使用_mm_extract_epi8.

应该相当明显如何适应min,以及签名的min/max.

  • 你可以使用PSHUFD(`_mm_shuffle_epi32`)保存一些MOVDQA指令用于最后两次shuffle,因为它们的粒度> = 4.如果你不需要结果广播,那么你可以按相反的顺序,带来高一半低于一半.这将允许使用PSHUFLW进行单词shuffle,再次利用它是一个移动+随机播放的事实.(PALIGNR就地更新其目标,因此如果没有AVX,编译器必须复制`vmax`,因此它仍然具有原始作为PMAXUB的输入). (2认同)