【发布时间】:2015-04-18 04:15:21
【问题描述】:
这个问题似乎与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));
}
对于x的上下部分,函数的作用与https://stackoverflow.com/a/18616825/1500111中的答案基本相同。所以,我知道最小值在 __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;
}
【问题讨论】:
-
为什么取 16 条短裤的水平最小值至关重要?
-
@Zboson 为 __m128i x 取最小值将执行超过 100k 次。对于这 100K 次中的每一次,总共有 24-64 个 SIMD 添加 + MAX 以在 __m128i x 内创建短值。
-
您只是在寻找
_mm_minpos_epu16吗? -
@harold 我认为 _mm_minpos_epu16 是特定于 MS 的。我会试试看。
-
XOR 与 _mm_set1_epi16(0x8000) 如果你想找到有符号的最小值