c++ - 使用 SSE 获取 __m128i vector 中的最小短值?

标签 c++ sse simd sse4

这个问题看起来类似于 Getting max value in a __m128i vector with SSE?但用短裤和最小值而不是整数+最大值。这就是我想到的:

typedef short int weight;

weight horizontal_min_Vec4i(__m128i x) {
    __m128i max1 = _mm_shufflehi_epi16(x, _MM_SHUFFLE(0, 0, 3, 2));
    __m128i max1b = _mm_shufflelo_epi16(x, _MM_SHUFFLE(0, 0, 3, 2));
    __m128i max2 = _mm_min_epi16(max1, max1b);
    //max2 = _mm_min_epi16(max2, x);
    max1 = _mm_shufflehi_epi16(max2, _MM_SHUFFLE(0, 0, 0, 1));
    max1b = _mm_shufflelo_epi16(max2, _MM_SHUFFLE(0, 0, 0, 1));
    __m128i max3 = _mm_min_epi16(max1, max1b);
    max2 = _mm_min_epi16(max2, max3);
    return min(_mm_extract_epi16(max2, 0), _mm_extract_epi16(max2, 4));
}

该函数基本上与 https://stackoverflow.com/a/18616825/1500111 中的答案相同。对于 x 的上部和下部。所以,我知道最小值位于 __m128i 变量 max2 的位置 0 或 4。虽然它比下面所示的无 SIMD 函数 horizo​​ntal_min_Vec4i_Plain(__m128i x) 快得多,但恐怕瓶颈是最后一行的 _mm_extract_epi16 操作。有没有更好的方法来实现这一点,以更好地加快速度?我使用的是 Haswell,因此我可以访问最新的 SSE 扩展。

weight horizontal_min_Vec4i_Plain(__m128i x) {
    weight result[8] __attribute__((aligned(16)));
    _mm_store_si128((__m128i *) result, x);
    weight myMin = result[0];
    for (int l = 1; l < 8; l++) {
        if (myMin > result[l]) {
            myMin = result[l];
        }
    }
    return myMin;
}

最佳答案

有符号和无符号比较几乎相同,只是在无符号比较中设置了最高位的范围被视为大于未设置最高位的范围,而在有符号比较中被视为较小。这意味着有符号和无符号比较可以通过以下规则相互转换:

x <s y = (x ^ signbit) <u (y ^ signbit)
x <u y = (x ^ signbit) <s (y ^ signbit)

此属性直接传输到 minmax,因此:

min_s(x, y) = min_u(x ^ signbit, y ^ signbit) ^ signbit

然后我们可以使用_mm_minpos_epu16来处理水平最小值,总共得到类似的东西

__m128i xs = _mm_xor_si128(x, _mm_set1_epi16(0x8000));
return _mm_extract_epi16(_mm_minpos_epu16(xs), 0) - 0x8000;

- 0x8000^ 0x8000 和符号扩展(提取零扩展)合二为一。

关于c++ - 使用 SSE 获取 __m128i vector 中的最小短值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28561983/

相关文章:

c++ - OpenCV查找方中心C++

C++11,使用 vs typedef,模板化

C++:使类及其某些数据成员仅在 namespace 中可用

c++ - GCC SSE 手写与生成

c - SIMD 代码运行速度比标量代码慢

vector - 支持矢量扩展的 RISC-V 仿真器

关于 C 中 SIMD 的说明

c++ - 在字符串 vector 中创建 20,000 个 MAC 地址

c++ - 如何检查我的 Linux Box 安装是否具有 SSE 指令功能?

c++ - 加载 128 位混合 float+int 数据?