这个问题似乎类似于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 功能快得多 horizontal_min_Vec4i_Plain(__m128i x)
,但恐怕瓶颈是_mm_extract_epi16 operation
最后一行。有没有更好的方法来实现这一点,以获得更好的速度?我正在使用 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;
}